常见的GNU makefile目录path

我正在尝试通过使用通用的makefile来合并一些构build信息。 我的问题是,我想从不同的子目录级别使用该生成文件,这使得工作目录值( pwd )不可预知。 例如:

 # Makefile.common TOP := $(shell pwd) COMPONENT_DIR := $(TOP)/component COMPONENT_INC := $(COMPONENT_DIR)/include COMPONENT_LIB := $(COMPONENT_DIR)/libcomponent.a 

如果我从一个子目录中包含Makefile.common ,就像这样, $(TOP)目录是不正确的,其他的都是这样:

 # other_component/Makefile include ../Makefile.common # $(COMPONENT_LIB) is incorrectly other_component/component 

Makefile.common使用自己的目录path,而不是更多变幻的pwd ,最好的办法是什么?

您应该可以使用MAKEFILE_LISTvariables ,如下所示:

 # This must be the first this in Makefile.common TOP := $(dir $(lastword $(MAKEFILE_LIST))) 

从文档:

由于make读取各种makefile,包括从MAKEFILESvariables,命令行,默认文件或include指令获取的任何makefile,它们的名称将自动附加到MAKEFILE_LISTvariables。 在make开始parsing之前,它们被添加。 这意味着如果makefile所做的第一件事是检查这个variables中的最后一个单词,它将是当前makefile的名字。 一旦当前的makefile使用include,最后的单词将是刚刚包含的makefile。

这是不好的样式,因为它增加了另一个依赖项(即实时path二进制)。 根据您的使用情况,这可能是可以接受的。

 ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) 

如果你没有安装realpath:

 $ sudo apt-get install realpath # on debian and derivatives 

编辑 :一定要使用:=而不是=因为后者导致使用后期绑定和MAKEFILE_LIST可能已经改变,由于后来包括。

你有没有尝试过:

 # Makefile.common TOP ?= $(shell pwd) COMPONENT_DIR := $(TOP)/component COMPONENT_INC := $(COMPONENT_DIR)/include COMPONENT_LIB := $(COMPONENT_DIR)/libcomponent.a # other_component/Makefile TOP ?= .. include ../Makefile.common 

如果已经设置,使用?=构造将保持TOP不被重新定义。 在调用make时,可以根据树中的位置将其设置为适当的值。 我承认自从使用了GNU make之后已经有一段时间了,所以这可能不起作用,或者可能需要一些调整。

我的解决scheme

 cwd := $(shell readlink -en $(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST)))) 

当你在/opt/other/path/subdir这也适用于make -f /opt/some/dir/Makefile调用。

只需在common.mk写下常用的东西。 然后把common.mk是Make在遇到包含common.mk语句时查找的默认文件夹。

查看常见文件夹的帮助查找。 您也可以将common.mk放在您的home文件夹中,然后从任何文件夹中键入make -I$HOME

在每个子文件夹的Makefile里面,你只需要做

 include common.mk 

就这些。 无需担心path和移动的东西。