食谱中变量的早期扩展
Early Expansion of Variables in Recipes
我知道GNU Make中两种变量的区别
我目前正在编写一个构建系统,其中某些变量在子目录(例如 VERSION)中定义。为了让子目录作者的生活更简单,我不想强迫他们使他们的变量全局唯一。我也想避免递归制作。
我现在的问题是我需要一种方法来提供一些简单的库目标,以便在定义目标时扩展这些公共变量。举个简单的例子:
FOO := Bar
PHONY: $(FOO)
$(FOO):
@echo $(FOO)
FOO := Definitely not Bar
PHONY: test2
test2: Bar
@echo $(FOO)
我需要 make test2
的输出是
Bar
Definitely not Bar
当然,我可以在第一条规则中使用一个临时变量来强制扩展 FOO,但是我需要一种方法来可靠地定义一个新的临时变量。有没有办法扩大目标,例如使用评估?
编辑:使示例代码中 FOO 的奇怪扩展更加清晰。
看起来你只是想要 target-specific variables,
例如
生成文件
.PHONY: Bar test2
Bar: FOO := Bar
Bar:
@echo $(FOO)
test2: FOO := Definitely not Bar
test2: Bar
@echo $(FOO)
运行方式如下:
$ make test2
Bar
Definitely not Bar
(请注意,.PHONY
与所有特殊目标一样,以 .
开头)
您可以使用 $(eval …)
编写一些很好的功能代码(双关语)。您可以编写闭包,并决定什么时候扩展什么。
考虑这个变量:
define rule =
PHONY: ${FOO}
${FOO}:
@echo $$@ ${FOO}
endef
没什么奇怪的。但是看看当我们将它传递给 eval:
时会发生什么
FOO := Bar
$(eval ${rule})
我们最好仔细看看最后一行。
- 使扩展
$(eval ${rule})
- 首先扩展
${rule}
$$
扩展为 $
-
${FOO}
的所有 次出现都被替换为 Bar
- 给我们留下这段文字:
PHONY: Bar
Bar:
</code> <code>
</code> <code>@echo $@ Bar
你能看出 ${FOO}
的当前值是如何被烘焙到配方中的吗?
- 现在 make 语法块被传递给
$(eval)
- Make 创建新规则作为 eval
的副作用
- eval 的扩展虽然是空的。
不错。
FOO := Dead
$(eval ${rule})
FOO := Beef
$(eval ${rule})
您离避免使用全局变量而使用局部参数不远了:
$(call makerule,Dead)
$(call makerule,Beef)
一定是件好事,不是吗?
[AFAICR eval 在 make 3.81 中效果不佳,因此至少使用 3.82 版本]
我知道GNU Make中两种变量的区别
我目前正在编写一个构建系统,其中某些变量在子目录(例如 VERSION)中定义。为了让子目录作者的生活更简单,我不想强迫他们使他们的变量全局唯一。我也想避免递归制作。
我现在的问题是我需要一种方法来提供一些简单的库目标,以便在定义目标时扩展这些公共变量。举个简单的例子:
FOO := Bar
PHONY: $(FOO)
$(FOO):
@echo $(FOO)
FOO := Definitely not Bar
PHONY: test2
test2: Bar
@echo $(FOO)
我需要 make test2
的输出是
Bar
Definitely not Bar
当然,我可以在第一条规则中使用一个临时变量来强制扩展 FOO,但是我需要一种方法来可靠地定义一个新的临时变量。有没有办法扩大目标,例如使用评估?
编辑:使示例代码中 FOO 的奇怪扩展更加清晰。
看起来你只是想要 target-specific variables, 例如
生成文件
.PHONY: Bar test2
Bar: FOO := Bar
Bar:
@echo $(FOO)
test2: FOO := Definitely not Bar
test2: Bar
@echo $(FOO)
运行方式如下:
$ make test2
Bar
Definitely not Bar
(请注意,.PHONY
与所有特殊目标一样,以 .
开头)
您可以使用 $(eval …)
编写一些很好的功能代码(双关语)。您可以编写闭包,并决定什么时候扩展什么。
考虑这个变量:
define rule =
PHONY: ${FOO}
${FOO}:
@echo $$@ ${FOO}
endef
没什么奇怪的。但是看看当我们将它传递给 eval:
时会发生什么FOO := Bar
$(eval ${rule})
我们最好仔细看看最后一行。
- 使扩展
$(eval ${rule})
- 首先扩展
${rule}
$$
扩展为$
-
${FOO}
的所有 次出现都被替换为Bar
- 给我们留下这段文字:
PHONY: Bar
Bar:
</code> <code>
</code> <code>@echo $@ Bar
你能看出${FOO}
的当前值是如何被烘焙到配方中的吗?
- 现在 make 语法块被传递给
$(eval)
- Make 创建新规则作为 eval 的副作用
- eval 的扩展虽然是空的。
- 首先扩展
不错。
FOO := Dead
$(eval ${rule})
FOO := Beef
$(eval ${rule})
您离避免使用全局变量而使用局部参数不远了:
$(call makerule,Dead)
$(call makerule,Beef)
一定是件好事,不是吗?
[AFAICR eval 在 make 3.81 中效果不佳,因此至少使用 3.82 版本]