我正在尝试使用通用的makefile来整合一些构建信息。我的问题是我想从不同的子目录级别使用该makefile,这使得工作目录值(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
使用自己的目录路径而不是更加善变pwd
的最佳方式是什么?
答案 0 :(得分:68)
您应该可以使用MAKEFILE_LIST variable,如下所示:
# This must be the first line in Makefile.common
TOP := $(dir $(lastword $(MAKEFILE_LIST)))
来自文档:
当make读取各种makefile时,包括从MAKEFILES变量,命令行,默认文件或include伪指令获得的任何makefile,它们的名称将自动附加到MAKEFILE_LIST变量中。它们在make开始解析之前添加。这意味着如果makefile执行的第一件事是检查此变量中的最后一个单词,它将是当前makefile的名称。但是,一旦当前的makefile使用了include,最后一个单词将是刚刚包含的makefile。
答案 1 :(得分:9)
这不是好的样式,因为它添加了另一个依赖项(即realpath二进制文件)。根据您的使用情况,这可能是可以接受的。
ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
如果您没有安装realpath:
$ sudo apt-get install realpath # on debian and derivatives
编辑:请务必使用:=
代替=
,因为后者导致make
使用后期绑定,而MAKEFILE_LIST
可能会由于后来的包括而改变了。
答案 2 :(得分:2)
你有没有尝试过:
# 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,则使用?=构造将使TOP不被重新定义。您可以根据调用make时树中的位置将其设置为适当的值。我承认自从我使用GNU make以来已经有一段时间了,所以这可能不起作用或者可能需要一些调整。
答案 3 :(得分:2)
我的解决方案:
cwd := $(shell readlink -en $(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))))
当您进入make -f /opt/some/dir/Makefile
。
/opt/other/path/subdir
等来电
答案 4 :(得分:1)
只需在common.mk
中编写常见内容即可。然后把common.mk放在Make遇到include common.mk语句时查找的默认文件夹中。
查看常用文件夹的帮助查找。您也可以将common.mk放在主文件夹中,然后从任何文件夹中键入make -I$HOME
。
在每个子文件夹的Makefile中,您只需执行
include common.mk
就是这样。无需担心路径和移动物体。