在一个makefile目标中可以使用多个百分号(%)吗?

14

所以我有一个类似于这样的目标依赖的Makefile:

all: $(foreach lang, $(LANGS), $(foreach models,$(MODELS),targetName$(model).xml$(lang)))

目标名称 target 的外观如下:

targetName%.xml%: MODEL\=% targetName.xml*
但是它不起作用。我收到了这个错误:
make[1]: *** No rule to make target `targetNameMYMODEL.xmlen', needed by `all'.  Stop.

然而,像这样在targetName目标中硬编码语言并调用'all'函数可以正常工作:

all: $(foreach lang, $(LANGS), $(foreach models,$(MODELS),targetName$(model).xmlen))
而且,如果在all或targetName中不包含语言调用'all'也可以正常工作。我想也许Makefile不喜欢目标名中有两个百分号。
此外,既然我是继承了这个makefile的,有人能告诉我MODEL\=%是什么意思吗?还有另一个目标看起来像这样:MODEL%: ;但我不确定 \=% 是什么意思。
编辑: 因此,根据此响应进一步澄清:
假设我有一个列表,其中有5个模型和5种语言,目标是生成25个文件,每个组合对应一个文件。
原始的targetName%.xml目标将构建名为targetName.xml的文件,但现在我需要它构建类似于targetName_lang.xml这样的东西。这就是我需要两个%符号的原因。
我正在使用嵌套的foreach循环遍历这两个列表,但我很难将这些变量传递到目标中。我尝试从foreach语句中导出语言变量,尝试将targetName%.xml的内容放入循环中以便在那里遍历语言。后者无法工作,因为循环中有Makefile命令(例如eval)。
2个回答

6

你说得对,Make不喜欢目标名称中有两个%符号。这只是Make通配符处理方式不太完美的其中一种表现。有一种方法可以自动地通过迭代一个变量的值(并使用%作为另一个变量)生成所有模式规则;虽然有点丑陋,但如果您需要,我们可以向您展示。

但这行代码很混乱:

targetName%.xml%: MODEL\=% targetName.xml*

除了目标中有两个通配符的问题之外,最后一个先决条件targetName.xml*将恰好表示:名为targetName.xml*的目标(或文件)。星号不会被展开,也不会变成一个以targetName.xml开头的所有现有文件列表或其他任何内容。

然后是MODEL\=%,这表明该Makefile的作者有点困惑(并且不相信测试)。如果通配符的值为foo,则这将指示一个名为MODEL=foo的目标(或文件)作为前提条件。反斜杠\ "转义" =,使得Make不会中止,但这只是抑制了健康错误消息。我认为作者想表达的是这样的意思:

targetName%.xml: MODEL=%

targetName%.xml: $(wildcard targetName.xml*)
    do some things

第一条规则是不指定先决条件,而是设置特定于目标的变量。因此,当Make尝试通过执行某些操作来构建targetNamefoo.xml时,在该命令的上下文中,变量MODEL将具有值foo。第二条规则有一个前置列表,由通配符生成;您不能在同一行中混合使用特定于目标的变量和先决条件。
我们可以给出进一步的建议,但如果我们能更清楚地看到您想要做什么,那会很有帮助。

4
值得注意的是,有关此问题的官方文档指出:
10.5定义和重新定义模式规则
您可以编写一个模式规则来定义一个隐含规则。模式规则看起来像普通规则,只是其目标包含字符%仅限一个)。该目标被视为匹配文件名的模式; %可以匹配任何非空子字符串,而其他字符仅匹配自身。先决条件同样使用%来显示它们的名称与目标名称的关系。
因此,模式规则%.o : %.c说明如何从另一个文件stem.c创建任何文件stem.o
请注意,在模式规则中使用%进行扩展发生在变量或函数扩展之后,这些扩展发生在读取makefile时。请参见如何使用变量用于转换文本的函数
来源:https://www.gnu.org/software/make/manual/html_node/Pattern-Rules.html

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接