GNU make:删除生成的文件时如何重建哨兵目标?

Posted

技术标签:

【中文标题】GNU make:删除生成的文件时如何重建哨兵目标?【英文标题】:GNU make: how to rebuild sentinel targets when a generated file is deleted? 【发布时间】:2021-12-25 10:28:09 【问题描述】:

从 GNU make 执行代码生成器。生成器生成多个文件(取决于输入),并且仅在文件内容发生变化时才触及这些文件。因此需要使用哨兵目标来记录生成器的执行时间:

GEN_READY : $(gen_input_files)
    gen.exe $(gen_input_files)
    touch GEN_READY

$(gen_output_files): GEN_READY

它工作得很好,除非生成的文件被删除,但哨兵文件留在原地。由于哨兵在那里,并且它是最新的,因此不会再次执行生成器。 在这种情况下,强制 make 重新运行生成器的正确解决方案是什么?

【问题讨论】:

如果您有 Make 4.3,您可以尝试分组目标。如果不是,您可以考虑按档案对它们进行分组,并声明诸如 target.tar:prerequisite.tar 之类的规则。从输入文件哈希生成哨兵文件名是一种效果很好的技术,但可能需要比注释更长的时间来解释......有任何偏好吗? 感谢您的想法。我现在正在尝试分组目标。除了 4.3+ 之外,这可能是一个问题,我在链接规则时遇到了另一个问题。虽然可能可以修复。档案听起来很有趣,我从未尝试过的功能,看着它。哈希在这里肯定太复杂了。 Automake 手册对handling tools that produce multiple outputs 进行了相对冗长的讨论,包括使用标记文件。尽管有其来源,但讨论对于各种make 实现是通用的,而不是特定于 Automake。我想你会觉得它值得一读。 这绝对是有趣且有用的信息,非常感谢。最终的解决方案可能不适用于 GNU make。它非常复杂,使用递归 make 调用,并且不确定如何测试许多生成的文件。 从 2007 年开始,有一个 Ask Mr. Make article 关于在 GNU Make 中使用原子规则和哨兵文件。 【参考方案1】:

这是使用存档对它们进行分组的一种方法:

# create archive of output files from input files passed through gen.exe
GEN_READY.tar: $(gen_input_files)
    @echo Generate the files
    gen.exe $^
    @echo Put generated files in archive
    tar -c -f $@ $(gen_output_files)
    @echo Remove intermediate files (recreated by next recipe)
    rm $(gen_output_files)

# Extracting individual files for use as prerequisite or restoration
$(gen_output_files): GEN_READY.tar
    @echo Extract one member
    tar -x -f $< $@

由于 tar(和 zip 就这一点而言)允许重复条目,因此如果输入-输出关系允许,则可能有机会更新或附加存档中的文件,而不是重写。


编辑:简化的解决方案。

【讨论】:

我意识到这个答案实际上并不适用于这个问题,因为哨兵文件被删除了。哦,好吧,无论如何,有人可能会觉得它很有用。 这当然很有用,因为我从来没有在 make 中使用过存档并且不熟悉语法。我想知道这是否可以在不实际创建档案的情况下使用,只是为了对目标进行分组...... 已编辑以涵盖删除一个文件的情况,在这种情况下,当前答案将从半中间存档中恢复该文件。

以上是关于GNU make:删除生成的文件时如何重建哨兵目标?的主要内容,如果未能解决你的问题,请参考以下文章

GNU make:规则专题

如何在 GNU make 中收集过期依赖项列表?

在 GNU make 中列出定义中包含变量的目标/目标

GNU Autotools:在没有版本信息的情况下重建

如何在 GNU Make 中以编程方式定义目标?

makefile工作方式