我有一个简单的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以这种非直观的方式行事?
答案 0 :(得分:2)
这是正确的,它不是不直观的(虽然可能不是很明显)。
它与其他语言中的变量的工作方式相同。
试试这个shell示例。
$ var=aaa
$ echo "${var}"
aaa
$ ev() { echo "${var}"; }
$ ev
aaa
$ var+=bbb
$ ev
aaabbb
获取变量的值,因为它在您使用时存在。
make中tgt: prereq
和@recipe line
之间的差异在于评估线条时。
GNU Make Manual在3.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))
不要忘记使用食谱线标签。