我正在使用GNU make 3.81。这是一个演示问题的测试makefile:
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
函数将扩展发送到标准输出,让我们看看该行扩展到了什么。我将第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.
请注意,“no targets”消息是预期的,因为$(info ...)函数的计算结果为空,但会导致生成 print 生成的规则。
我们应该运行这些规则吗?
$make -n > out.txt
make: *** No targets. Stop.
$make -f out.txt a1 a2 a3
touch a1
touch a2
touch a3
$
AAARGH!规则运作正常。所以...是make中的错误还是我的理解?
可能有助于诊断的最后一条线索:如果我将foreach行更改为:
$(foreach i,1,$(call BOZO,$(i)))
(因此foreach只有一次迭代)
然后再做
$make a1
我得到了一个不同的错误:
make: *** No rule to make target `a1'. Stop.
我不知道有什么方法可以“看到”除$(foreach )
以外的$(info )
的扩展,并且它的输出是合法的,所以我很难过。
答案 0 :(得分:40)
$(foreach i,1 2 3,$(eval $(call BOZO,$(i))))
eval function告诉Make将结构解析为makefile语法,以“制定”它们。我不确定为什么以这种特殊的方式反对未评估的规则,但这是一种学术性的。
答案 1 :(得分:32)
Beta的回答是正确的但我想解决这个问题,“我不确定为什么反对un-eval'd规则”。
un-eval'd规则不起作用的原因是makefile最终是基于行的,并且在扩展变量之前切断行。因此,变量的扩展变成多行结果是不可能的:即使扩展包含换行,make也将整个事物视为一条“线”。当make完成扩展foreach
循环并解析结果时,它基本上会看到:
a1: b c touch a1 a2: b c touch a2 a3: b c touch b3
这就是你得到“多目标模式”错误的原因。
eval使得make从头开始重新解释扩展的结果,作为makefile语法的完整片段,包括行斩波等,这就是多行扩展在那里工作的原因。
答案 2 :(得分:1)
也许过时,但总是相关的。 根本不需要制作这个宏。
您的问题的解决方案是简单地定义此规则:
a%: b c
touch a%
百分比充当通配符。在这里查看更多信息: https://stackoverflow.com/a/7406471/2522849