GNU Makefile - 具有一个依赖项的多个目标的模式规则忽略所有目标,但第一个

Posted

技术标签:

【中文标题】GNU Makefile - 具有一个依赖项的多个目标的模式规则忽略所有目标,但第一个【英文标题】:GNU Makefile - Pattern rule with multiple targets with one dependency ignores all targets but the first 【发布时间】:2015-01-08 08:58:21 【问题描述】:

我想创建一个语言依赖目标。特别是:我有一个源文件,我想创建不同的对象,这些对象添加到相应的语言文件夹中。那个单一的源文件在 C 标志中会有所不同,编译器会得到。只要我以静态方式使用它,它就可以很好地工作。

de/info.o en/info.o es/info.o : info.c
    $(ECHO)     (DEP) $< for $@

现在我想,如果它更动态一点会很棒,以防我添加新的语言依赖文件。所以我使用了如下通配符:

de/%.o en/%.o es/%.o : %.c
    $(ECHO)     (DEP) $< for $@

但现在它只制作第一个目标而忽略其余的。 Make-Debug 打印以下内容:

Successfully remade target file `de/info.o'.
Considering target file `en/info.o'.
File `en/info.o' was considered already.

以防万一:不,对象不存在。所以没有目标,只有一个存在的依赖,所以 make 应该执行规则。

编辑:找到该问题的解决方案。

define FOO

$(1)/%.o : %.c
    $(ECHO)     $$< for $(1)

endef

 $(foreach lang,$(LANGUAGE_LIST), $(eval $(call FOO,$(lang))))

灵感来自:http://www.gnu.org/software/make/manual/make.html#Eval-Function

【问题讨论】:

【参考方案1】:

模式规则的工作方式与隐式规则不同。而隐含的规则,例如

a b c: d
      command

等价于更长的符号

a: d
      command
b: d
      command
c: d
      command

这不适用于模式规则。明确要求具有多个目标的模式规则在一次 command 调用中构建所有的目标。因此你必须写

$ cat GNUmakefile
all: de/x.o en/x.o es/x.o

de/%.o: %.c
        @echo $@ from $<
en/%.o: %.c
        @echo $@ from $<
es/%.o: %.c
        @echo $@ from $<
$ gmake
de/x.o from x.c
en/x.o from x.c
es/x.o from x.c

相关文档见 GNU make 手册的10.5.1 Introduction to Pattern Rules

模式规则可能有多个目标。与普通规则不同,这不会像许多具有相同先决条件和配方的不同规则一样起作用。如果模式规则有多个目标,make 知道规则的配方负责生成所有目标。该配方仅执行一次以生成所有目标。在搜索与目标匹配的模式规则时,与需要规则的目标匹配的规则之外的规则的目标模式是偶然的:只需担心为当前有问题的文件提供配方和先决条件。但是,当此文件的配方运行时,其他目标被标记为已自行更新。

【讨论】:

啊好吧,是的,我读到了这个……但我认为这个问题会有一个可靠的解决方案。因为每次添加语言时都必须添加目标。 好吧,如果您的命令是多行的,请考虑定义一个名为commands 的多行宏并将其与@$(call commands) 一起使用。那么每种新语言只需要添加两行。 宏是一个很好的提示! $(foreach , , )$(eval )$(call) 的组合解决了这个问题!我编辑了我的第一篇文章。

以上是关于GNU Makefile - 具有一个依赖项的多个目标的模式规则忽略所有目标,但第一个的主要内容,如果未能解决你的问题,请参考以下文章

GNU makefile 规则和依赖项

具有多个依赖项的 taskjuggler,其中任务长度取决于先前的任务

配置具有公共依赖项的 TypeScript 项目以构建多个纯 JavaScript 输出文件

使用 sbt-assembly 来自单个项目的具有不同外部依赖项的多个可执行 jar 文件

MySQL:在具有多个外键依赖项的表上进行更新

将具有循环链接依赖的makefile转换为CMake