15

这是从这里开始的问题的延续。问题是有一个规则会从单个输入生成多个输出,并且该命令很耗时,因此我们希望避免重新计算。现在还有一个额外的转折,我们希望防止文件作为中间文件被删除,并且规则涉及通配符以允许参数。


建议的解决方案是我们设置以下规则:

file-a.out: program file.in
    ./program file.in file-a.out file-b.out file-c.out

file-b.out: file-a.out
    @

file-c.out: file-b.out
    @

然后,调用make file-c.out创建了两者,我们避免了与switchmake并行运行的问题。-j到目前为止一切都很好。


问题如下。由于上述方案在DAG中建立了一个链,make考虑不同;这些文件被视为中间文件,默认情况下,一旦准备好,它们就会被删除,因为它们是不必要file-a.out的。file-b.outfile-c.out

此处某处提到了一种避免这种情况的方法,包括添加file-a.outfile-b.out作为目标的依赖项.SECONDARY,以防止它们被删除。不幸的是,这并不能解决我的问题,因为我的规则使用通配符模式;具体来说,我的规则看起来更像这样:

file-a-%.out: program file.in
    ./program $* file.in file-a-$*.out file-b-$*.out file-c-$*.out

file-b-%.out: file-a-%.out
    @

file-c-%.out: file-b-%.out
    @

这样就可以传递包含在文件名中的参数,例如通过运行

make file-c-12.out

文档建议的解决方案make是将这些作为隐式规则添加到 的依赖项列表中.PRECIOUS,从而防止这些文件被删除。


该解决方案.PRECIOUS有效,但它还可以防止在规则失败且文件不完整时删除这些文件。有没有其他方法可以使这项工作?

解决这个问题的一个技巧是定义一个.SECONDARY没有先决条件的目标,即

.SECONDARY:

它通知make所有文件都应该被视为次要文件,因此不会被删除,除非make被中断或规则失败。不幸的是,这不允许选择带有通配符的规则子集以这种方式工作,所以我认为这只是一个 hack(尽管它很有用)。

4

2 回答 2

25

最简单的事

file-a-%.out file-b-%.out file-c-%.out: program file.in
    ./program $* file.in file-a-$*.out file-b-$*.out file-c-$*.out

会做你想做的事。

(具有多个目标的模式规则与您在此处询问的具有多个目标的正常规则不同。请参阅制作手册中的野牛示例。)

于 2010-06-24T20:14:06.767 回答
2

如果,而不是单个 file.in,您的输出是从包含词干的先决条件文件生成的,即

file-a.out: program file-%.in
    ./program file-$*.in file-a-$*.out file-b-$*.out file-c-$*.out

然后,您可以构建所有可能的目标匹配的列表:

inputs = $(wildcard file-*.in)
secondaries = $(patsubst file-%.in,file-a-%.out,$(inputs)) \
    $(patsubst file-%.in,file-b-%.out,$(inputs))

同样,如果词干来自有限集:

batchnos = 17 18 19 20 
batchnos = $(shell seq 17 20)
secondaries = $(patsubst %,file-a-%.out,$(batchnos)) $(patsubst %,file-b-%.out,$(batchnos))

然后只需将这些作为先决条件添加到 .SECONDARY 目标

.SECONDARY: $(secondaries)
于 2010-06-15T15:55:22.947 回答