给出这个 Makefile:
.PHONY: plus cond set
plus: export FOO += plus
plus:
@echo plus is $(FOO)
cond: export FOO ?= cond
cond: plus
@echo cond is $(FOO)
set: export FOO := set
set: cond
@echo set is $(FOO)
我期望
make set
输出:
plus is set plus
cond is set
set is set
但我得到的是:
plus is cond plus
cond is cond
set is set
plus is cond plus
这一事实告诉我,我认为特定于目标的变量在先决条件的特定于目标的变量的范围内是正确的。那么为什么条件赋值 FOO ?= cond
不尊重 FOO
已经设置的情况呢?这是一个错误吗?
无论它是否是一个错误,并且在不使用
.SECONDEXPANSION
的情况下,我如何获得所需的行为,即make cond
输出cond is cond
但make set
给我cond is set
?
它被归档为错误,但已成为增强请求。我认为这是一个错误。
条件变量的工作方式是,变量的“条件性”是在变量被赋值时(在直接上下文中)确定的,而不是在变量扩展时确定的。当我们评估“lib: TARGET ?= Two”中的变量赋值时,我们还没有范围内“all”目标的继承,因为直到 make 实际运行 makefile 时才会发生这种情况。因此,在我们评估“条件性”时,范围内没有其他价值。
现在实际上我撒了一点谎,因为即使您将“TARGET = global”设置为全局设置(当设置目标特定变量时它显然在范围内),结果仍然是“二”。这是因为条件性仅查看在同一范围内分配的变量。
在变量名称并不重要(它不会进一步传播)的简单情况下,您可以通过以下任一方式使用显式条件来修复它:
cond: export FOO_cond = $(or $(FOO),cond)
cond: plus
@echo cond is $(FOO_cond)
@echo cond is $(or $(FOO),cond)
但是,如果您希望
FOO
进一步传播,例如,这些都不是解决方案cond
的先决条件,如 plus
。到目前为止,我发现的最好的解决方法是引入另一个目标:
cond: export FOO = cond
cond: cond_w_override
cond_w_override: plus
@echo cond is $(FOO)
set: export FOO := set
set: cond_w_override
@echo set is $(FOO)
但请注意,现在您必须选择正确的先决条件,具体取决于您是否要覆盖
cond
的 FOO
的默认值。