为什么 "make" 仅在隐式时才删除目标文件

why does "make" delete target files only if implicit

假设我有一个这样的 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 $@

相反,当我 correct1.txt:

时会发生这种情况
python big_long_program.py A1.txt > B1.txt
diff -q B1.txt reference.txt
touch correct1.txt
rm B1.txt

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

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

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

The second difference is that if make does create b in order to update something else, it deletes b later on after it is no longer needed. Therefore, an intermediate file which did not exist before make also does not exist after make. make reports the deletion to you by printing a rm -f command showing which file it is deleting.

文档没有明确解释为什么它的行为是这样的。查看文件 ChangeLog.1,早在 1988 年就有对 remove_intermediates 功能的引用。当时,磁盘 space 价格昂贵且溢价。

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

感谢 MadScientist 的补充评论,请参阅下文。