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

时间:2017-10-23 01:54:32

标签: makefile

我想在其他规则中调用规则。所以我尝试编写以下测试makefile

var = 11

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

b:
    echo $(var)

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

3 个答案:

答案 0 :(得分:1)

如果你在同一个文件中,你应该完全避免这种情况 - 停止将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。应该避免使用恕我直言,递归make ,因为使用递归make非常难以使依赖关系正确。但无论如何,这会奏效。

答案 1 :(得分:1)

当你从a的配方再次调用make时,你真的启动了一个新的make进程,它将再次解析你的makefile,因此,它的第一行,它将值11赋给变量var。接下来,第二个make调用构建目标b并回显11 ...

如果要将变量值传递给子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 manual)。

此命令行分配可能看起来很奇怪,因为它似乎将变量var的值分配给自身,但事实并非如此。它将第一个(顶部)make调用的变量var的当前值分配给子make调用的变量var

答案 2 :(得分:0)

是。恕我直言,你应该恢复顺序:'a'取决于'b'     var = 11     b:var = 22     b:a         echo b:$(var)     A:         echo:a:$(var)