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

Joe*_*Joe 28 makefile

我正在使用GNU make 3.81.这是一个演示问题的测试makefile:

define BOZO

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

endef

$(foreach i,1 2 3,$(call BOZO,$(i)))
Run Code Online (Sandbox Code Playgroud)

这里的想法是使用宏模板(BOZO)来生成遵循可预测模式的规则.

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

Makefile.fake:10: *** multiple target patterns.  Stop.
Run Code Online (Sandbox Code Playgroud)

(第10行是foreach的行).

现在,我知道错误通常表示的是什么.通过使用info函数将扩展发送到标准输出,让我们看看该行扩展到了什么.我将第10行更改为:

$(info $(foreach i,1 2 3,$(call BOZO,$(i))))
Run Code Online (Sandbox Code Playgroud)

我跑:

$ make -n

a1: b c
    touch a1

a2: b c
    touch a2

a3: b c
    touch a3

make: *** No targets.  Stop.
Run Code Online (Sandbox Code Playgroud)

请注意,"无目标"消息是预期的,因为$(info ...)函数的计算结果为空,但会导致make 打印生成的规则.

我们应该运行那些规则吗?

$make -n > out.txt
make: *** No targets.  Stop.
$make -f out.txt a1 a2 a3
touch a1
touch a2
touch a3
$
Run Code Online (Sandbox Code Playgroud)

AAARGH!规则运作正常.所以...是制作中的错误,还是我的理解?

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

$(foreach i,1,$(call BOZO,$(i)))
Run Code Online (Sandbox Code Playgroud)

(这样foreach只有一次迭代)

然后呢

$make a1
Run Code Online (Sandbox Code Playgroud)

我得到一个不同的错误:

make: *** No rule to make target `a1'.  Stop.
Run Code Online (Sandbox Code Playgroud)

我不知道有什么方法可以"看到" $(foreach )除了之外的那种扩展$(info ),并且它的输出是合法的,所以我很难过.

Bet*_*eta 40

$(foreach i,1 2 3,$(eval $(call BOZO,$(i))))
Run Code Online (Sandbox Code Playgroud)

eval函数告诉make解析结构的生成文件的语法,以"立"起来.我不确定为什么要以这种特殊的方式反对未经评估的规则,但那是一种学术性的.


Mad*_*ist 33

Beta的答案是正确的,但我想解决这个评论,"我不确定为什么要反对un 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
Run Code Online (Sandbox Code Playgroud)

这就是你得到"多目标模式"错误的原因.

eval使得make从一开始就重新解释扩展的结果,作为makefile语法的完整片段,包括行斩波等,这就是多行扩展在那里工作的原因.