首页 > 解决方案 > 具有多个输出规则的 Makefile 在并行运行时不会重建嵌套依赖项

问题描述

我有一个生成多个输出的规则的生成文件。为了解决这个规则在并行运行时经常运行多次的问题,我使用了一个虚拟的“时间戳文件”。我还有一个规则,它取决于这个“多输出”规则的输出之一。

当所有这些都从干净的状态运行时,一切正常。但是,如果更新了多输出规则的源,则不会运行其他规则,直到再次运行 Make。

我查看了调试输出,但未能取得太大进展。似乎 Make 可能正在缓存先前版本的多输出文件的旧时间戳?

希望下面的内容充分说明了这个问题。

 $ cat Makefile
all: data.txt

multioutput.stamp: sourcefile.txt
        touch multioutput1.txt
        touch multioutput2.txt
        touch $@

FILES=multioutput1.txt multioutput2.txt

$(FILES): multioutput.stamp

data.txt: multioutput1.txt
        touch data.txt
 $ touch sourcefile.txt
 $ make
touch multioutput1.txt
touch multioutput2.txt
touch multioutput.stamp
touch data.txt
 $ touch sourcefile.txt  # update
 $ make  # data.txt is not updated!!
touch multioutput1.txt
touch multioutput2.txt
touch multioutput.stamp
 $ make  # except when it's run again??
touch data.txt

我在这里做错了什么,我应该怎么做?

标签: makefilegnu-make

解决方案


你是在撒谎。不要那样做。

运行规则的配方后,检查文件是否已被配方实际更新。如果它没有改变,您不必重新制作任何将文件列为依赖项的目标。

在这里,您没有给出任何方法multioutput1.txt,只是一个依赖行:

multioutput1.txt: multioutput.stamp

Make知道没有办法更新multioutput1.txt

廉价修复

通过multioutput1.txt. _ 即使是空的也可以:

${FILES}: multioutput.stamp ;

是的,这就是它的;含义——食谱的第一行在同一行。

更好的修复

说“这个配方创建两个文件”的唯一方法是使用模式规则。那么就不需要multioutput.stamp.

.PHONY: all
all: data.txt

%1.txt %2.txt:
    touch $*1.txt
    touch $*2.txt

data.txt: multioutput1.txt  multioutput2.txt
    touch data.txt

这里$*的配方扩展为%依赖行中匹配的任何内容。

为什么我要data.txt依赖这两个多输出文件?在这里,我认为如果其中一个multioutput1multioutput2丢失,我们可能应该运行配方来创建两者。YMMV。

最佳修复

YMMV,但我不喜欢模式规则。它们对我的口味来说太随意了。

我们观察到其中一个multioutput1.txt永远multioutput2.txt比另一个年轻。假设现代文件系统,它们将永远不会具有相同的时间戳。

.PHONY: all
all: data.txt

multioutput2.txt: start.stamp
    touch $@
    touch multioutput2.txt

multioutput1.txt: multioutput2.txt ;

data.txt: multioutput1.txt
    touch data.txt

推荐阅读