我正在使用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语法的完整片段,包括行斩波等,这就是多行扩展在那里工作的原因.
归档时间: |
|
查看次数: |
12023 次 |
最近记录: |