Makefile 通用GNU生成文件目录路径
我正试图通过使用一个通用的makefile来整合一些构建信息。我的问题是我想使用来自不同子目录级别的makefile,这使得工作目录值(Makefile 通用GNU生成文件目录路径,makefile,Makefile,我正试图通过使用一个通用的makefile来整合一些构建信息。我的问题是我想使用来自不同子目录级别的makefile,这使得工作目录值(pwd)不可预测。例如: # Makefile.common TOP := $(shell pwd) COMPONENT_DIR := $(TOP)/component COMPONENT_INC := $(COMPONENT_DIR)/include COMPONENT_LIB := $(COMPONENT_DIR)/libcomponent.a 如果我包含
pwd
)不可预测。例如:
# Makefile.common
TOP := $(shell pwd)
COMPONENT_DIR := $(TOP)/component
COMPONENT_INC := $(COMPONENT_DIR)/include
COMPONENT_LIB := $(COMPONENT_DIR)/libcomponent.a
如果我包含子目录中的Makefile.common
,如是,则$(顶部)
目录不正确,其他所有内容如下:
# other_component/Makefile
include ../Makefile.common
# $(COMPONENT_LIB) is incorrectly other_component/component
获取Makefile.common
的最佳方法是使用它自己的目录路径,而不是更易变的pwd
?您是否尝试过:
# 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了,所以这可能不起作用或者需要一些调整。您应该能够使用,如下所示:
# This must be the first line in Makefile.common
TOP := $(dir $(firstword $(MAKEFILE_LIST)))
从文件中:
当make读取各种MAKEFILE时,包括从makefiles变量、命令行、默认文件或include指令获得的任何MAKEFILE文件,它们的名称将自动附加到MAKEFILE_列表变量。它们是在make开始解析它们之前添加的。这意味着,如果makefile要做的第一件事是检查这个变量中的最后一个单词,那么它将是当前makefile的名称。但是,一旦当前makefile使用了include,最后一个字就是刚刚包含的makefile
这不是一种好的样式,因为它添加了另一个依赖项(即realpath二进制文件)。根据您的用例,这可能是可以接受的
ROOT_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
如果未安装realpath:
$ sudo apt-get install realpath # on debian and derivatives
编辑:请确保使用
:=
而不是=
,因为后者会导致make
使用后期绑定,并且MAKEFILE\u列表可能由于以后的包含而发生更改。在common.mk
中编写常用内容。然后将common.mk放在默认目录中,在遇到include语句时进行查找。有关常见目录的信息,请参阅查找
您还可以将common.mk放在自定义目录中,然后键入make-I customdir
在每个子文件夹的Makefile中,您可以
include common.mk
仅此而已。无需担心路径和移动问题。我的解决方案:
cwd := $(shell readlink -en $(dir $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))))
这也适用于调用make-f/opt/some/dir/Makefile
,当您的in/opt/other/path/subdir同意时,这将起作用。我希望有一种方法可以做到这一点,它不需要在makefile部分进行准备(除了包含),但这肯定是一个很好的回退。这在我的dev box上运行得非常好,但我意识到目标机器运行的是Make3.79,Make3.80中添加了MAKEFILE_列表功能:MAKEFILE_列表似乎不包含完整路径,而只包含相对路径。这是事实,但如果它对任何人都有帮助的话:下面是一个片段,它将为您提供一个绝对路径,但不依赖于realpath(基于此答案和):TOP:=$(dir$(CURDIR)/$(word$(words$(words$(MAKEFILE_列表))$(MAKEFILE_LIST))
Xavier,你应该把它作为一个答案,而不是一个评论。事实是好的(甚至是鼓励的),这是一个活生生的网站。这就是我给出绝对路径的好方法:TOP:=$(abspath$(dir$(lastword$(MAKEFILE_LIST))
$(abspath…
是在GNU make 3.81中引入的(2006年4月1日)与$(lastword…)同时发布
根据我的快速网络搜索。Xavier Holt的解决方案适用于GNU make的旧版本。我应该注意的是,这是建立在上面JesperE的示例表单上的。但是,它提供了一个在+1基础上构建的绝对路径。此解决方案是完美的,可移植的。我已经在Unix和Windows/Cygwin上成功地测试了它。另外请注意able/DIRECTIONAL。在我看来,realpath
是make
的一个内置函数——不是对已安装的二进制文件()的依赖。这里使用的是gnu make内置函数。另外,与shell dirname
不同,可能更容易使用dir
内置函数。这很有趣,但对于复杂的项目和部署来说太幼稚了。