具有多个输出规则的Makefile在并行运行时不重建嵌套依赖关系

问题描述 投票:1回答:1

我有一个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

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

makefile gnu-make
1个回答
0
投票

您对make撒谎。不要那样做。

一旦您运行了规则的配方,make会检查该配方是否实际更新了文件。如果尚未更改,则不必重新创建将文件作为依赖项列出的任何目标。

这里您没有给出multioutput1.txt的任何配方,仅给出了依赖项:

multioutput1.txt: multioutput.stamp

Make知道无法更新multioutput1.txt

廉价修复

Force make通过提供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依赖于两个multioutput文件?在这里,我认为如果缺少multioutput1multioutput2中的任何一个,我们可能应该运行配方来创建两者。YMMV。

最佳修复

YMMV,但我不喜欢模式规则。他们对我来说太武断了。

我们注意到multioutput1.txtmultioutput2.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
© www.soinside.com 2019 - 2024. All rights reserved.