【问题标题】:why does "make" delete target files only if implicit为什么“make”只有在隐式的情况下才会删除目标文件
【发布时间】:2019-01-25 02:36:13
【问题描述】:

假设我有一个像这样的 Makefile

B1.txt: A1.txt
    python big_long_program.py A1.txt > $@

correct1.txt: B1.txt reference.txt
    diff -q B1.txt reference.txt
    touch $@

然后我做correct1.txt时的输出是我所期望的:

python big_long_program.py A1.txt > B1.txt
diff -q B1.txt reference.txt
touch correct1.txt

现在如果我有很多文件,B1.txt、B2.txt、B3.txt 等,那么创建一个隐式规则:

B%.txt: A%.txt
    python big_long_program.py A$*.txt > $@

correct%.txt: B%.txt reference.txt
    diff -q B$*.txt reference.txt
    touch $@

相反,当我制作正确的 1.txt 时会发生这种情况:

python big_long_program.py A1.txt > B1.txt
diff -q B1.txt reference.txt
touch correct1.txt
rm B1.txt

即不同的是,现在文件 B1.txt 已被删除,这在很多情况下确实很糟糕。

那么为什么隐式规则不同呢?还是我做错了什么?

【问题讨论】:

    标签: makefile gnu-make


    【解决方案1】:

    你没有做错任何事。您观察和分析的行为记录在 10.4 Chains of Implicit Rules 中。它指出中间文件确实被区别对待。

    第二个区别是如果 make 确实创建 b 是为了更新 别的东西,它会在不再需要 b 后删除它。 因此,在 make 之前不存在的中间文件也 make 后不存在。 make 通过以下方式向您报告删除 打印一个rm -f 命令,显示它正在删除哪个文件。

    文档没有明确解释为什么它会这样。在文件ChangeLog.1 中查找到remove_intermediates 函数的引用早在1988 年。当时,磁盘空间非常昂贵且非常珍贵。

    如果您不希望出现这种行为,请将要保留在 makefile 中某处的目标作为明确的先决条件或目标提及,或者为此使用 the .PRECIOUS or the .SECONDARY special built-in targets

    感谢MadScientist 提供额外的cmets,见下文。

    【讨论】:

    • 您不必使用.PRECIOUS.SECONDARY。您所要做的就是将您想要保留在 makefile 中某处的目标作为明确的先决条件或目标。例如,您可以说alltxt: B1.txt B2.txt B3.txt 等。
    • @MadScientist 当然,您是对的,有多种选择可以避免这种删除。既然您提到了另一个选项,那么您有理由更喜欢一种机制而不是另一种吗?
    • 就个人而言,我总是更喜欢任何“正常”的 make 行为,而不是任何“特殊”目标。 .PRECIOUS 具有您可能不想要的其他效果。通常情况下,如果您考虑一下,如果出于某种原因确实需要这些文件,无论如何,将它们作为某个目标的先决条件很方便。
    • @MadScientist 这是有道理的。我已经更新了我的答案,感谢您帮助我改进它。
    • 至于为什么会发生这种情况,从过去的历史可以追溯到磁盘空间昂贵且溢价的时候。它主要用于静态库,您可以通过替换单个目标文件来更新库,而不是从头开始重建它。由于您不需要所有其他 .o,只需要过期的,因此您可以删除它们并节省磁盘空间,而不会增加构建时间。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-16
    相关资源
    最近更新 更多