通过计算名称的简单扩展变量的值在配方中与在配方外部是不同的



我试图弄清楚以下行为是 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.

最新更新