在带有.mediate的makefile中不可靠的并行生成?

在带有.mediate的makefile中不可靠的并行生成?,makefile,gnu-make,Makefile,Gnu Make,我有一个工具可以生成多个输出文件,这是出了名的难以建模。我正在使用的配方似乎简单可靠。而且它几乎起作用了 不幸的是,我看到了一些关于并行构建的非常奇怪的行为,有时它似乎会删除依赖项;我不明白为什么 下面是我的测试用例: out3: out1 out2 touch out3 .INTERMEDIATE: out.intermediate out1 out2: out.intermediate out.intermediate: in touch out1 out2 如果我构建一

我有一个工具可以生成多个输出文件,这是出了名的难以建模。我正在使用的配方似乎简单可靠。而且它几乎起作用了

不幸的是,我看到了一些关于并行构建的非常奇怪的行为,有时它似乎会删除依赖项;我不明白为什么

下面是我的测试用例:

out3: out1 out2
    touch out3

.INTERMEDIATE: out.intermediate
out1 out2: out.intermediate
out.intermediate: in
    touch out1 out2
如果我构建一次,它就会工作:

$ touch in
$ make -f test.mk out3 -j4
touch out1 out2
touch out3
out1
out2
一起构建一次,这很好;然后根据结果构建
out3

现在,我触摸输入文件,模拟增量构建,然后重试:

$ touch in
$ make -f test.mk out3 -j4
touch out1 out2
这就是重建
out1
out2
,正确。。。但它并没有重建它应该拥有的
out3
。然后,如果我进行另一次构建:

$ make -f test.mk out3 -j4
touch out3
…然后它赶上了

这只适用于并行构建<代码>-j1构建工作正常

这很糟糕——我需要能够依赖正确的构建。有人知道发生了什么事吗


这是GNU Make 4.1。

您链接到的SO答案有错误;令人惊讶的是,这么多人显然成功地使用了它

发生的事情(您可以将
-rRd
选项添加到make调用中以查看更多细节)是gnumake目录缓存的结果。GNU make不希望文件系统状态以makefile描述以外的任何方式发生更改,因此它缓存目录的内容以提供显著的性能提高(对于大型makefiles/目录)

基本上,当make运行规则时:

out.intermediate: in
        touch out1 out2
该配方不会更新规则中列出的目标以外的任何目标:
out.intermediate
。如果其他文件
out1
out2
已经在目录缓存中内部化(它们将在目录缓存中,因为它们存在,并且我们已经将它们作为
out3
的先决条件进行了检查),那么make将不会返回到文件系统并查看它们是否已更新:make“knows”根据makefile,它们不可能改变,因为它运行的任何规则都不可能改变它们

有一个简单的,一个字符修复,使所有这些工作。更改此行:

out1 out2: out.intermediate
为此:

out1 out2: out.intermediate ;
如果您想更明确,您也可以使用:

out1 out2: out.intermediate
        @:
甚至是这个,对于调试:

out1 out2: out.intermediate
        @echo Do nothing

所有这些的共同点是,您现在不仅定义了目标和先决条件之间的依赖关系,还提供了make应该为该规则调用的配方。即使配方为空(如第一个示例中所示),因此make实际上没有运行任何命令,make仍会推断
out1
和/或
out2
上的时间戳可能已更改,它将使这些目标的缓存修改时间无效,并从文件系统中重新检索它们。

您所指的方法是在对该问题投票最多的第二个答案中的非GNU Make备用方案。当您使用GNU Make时,您可以在相同的答案中使用GNU Make解决方案,或者在投票最多的答案中使用GNU Make解决方案:我在您的测试用例中尝试了这个解决方案,很好。哪个GNU Make解决方案?你是说图案吗?这在这里是不合适的,因为我的文件名是不相关的。必要的相关是目标文件名(不是必备文件名)至少有一个共同字符,甚至是“.”甚至不是。我不能保证这一点,不。但是,这是一个次要问题;我主要关心的是依赖引擎中看起来可疑的完全错误。这应该行得通,还是
.INTERMEDIATE
没有我想的那样?谢谢你,这很好用。(而且,每次我使用make时,我都会更加讨厌它。)