首页 > 解决方案 > 为什么“make”只有在隐式的情况下才会删除目标文件

问题描述

假设我有一个像这样的 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 已被删除,这在很多情况下是非常糟糕的。

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

标签: makefilegnu-make

解决方案


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

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

该文档没有明确解释为什么它会这样。查看文件ChangeLog.1,可以remove_intermediates追溯到 1988 年的函数。当时,磁盘空间非常昂贵且非常宝贵。

如果您不希望这种行为,请提及您要保留在 makefile 中某处的目标作为明确的先决条件或目标,或者为此使用.PRECIOUS特殊的.SECONDARY内置目标

感谢MadScientist的其他评论,见下文。


推荐阅读