makefile:是否可以让规则调用规则进程继承变量值



我想在另一个规则中调用规则。因此,我尝试编写以下测试makefile

var = 11
a:
echo $(var)
$(eval var=22)
echo $(var)
$(MAKE) b
b:
echo $(var)

问题是,当我运行make a时,$(MAKE) b仍然会输出11,但我希望它应该是22。所以我的问题是:有没有一种方法可以跨不同的规则继承变量值?

如果你在同一个文件中,你应该完全避免这种情况——不要把make看作是某种"高级脚本工具"。事实并非如此。它是一种构建文件的工具,在尊重所有依赖关系的同时完成最少的必要工作,因此,您的工作是使用先决条件准确地说明这些依赖关系。

看看这个例子和它的作用:

var = 11
printvar:
echo $(var)
setvar:
$(eval var=22)
a:  printvar setvar b
b:  
echo $(var)
.PHONY: a b printvar setvar

请注意,none这些规则都不会创建实际的文件。通常,规则应该创建其目标,如果没有,则必须将其列为特殊目标.PHONY的先决条件,以使其知道这一点。这应该是一个例外——make的主要用途是,它可以通过比较先决条件的时间戳和目标的时间戳来决定是否必须应用规则。只有当存在比目标更新的先决条件时,才会执行规则的配方。对于.PHONY规则,每次都必须执行配方。


当谈到递归make时,这个问题会更有意义。将变量从父make进程传递给子进程的一种简单方法是将其导出到环境中。在您的示例中,可以使用以下方法:

var ?= 11      # only set var if it doesn't have a value yet
export var     # export var to the environment, so it's available to child make
a:
echo $(var)
$(eval var=22)
echo $(var)
$(MAKE) b
b:
echo $(var)
.PHONY: a b

当然,只有当您有不同的Makefile时,这在实践中才有意义,所以不要只调用$(MAKE) b,而是例如$(MAKE) -C [some subdir] b。IMHO,递归make应该避免,因为使用递归make很难获得正确的依赖关系。但无论如何,这是可行的。

当您从a的配方中再次调用make时,您实际上启动了一个新的make进程,该进程将再次解析您的makefile,因此,它的第一行将值11分配给变量var。接下来,第二次make调用构建目标b并返回11…

如果要将变量值传递给sub-make调用,可以在命令行中使用make VAR=VALUE ...语法进行。在您的示例中,您可以,例如:

$ cat Makefile
var = 11
a:
echo $(var)
$(eval var=22)
echo $(var)
$(MAKE) var=$(var) b
b:
echo $(var)
$ make a
echo 11
11
echo 22
22
make var=22 b
make[1]: Entering directory 'foo'
echo 22
22
make[1]: Leaving directory 'foo'

它之所以有效,是因为默认情况下,在命令行上指定的变量会覆盖makefile中的定义(请参阅make手册)。

这个命令行赋值可能看起来很奇怪,因为它似乎将变量var的值赋值给了它自己,但它没有。它将第一个(顶部)make调用的变量var的当前值分配给子make调用变量var

是。IMHO您应该恢复顺序:"a"取决于"b"var=11b: var=22b: aecho b:$(var)a:echo:a:$(var)

最新更新