【发布时间】:2023-03-03 03:37:01
【问题描述】:
这是here 的问题的延续。问题是有一个规则会从单个输入生成多个输出,并且该命令很耗时,因此我们希望避免重新计算。现在还有一个额外的转折,我们希望防止文件作为中间文件被删除,并且规则涉及通配符以允许参数。
建议的解决方案是我们设置以下规则:
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 会同时创建这两者,并且我们避免了与-j 开关并行运行make 的问题。到目前为止一切都很好。
问题如下。因为上面的方案在DAG中建立了一个链,make的考虑不同;文件file-a.out 和file-b.out 被视为中间文件,默认情况下,一旦file-c.out 准备就绪,它们就会被删除,因为它们是不必要的。
这里提到了一种避免这种情况的方法,包括添加file-a.out 和file-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(尽管它很有用)。
【问题讨论】:
-
嗯,那里的先决条件中没有词干(即您使用的是 file.in 而不是 file-%.in)。如果你从 file-$n.in 构建 file-$a-$n.out 会变得容易得多,而且它的方式很奇怪(make file-c-17.out file-c-18.out)会除非有像时间这样的隐藏输入源,否则产生具有不同名称的相同输出。规则可以改成file-a-%.out: program file-%.in 吗?
-
这与手头的问题无关。这些只是组成的规则,关键是它们包含通配符。真正的规则要复杂得多,但这种复杂性会隐藏我面临的问题。
-
查看我的答案,了解为什么它是相关的。
-
不,因为
file.in不依赖于$*的事实来自某个地方;这是有原因的。例如,file.in保留所有常量参数,而 % 用于我想改变的东西。 -
您是否尝试过辅助连接,而不是链。看到这个答案:stackoverflow.com/questions/2973445/…
标签: makefile wildcard gnu-make