【问题标题】:Why is make not deleting intermediate files?为什么make不删除中间文件?
【发布时间】:2012-01-19 04:42:19
【问题描述】:

我遇到了 GNU make 3.81 不删除中间文件的问题。该问题类似于GNU make Not Deleting Intermediate Files,但该答案并不能解决我的问题。我已将问题提炼到这个测试用例:

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 $@ >$@

注意命令块必须是制表符缩进的。

也就是说,目标once 依赖于once.dep,而twice 依赖于twice.dep。此外,another 还依赖于twice.dep。正是这一行导致 twice.dep 永远不会被删除,即使 make 创建了它并且尽管有 .INTERMEDIATE 行。

发布的 Makefile 给出:

snafu$ rm -f once* twice*; make oncetwice
oncetwice: once twice
rm once.dep twice.dep

取消注释twice: twice.dep 行:

snafu$ rm -f once* twice*; make oncetwice
oncetwice: once twice
rm once.dep

请注意,在第二次调用中, two.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.**

我尝试使用命令块将another: twice.dep 设为真正的规则。我还尝试了将 .INTERMEDIATE 指定为模式、文字文件名以及两者的变体。我也尝试过使用.PHONY。 make-3.82 NEWS 似乎没有任何相关的修复。我目睹的行为看起来更像 .SECONDARY 目标所描述的行为。

谢谢,

里斯

【问题讨论】:

    标签: makefile gnu-make


    【解决方案1】:

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

    此外,GNU make 3.81 中有一个错误,即 .INTERMEDIATE 无法正常工作;此错误已在 3.82 中修复。如果您更改要使用的文件:

    .INTERMEDIATE: twice.dep
    

    (编辑:原始回复说“two.dep”)

    而不是 "%.dep" 并且您切换到 GNU make 3.82,您的示例将按预期工作。

    【讨论】:

    • 谢谢!如果没有“另一个:两次.dep”,则两次.dep 被认为是一个中间并适当地删除(如果已创建)。有了这条线,它不再被视为中间产品。为什么?
    • 因为中间文件的定义是“不存在且未提及”的文件。通过将文件列为先决条件,这在 makefile 中被视为“提及”。只需在 any 规则(不是配方)中明确提及它,即可取消其获得中间状态的资格。
    【解决方案2】:

    问题在于规则

    .INTERMEDIATE: %.dep
    

    不被解释为模式规则(因为它在左侧缺少%), 而%.dep 不是文件。

    例如,试试这个 Makefile:

    foo: %.bar
        cat $+ > $@ 
    

    现在创建a.barb.bar 并运行make foo

    【讨论】:

    • 如果这是原因,那么我可以建议将所有.dep 文件放入一个变量中(使用类似DEPS := $(SRCS:.c=.dep) 或任何适合您需要的东西)然后.INTERMEDIATE: $(DEPS)?跨度>
    • 是的,我认为需要一些类似的东西。
    • @reinierpost 我认为您认为 .INTERMEDIATE 是文件目标。相反,它是一个“特殊目标”(绝对不是模式规则)。文档不清楚模式是否允许,但它们肯定适用于 .PRECIOUS。在任何情况下,带有模式或显式 'twice.dep' 的 .INTERMEDIATE 或根本没有 .INTERMEDIATE 都会给出相同的结果。
    • @JackKelly 发布的 Makefile 是我能想到的最简单的案例,它可以复制问题。它不是发现问题的实际 Makefile(并且已经使用了您建议的构造)。文字依赖或变量依赖的使用无关紧要。 (但要不断提出想法!)
    • 好吧,我已经浏览了 GNU make 3.82 源代码,但我不能很快弄清楚 .INTERMEDIATE 是否支持模式作为依赖项。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-06
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多