立即变量赋值
Make Immediate Variable Assignment
我在 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:
We say that expansion is immediate if it happens during the first
phase: in this case make will expand any variables or functions in
that section of a construct as the makefile is parsed.
immediate := immediate
immediate += deferred or immediate
For the append operator, ‘+=’, the right-hand side is considered
immediate if the variable was previously set as a simple variable
(‘:=’ or ‘::=’), and deferred otherwise.
如果 := 实际上是立即变量,并且立即变量在解析时被扩展,正如 make 手册所说的那样,那么我希望这些 make 文件具有相同的行为。为什么那不是真的?我认为这要么是 make 文档中的错误,要么是 make 中的错误。
你缺少的一点是配方行(规则的主体)在解析时没有扩展(最多它们可以部分扩展,想想像 $@
和 [=14 这样的自动变量=] 例如),而是在规则执行时展开。
这在您上面引用的手册部分的最后一节中有所介绍 How make
Reads a Makefile:
Rule Definition
A rule is always expanded the same way, regardless of the form:
immediate : immediate ; deferred
deferred
That is, the target and prerequisite sections are expanded immediately, and the recipe used to construct the target is always deferred. This general rule is true for explicit rules, pattern rules, suffix rules, static pattern rules, and simple prerequisite definitions.
因此,虽然您认为分配是立即的是正确的,但您错过了配方上下文中的扩展 不是 。所以食谱总是扩展在每个顶级分配完成后。
此外,对于第一个示例,您从未将 VARS
设置为简单扩展,因此它默认为递归扩展,因此当您编写时:
VAR := a
VARS += $(VAR)
并认为你在做:
VAR := a
VARS += a
你不是。
你实际上是在做字面上写的事情,并将 $(VAR)
存储在 $(VARS)
的值中,这样当 make 完成时 $(VARS)
的值就是 $(VAR) $(VAR)
然后,自然会扩展为 b b
.
如果您将 VARS :=
添加到第一个 makefile 示例的顶部,您将得到您期望的 a b
(从那时起 VARS
被简单地扩展并扩展 $(VAR)
在 +=
作业时间)。
我在 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:
We say that expansion is immediate if it happens during the first phase: in this case make will expand any variables or functions in that section of a construct as the makefile is parsed.
immediate := immediate
immediate += deferred or immediate
For the append operator, ‘+=’, the right-hand side is considered immediate if the variable was previously set as a simple variable (‘:=’ or ‘::=’), and deferred otherwise.
如果 := 实际上是立即变量,并且立即变量在解析时被扩展,正如 make 手册所说的那样,那么我希望这些 make 文件具有相同的行为。为什么那不是真的?我认为这要么是 make 文档中的错误,要么是 make 中的错误。
你缺少的一点是配方行(规则的主体)在解析时没有扩展(最多它们可以部分扩展,想想像 $@
和 [=14 这样的自动变量=] 例如),而是在规则执行时展开。
这在您上面引用的手册部分的最后一节中有所介绍 How make
Reads a Makefile:
Rule Definition
A rule is always expanded the same way, regardless of the form:
immediate : immediate ; deferred deferred
That is, the target and prerequisite sections are expanded immediately, and the recipe used to construct the target is always deferred. This general rule is true for explicit rules, pattern rules, suffix rules, static pattern rules, and simple prerequisite definitions.
因此,虽然您认为分配是立即的是正确的,但您错过了配方上下文中的扩展 不是 。所以食谱总是扩展在每个顶级分配完成后。
此外,对于第一个示例,您从未将 VARS
设置为简单扩展,因此它默认为递归扩展,因此当您编写时:
VAR := a
VARS += $(VAR)
并认为你在做:
VAR := a
VARS += a
你不是。
你实际上是在做字面上写的事情,并将 $(VAR)
存储在 $(VARS)
的值中,这样当 make 完成时 $(VARS)
的值就是 $(VAR) $(VAR)
然后,自然会扩展为 b b
.
如果您将 VARS :=
添加到第一个 makefile 示例的顶部,您将得到您期望的 a b
(从那时起 VARS
被简单地扩展并扩展 $(VAR)
在 +=
作业时间)。