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

时间:2012-03-13 20:22:58

标签: makefile

我正在使用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 )的扩展,并且它的输出是合法的,所以我很难过。

3 个答案:

答案 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