我试图弄清楚以下行为是 Make 中的错误,还是故意成为设计的一部分(如果是这样,我在任何地方都找不到它记录(。 它发生在我尝试过的旧版本的GNU Make和新版本中。
简而言之,行为是配方中计算名称变量的评估发生在调用配方时,而不是文件中定义配方的位置,即使变量只是简单地扩展(":=",而不是递归扩展的"="((并不是说我希望这很重要(。
重现代码:
a_name := alpha
b_name := beta
AB := a
target1 : $($(AB)_name)
echo $^
echo $($(AB)_name)
alpha : ;
beta : ;
AB := b
target2 : target1 ;
调用make target2
后
我期望的输出:
阿尔法阿尔法
实际输出:
阿尔法贝塔
你需要阅读 3.7 如何使读取生成文件来理解你所看到的内容。
阅读后,您将认识到关键部分是:
Rule Definition
A rule is always expanded the same way, regardless of the form:
immediate : immediate ; deferred
deferred
从这个角度来看,你会看到:
target1 : $($(AB)_name)
在阶段 1 中读取生成文件时,会立即展开。此时AB
的定义是a
,所以$($(AB)_name)
展开到$(a_name)
,然后到alpha
。
因此,这一alpha
是$^
将一劳永逸地实现的先决条件。扩展,延迟,在第 2 阶段,在配方中,因此:
echo $^
在食谱中会呼应alpha
.
食谱中的下一行:
echo $($(AB)_name)
在整个生成文件之后的第 2 阶段,也会延迟扩展已被阅读。在这一点上,AB
拥有其最终定义来自第一阶段,这是b
,所以这里$($(AB)_name)
扩展到$(b_name)
,然后beta
.所以食谱的这一行呼应beta
.