首页 > 解决方案 > Makefile 变量扩展未按预期工作

问题描述

我想根据变量列表自动创建生成文件规则(在我的用例中,我想有选择地构建一组文件)。但是我在扩展名称时遇到问题。

我创建了以下 Makefile 作为示例(M(not)WE):

FILES_A=a1 a2 a3
FILES_B=b1 b2 b3
TARGET_BASES=A B

define test
  FILES := $(value FILES_$1)
  build_$1: $(addsuffix .ext, $(FILES))
  build_dummy_$1: $(FILES)
endef

$(foreach target, $(TARGET_BASES), $(eval $(call test,$(target))))

运行make -p|grep build我希望得到以下输出:

[...]
build_A: a1.ext a2.ext a3.ext
build_dummy_A: a1 a2 a3
build_B: b1.ext b2.ext b3.ext
build_dummy_B: b1 b2 b3

但相反我得到

build_A:
build_dummy_A:
build_B: a1.ext a2.ext a3.ext
build_dummy_B: a1 a2 a3

同时我不知道为什么。有人可以阐明我在这里缺少的东西吗?

标签: makefile

解决方案


理解围绕 eval 和 call 的扩展可能会令人困惑。这就是为什么它们被认为是高级项目,只有在没有更容易理解的设施能够解决问题的情况下才应该使用它们。

这里的问题是您的宏test首先由call函数评估,然后再传递给eval函数。在该评估期间,该变量FILES尚未设置,因此它解析为上次运行 eval 时设置的任何内容:第一次评估为空,第二次评估为第一次运行后的结果,等等.

基本上规则是,您想要扩展的任何变量都call应该只有一个$,并且您想要扩展的任何变量都eval需要使用$$. 所以:

define test
  FILES := $$(value FILES_$1)
  build_$1: $$(addsuffix .ext, $$(FILES))
  build_dummy_$1: $$(FILES)
endef

推荐阅读