如何使用宏在foreach中生成多个Makefile目标/规则?神秘行为

如何使用宏在foreach中生成多个Makefile目标/规则?神秘行为,makefile,Makefile,我正在使用GNU make 3.81。下面是一个测试生成文件,演示了该问题: define BOZO a$(1): b c touch a$(1) endef $(foreach i,1 2 3,$(call BOZO,$(i))) 这里的想法是使用宏模板(BOZO)生成遵循可预测模式的规则 问题:当我在这个makefile上运行make时,我得到一个错误,它说: Makefile.fake:10: *** multiple target patterns. Stop. (其

我正在使用GNU make 3.81。下面是一个测试生成文件,演示了该问题:

define BOZO

a$(1): b c
    touch a$(1)

endef

$(foreach i,1 2 3,$(call BOZO,$(i)))
这里的想法是使用宏模板(BOZO)生成遵循可预测模式的规则

问题:当我在这个makefile上运行make时,我得到一个错误,它说:

Makefile.fake:10: *** multiple target patterns.  Stop.
(其中第10行是与foreach的行)

现在,我知道这个错误通常意味着什么。让我们通过使用
info
函数将扩展发送到standard out来查看该行扩展到什么。我将第10行更改为:

$(info $(foreach i,1 2 3,$(call BOZO,$(i))))
我跑:

$ make -n

a1: b c
    touch a1

a2: b c
    touch a2

a3: b c
    touch a3

make: *** No targets.  Stop.
请注意,由于$(info…)函数的计算结果为空,但会导致make打印生成的规则,因此应显示“no targets”消息

我们来执行这些规则好吗

$make -n > out.txt
make: *** No targets.  Stop.
$make -f out.txt a1 a2 a3
touch a1
touch a2
touch a3
$
啊!规则很有效。所以这个bug是在制造中,还是在我的理解中

最后一个可能有助于诊断的线索是:如果我将foreach行更改为:

$(foreach i,1,$(call BOZO,$(i)))
(这样foreach只有一次迭代)

然后呢

$make a1
我得到一个不同的错误:

make: *** No rule to make target `a1'.  Stop.
除了
$(info)
,我不知道有什么方法可以“看到”除了
$(info)
之外的
$(foreach)
的扩展,而且它的输出是合法的,所以我很困惑

$(foreach i,1 2 3,$(eval $(call BOZO,$(i))))

命令Make将结构解析为makefile语法,以“执行”它们。我不知道为什么Make会以这种特殊方式反对联合国评估规则,但这有点学术性。

Beta的回答是正确的,但我想回应一下评论,“我不确定为什么Make会反对联合国评估规则”

未评估规则不起作用的原因是生成文件最终是基于行的,并且在展开变量之前,行被截断。因此,变量的展开不可能变成多行结果:即使展开包含换行符,make也会将整个内容视为一条“行”。当make完成对
foreach
循环的扩展并解析结果时,它基本上会看到:

a1: b c touch a1 a2: b c touch a2 a3: b c touch b3
这就是为什么会出现“多目标模式”错误


eval使make从一开始就将扩展的结果重新解释为makefile语法的完整片段,包括断行等,这就是为什么多行扩展在那里工作。

可能很旧,但总是相关的。 根本不需要制作这个宏

您的问题的解决方案是简单地定义以下规则:

a%: b c
    touch a%
百分比用作通配符。请参见此处的更多信息: