在 Makefile 函数中设置变量值时遇到问题

Encountered an issue setting the value of a variable inside a Makefile function

目录结构(以 运行 本例为例)如下所示:

example
 |-- Makefile
 |-- foo
 |    |-- foo.h (empty file)
 |-- bar
 |    |-- bar.h (empty file)

Makefile 看起来像这样:

TARGETS=foo bar

define GEN_HEADER_RULE
$(1)_INCS = $(wildcard $(1)/*.h)
$(info $$($(1)_INCS) is [$($(1)_INCS)])
$(info $$(wildcard $$(1)/*) is: [$(wildcard $(1)/*)])
endef

$(foreach t,$(TARGETS),$(eval $(call GEN_HEADER_RULE,$t)))

all: 
    @echo "DONE"

实际输出为:

$(foo_INCS) is []
$(wildcard $(1)/*) is: [foo/foo.h]

$(bar_INCS) is []
$(wildcard $(1)/*) is: [bar/bar.h]

DONE

预期输出为:

$(foo_INCS) is [foo/foo.h]
$(bar_INCS) is [bar/bar.h]

我不明白为什么变量 $(1)_INCS 的值没有被设置为通配符函数的输出?通配符函数显然可以正常工作 - 如 $info 命令直接从中转储输出所示。

我构建了这个简单的 Makefile 来演示我在更大的构建系统中遇到的相同问题。

您忘记保护变量和函数免受双重展开。将除 $(1) 之外的所有 $ 加倍,你应该几乎看到你想要的(第二个 $(info...) 除外,它会产生比你预期更多的输出)。

host> cat Makefile
TARGETS=foo bar

define GEN_HEADER_RULE
$(1)_INCS = $$(wildcard $(1)/*.h)
$$(info $$$$($(1)_INCS) is [$$($(1)_INCS)])
$$(info $$$$(wildcard $(1)/*) is: [$$(wildcard $(1)/*)])
endef

$(foreach t,$(TARGETS),$(eval $(call GEN_HEADER_RULE,$t)))

all: 
    @echo "DONE"

host> make
$(foo_INCS) is [foo/foo.h]
$(wildcard foo/*) is: [foo/foo.h]
$(bar_INCS) is [bar/bar.h]
$(wildcard bar/*) is: [bar/bar.h]
DONE

当使用 foreach-eval-call 时,请记住 eval-call 会进行第一次扩展,当 make 将结果解析为 make 语法时会进行第二次扩展。您经常需要转义第一个扩展 ($$),有时甚至需要转义第二个扩展 ($$$$)。有关详细说明,请参阅 the GNU make manual