如何使用宏在foreach中生成多个Makefile目标/规则?神秘行为
我正在使用GNU make 3.81。下面是一个测试生成文件,演示了该问题:如何使用宏在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. (其
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%
百分比用作通配符。请参见此处的更多信息: