Makefile 为什么make不删除中间文件?

Makefile 为什么make不删除中间文件?,makefile,gnu-make,Makefile,Gnu Make,我对GNU make 3.81没有删除中间文件有问题。这个问题类似于,但这个答案并不能解决我的问题。我已经将问题提炼到这个测试用例中: default: @echo no $@ target; exit 1 oncetwice: once twice @echo $@: $^ ## Uncommenting the following line is sufficient to cause GNU make 3.81 to ## not delete the interme

我对GNU make 3.81没有删除中间文件有问题。这个问题类似于,但这个答案并不能解决我的问题。我已经将问题提炼到这个测试用例中:

default: 
    @echo no $@ target; exit 1

oncetwice: once twice
    @echo $@: $^

## Uncommenting the following line is sufficient to cause GNU make 3.81 to
## not delete the intermediate 'twice.dep', even if it didn't exist
## previously (i.e., was created by this invocation).
#another: twice.dep

%: %.dep
    @echo $^ >$@

## the following .INTERMEDIATE has no effect re: the twice: twice.dep
## dependency
.INTERMEDIATE: %.dep
%.dep:
    @echo $@ >$@
注意:命令块必须缩进制表符

也就是说,目标
一次取决于
一次.dep
两次取决于
两次.dep
。此外,
另一个
也取决于
两次。dep
。正是这一行导致
两次.dep
永远不会被删除,即使make创建了它并且忽略了.INTERMEDIATE行

发布的Makefile提供:

snafu$ rm -f once* twice*; make oncetwice
oncetwice: once twice
rm once.dep twice.dep
取消注释
行两次:两次。dep
行:

snafu$ rm -f once* twice*; make oncetwice
oncetwice: once twice
rm once.dep
请注意,在第二次调用中tweeps.dep不是rm'd

从信息页面:

.INTERMEDIATE
The targets which .INTERMEDIATE depends on are treated as intermediate files.

[...]

Intermediate files are remade using their rules just like all other
files. But intermediate files are treated differently in two ways.

The first difference [...]

**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.**
我已经试着用命令块把
另一个:两次.dep
变成一个真正的规则。我还尝试过将.INTERMEDIATE指定为模式、文本文件名,以及两者兼而有之。我也试过用。假的。make-3.82新闻似乎没有任何相关修复。我看到的行为更像是为次要目标描述的

谢谢


里斯

问题是规则

.INTERMEDIATE: %.dep
不被解释为模式规则(因为它的左侧缺少
%
), 和
%.dep
不是一个文件

例如,尝试以下生成文件:

foo: %.bar
    cat $+ > $@ 

现在创建
a.bar
b.bar
并运行
makefoo

规则

.INTERMEDIATE: %.dep
不被解释为模式规则(因为它的左侧缺少
%
), 和
%.dep
不是一个文件

例如,尝试以下生成文件:

foo: %.bar
    cat $+ > $@ 

现在创建
a.bar
b.bar
并运行
make foo
您不能使用模式作为.INTERMEDIATE特殊目标的先决条件(如果可以,它将记录在手册中;如果手册没有说您可以,那么您就不能)

此外,GNU make 3.81中有一个bug,其中.INTERMEDIATE不能正常工作;此错误已在3.82中修复。如果您将文件更改为使用:

.INTERMEDIATE: twice.dep
(编辑:原始回复为“两个dep”)


与“%.dep”不同,您将切换到GNU make 3.82,您的示例将按照您的预期工作。

您不能使用模式作为.INTERMEDIATE特殊目标的先决条件(如果可以,它将记录在手册中;如果手册没有说您可以,那么您就不能)

此外,GNU make 3.81中有一个bug,其中.INTERMEDIATE不能正常工作;此错误已在3.82中修复。如果您将文件更改为使用:

.INTERMEDIATE: twice.dep
(编辑:原始回复为“两个dep”)


与“%.dep”不同,您可以切换到GNU make 3.82,您的示例将按照您的预期工作。

如果这是原因,那么我建议将所有
.dep
文件放入一个变量(使用
DEPS:=$(SRCS:.c=.dep)或任何适合您需要的东西),然后
.INTERMEDIATE:$(DEPS)
?是,我认为需要一些类似的东西。@reinierpost我认为您相信。中间版本是一个文件目标。相反,它是一个“特殊目标”(绝对不是模式规则)。文档中不清楚模式是否被允许,但它们确实是非常宝贵的。在任何情况下,.INTERMEDIATE与一个模式或显式的'tweep.dep',或根本没有.INTERMEDIATE,都会给出相同的结果。@JackKelly发布的Makefile是我能找到的复制问题的最简单的例子。它不是发现问题的实际Makefile(并且已经使用了您建议的构造)。文字依赖或变量依赖的使用无关紧要。(但要继续保持想法!)好吧,我已经阅读了GNU make 3.82源代码,但我不能很快确定.INTERMEDIATE是否支持模式作为依赖项。如果这是原因,那么我可以建议将所有
.dep
文件放入一个变量中(使用类似
DEPS:=$(SRCS:.c=.dep)的内容吗
或任何适合您需要的工具)然后
中间版:$(DEPS)
?是的,我认为需要类似的东西。@reinierpost我认为您相信。中间版是一个文件目标。相反,它是一个“特殊目标”(绝对不是模式规则)。文档中不清楚模式是否被允许,但它们确实是非常宝贵的。在任何情况下,.INTERMEDIATE与一个模式或显式的'tweep.dep',或根本没有.INTERMEDIATE,都会给出相同的结果。@JackKelly发布的Makefile是我能找到的复制问题的最简单的例子。它不是发现问题的实际Makefile(并且已经使用了您建议的构造)。文字依赖或变量依赖的使用无关紧要。(但要继续保持想法!)好吧,我已经阅读了GNU make 3.82源代码,但我不能很快确定.INTERMEDIATE是否支持模式作为依赖项。谢谢!如果没有“另一个:twitter.dep”,twitter.dep将被视为中间版本,并被适当删除(如果已创建)。有了这条线,它就不再被认为是中间品了。为什么?因为中间文件的定义是“不存在且未提及”的文件。通过将文件列为先决条件,这在makefile中被视为“已提及”。只要在任何规则(不是配方)中明确提到它,就可以取消它的中级资格。谢谢!如果没有“另一个:twitter.dep”,twitter.dep将被视为中间版本,并被适当删除(如果已创建)。有了这条线,它就不再被认为是中间品了。为什么?因为中间文件的定义是“不存在且未提及”的文件。通过将文件列为先决条件,这在makefile中被视为“已提及”。它只需要在任何规则(而不是配方)中明确提及,就可以取消其中级资格。