GNU做出奇怪的行为

时间:2015-01-27 10:58:29

标签: gnu-make

我有一个简单的Makefile:

VAR := aaa
include a.inc
VAR += bbb

和a.inc

some_target: $(VAR)
        @echo "refer to automatic var $^"
        @echo "refer to VAR $(VAR)"

aaa:
bbb:

当我跑步时,我看到一个奇怪的印刷品:

refer to automatic var aaa
refer to VAR aaa bbb

似乎GNU在包含时刻在先决条件中替换$(VAR),但在稍后的某个时刻调试打印中的$(VAR)。这是正确的行为吗?为什么GNU以这种非直观的方式行事?

3 个答案:

答案 0 :(得分:2)

这是正确的,它不是不直观的(虽然可能不是很明显)。

它与其他语言中的变量的工作方式相同。

试试这个shell示例。

$ var=aaa
$ echo "${var}"
aaa
$ ev() { echo "${var}"; }
$ ev
aaa
$ var+=bbb
$ ev
aaabbb

获取变量的值,因为它在您使用时存在。

make中tgt: prereq@recipe line之间的差异在于评估线条时。

GNU Make Manual3.7 How make Reads a Makefile中论述了这一点。具体而言,对于这种情况,您需要最后一个子部分Rule Definition

答案 1 :(得分:2)

使用=(而不是:=)设置的变量在使用时会展开。

首先运行make时,它会解析makefile并确定目标和先决条件。此时VAR将扩展到其当前值。

然后它运行第一个目标,并执行该目标的配方,此时VAR再次展开,但为其新值。

答案 2 :(得分:1)

GNU make在2遍中评估makefile。除食谱外,一切都在第一次评估时进行评估。配方在第二次通过时进行评估。因此,您在$(VAR)的配方中对some_target的引用会在第二次传递时进行评估,即在+= bbb附加到VAR之后,该事件发生在第一次通过。

要实现您想要的行为,您可以使用以下技术来定义规则:

define rule
some_target: $(VAR)
    @echo "refer to automatic var $^"
    @echo "refer to VAR $(VAR)"
endef
$(eval $(rule))

不要忘记使用食谱线标签。