立即变量分配

时间:2015-05-12 15:54:06

标签: variables makefile

我在make文件中立即分配变量时遇到问题,使用:=与分配了+ =的变量结合使用。例如:

VAR := a
VARS += $(VAR)

rule1:
        echo "$(VARS)"

VAR := b
VARS += $(VAR)

rule2:
        echo "$(VARS)"

当我运行make时,无论规则如何,都会打印" b b"。令我感到困惑的是,如果我使用以下make文件:

VARS += a

rule1:
        echo "$(VARS)"

VARS += b

rule2:
        echo "$(VARS)"

它打印" a b"无论规则如何,这都是我所期望的。根据制作手册https://www.gnu.org/software/make/manual/html_node/Reading-Makefiles.html

  

我们说如果在第一次发生时就会立即扩展   阶段:在这种情况下,make将扩展任何变量或函数   解析了作为makefile的构造部分。

     

立即:=立即

     

立即+ =延迟或立即

     

对于追加运算符'+ =',考虑右侧   如果变量先前已设置为简单变量,则立即生效   (':='或':: ='),否则延期。

如果:=实际上是立即的,并且立即变量在解析时被扩展,正如make手册所说的那样,那么我希望这些文件具有相同的行为。为什么这不是真的?我认为这可能是make文档中的错误或make中的错误。

1 个答案:

答案 0 :(得分:3)

您缺少的是配方行(规则体)在解析时不会扩展(最多可以部分扩展,考虑自动变量,如$@$^例如)而是在规则执行时扩展。

您在上面引用的手册部分的最后一部分How make Reads a Makefile中介绍了这一点:

  

规则定义

     

规则总是以相同的方式扩展,无论形式如何:

immediate : immediate ; deferred
   deferred
     

也就是说,目标和先决条件部分会立即展开,并且用于构造目标的配方始终是延迟的。对于显式规则,模式规则,后缀规则,静态模式规则和简单的先决条件定义,此一般规则适用。

因此,如果您认为分配是正确的,那么您错过了配方上下文中的扩展不是。因此,在每个顶级任务完成后,配方始终扩展

此外,对于第一个示例,您从未将VARS设置为简单扩展,因此默认为递归扩展,因此在您编写时:

VAR := a
VARS += $(VAR)

并认为你在做:

VAR := a
VARS += a

你不是。

您实际上正在执行字面编写并将$(VAR)存储在$(VARS)的值中,以便在完成时$(VARS)的值为$(VAR) $(VAR)然后,自然,扩展为b b

如果您将VARS :=添加到第一个makefile示例的顶部,您将获得a b,因为那时VARS只是展开并展开$(VAR) +=分配时间)。