【问题标题】:How to undo intermediate file deletion如何撤消中间文件删除
【发布时间】:2012-03-27 03:40:10
【问题描述】:

我有一个软件堆栈,可以在构建过程中创建一些中间文件。出现了一些问题,构建中断。我想看看那些中间生成的文件。令我惊讶的是,这些文件在构建过程中被删除了。

Removing intermediate files...
rm fact_test_without_proxies.c fact_test_main.c fact_test_without_proxies.o

我查看了 Makefile,我没有看到任何明确的规则删除它们。是否有任何隐含的规则来删除中间文件。如果是,我该如何禁用这些隐式规则?

只有在使用 --debug 选项执行 make 时,我才会看到打印 Removing intermediate files...

skmt@tux:~/coding/factorial/ut$ make --debug
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for x86_64-pc-linux-gnu
Reading makefiles...
Updating goal targets....
 File `check' does not exist.
   File `test_dept_run' does not exist.
     File `fact_test' does not exist.
       File `fact_using_proxies.o' does not exist.
           File `fact_test_without_proxies' does not exist.
            File `fact_test_without_proxies.o' does not exist.
             File `fact_test_without_proxies.c' does not exist.
              File `fact_test_main.c' does not exist.
             Must remake target `fact_test_main.c'.
nm -p fact_test.o | build_main_from_symbols >fact_test_main.c
             Successfully remade target file `fact_test_main.c'.
            Must remake target `fact_test_without_proxies.c'.
cp fact_test_main.c fact_test_without_proxies.c
            Successfully remade target file `fact_test_without_proxies.c'.
           Must remake target `fact_test_without_proxies.o'.
gcc  -I../src  -c -o fact_test_without_proxies.o fact_test_without_proxies.c
           Successfully remade target file `fact_test_without_proxies.o'.
          Must remake target `fact_test_without_proxies'.
gcc   fact_test_without_proxies.o fact.o fact_test.o   -o fact_test_without_proxies
fact.o: In function `unknown':
fact.c:(.text+0x67): undefined reference to `do_update'
collect2: ld returned 1 exit status
make: *** [fact_test_without_proxies] Error 1
Removing intermediate files...
rm fact_test_without_proxies.c fact_test_main.c fact_test_without_proxies.o

【问题讨论】:

    标签: makefile


    【解决方案1】:

    如果您使用的是 GNUMake,则可以使用特殊目标 .PRECIOUS

    .PRECIOUS: fact_test_without_proxies.c fact_test_main.c fact_test_without_proxies.o
    

    或者只是

    .PRECIOUS: %.c %.o
    

    它唯一的作用是如果Make被杀死或中断,这些文件不会被删除。

    【讨论】:

    • 谢谢你这确实有帮助:)
    • 不仅如此,使用 .PRECIOUS 意味着即使 Make 成功完成(即没有被杀死或中断),这些文件也不会被删除。 “另外,如果目标是一个中间文件,它在不再需要后不会被删除,就像通常所做的那样。[...]在后一个方面,它与 .SECONDARY 特殊目标重叠。” - gnu.org/software/make/manual/make.html
    • +1:不像.SECONDARY,这是POSIX:pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html
    • 我猜这不适用于文件名foo.bar.ca.b.o 等?
    • @Beta 我做到了。这有点微妙。我很困惑 %.foo 在 make 像 bash 中的 '*.foo' 一样工作。多注意我是如何构建我的目标修复它。它是用于目标匹配,而不是用于文件匹配。
    【解决方案2】:

    您也可以使用 .SECONDARY,即使构建没有中断,它也会保留指定的文件。

    例如

     .SECONDARY:
    

    【讨论】:

    • 谢谢。除此之外,.PRECIOUS “与 .SECONDARY 特殊目标重叠”。关于保留指定文件,即使构建没有中断(引用gnu.org/software/make/manual/make.html
    • 你应该列出.SECONDARY的参数。如果没有先决条件,它会导致 all 中间文件被保留,这不一定是你想要的。
    • 谢谢!不幸的是,.SECONDARY 中的目标列表对于.o 以外的扩展名似乎不适用。特别是.d 依赖文件无论如何都会被删除。这个解决方案,虽然不知道,但至少有效:)
    • 目前,模式规则不适用于.SECONDARY 先决条件,请参阅bug #55533。显式文件名有效。
    【解决方案3】:

    对目标的使用有限制,这会影响.PRECIOUS的行为:

    我有目标 A/%.foo: 和 B/%.foo: ,所以我设置了:

    .PRECIOUS: %.foo
    

    这没有用;我不明白为什么,但扩展不是这样工作的;我必须按原样明确列出目标:

    .PRECIOUS: A/%.foo B/%.foo
    

    但即使在阅读 https://www.gnu.org/software/make/manual/html_node/Special-Targets.html 之后,我也不明白 .PRECIOUS: 和 .SECONDARY: 之间的区别。

    可以接受使用那些不依赖于的特殊目标,但我认为这将是非常肮脏的编码并且会产生副作用。有些人只是把 .PRECIOUS: 或 .SECONDARY: 放在没有 dep 的情况下,后来他们抱怨他们必须在构建损坏后运行 make clean ...

    【讨论】: