42

I have a software stack that creates some intermediate files as a part of build process. There is some problem come up and the build breaks. I want to have a look at those intermediate generated files. To my surprise those files are being deleted as a part of build process.

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

I went through the Makefiles I don't see any explicit rules deleting them. Can there be any implicit rules to delete intermediate files. If yes how can I disable those implicit rules ?

I see the print Removing intermediate files... only if make is executed with --debug option.

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
Whymarrh
  • 13,139
  • 14
  • 57
  • 108
Kamath
  • 4,461
  • 5
  • 33
  • 60

3 Answers3

53

If you're using GNUMake, you can use the special target .PRECIOUS:

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

or just

.PRECIOUS: %.c %.o

Its only effect is that these files will not be deleted if Make is killed or interrupted.

Beta
  • 96,650
  • 16
  • 149
  • 150
  • Thank you this indeed helped :) – Kamath Mar 12 '12 at 05:33
  • 7
    Not only that, using .PRECIOUS means these files won't be deleted even if Make completes successfully (ie, is not killed or interrupted). "Also, if the target is an intermediate file, it will not be deleted after it is no longer needed, as is normally done. [...]In this latter respect it overlaps with the .SECONDARY special target." - https://www.gnu.org/software/make/manual/make.html – PonyEars Jun 19 '14 at 00:50
  • 4
    +1: unlike `.SECONDARY`, this is POSIX: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html – Ciro Santilli OurBigBook.com Mar 18 '15 at 05:09
  • I guess this would not work for filename `foo.bar.c` or `a.b.o` etc.? – Dilawar Jul 26 '19 at 11:47
  • @Beta I did. It was bit subtle. I was confused that `%.foo` in make works like '*.foo' in bash. Paying a little more attention to how I was constructing my targets fixed it. It's for target matching and not for file matching. – Dilawar Jul 27 '19 at 14:08
47

You can also use .SECONDARY, which will preserve the specified files even if the build does not break.

e.g.

 .SECONDARY:
Michael
  • 9,060
  • 14
  • 61
  • 123
  • Thanks. Just to add to that, .PRECIOUS "overlaps with the .SECONDARY special target." with respect to preserving the specified files even if the build does not break (quote from https://www.gnu.org/software/make/manual/make.html) – PonyEars Jun 19 '14 at 00:50
  • 7
    You should list arguments to `.SECONDARY`. If it is given no prerequisites, it causes *all* intermediate files to be retained, which isn't necessarily what you want. – Kaz Dec 05 '14 at 00:29
  • 1
    Thank you! Unfortunately listing targets in `.SECONDARY` seems to be broken for extensions other than `.o`. Specifically `.d` dependency files get deleted no matter what. This solution, while not idea, at least works :) – foges Dec 08 '15 at 19:37
  • At the moment, pattern rules don't work in `.SECONDARY` prerequisites, see [bug #55533](https://savannah.gnu.org/bugs/?55533). Explicit file names work. – ruvim Nov 19 '19 at 08:01
9

There is a restriction on the use of targets, which affects the behaviour of .PRECIOUS:

I have targets A/%.foo: and B/%.foo: , so I have set:

.PRECIOUS: %.foo

and this did not work; I don't understand why, but expansion does not work this way; I had to explicitely list targets exactly as they are written:

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

But even after reading https://www.gnu.org/software/make/manual/html_node/Special-Targets.html I do not understand the difference between .PRECIOUS: and .SECONDARY: .

It's accepted to use those special targets without depends, but I think this would be very dirty coding and would expect side effects. Some people just put .PRECIOUS: or .SECONDARY: without dep, and later, they complain they have to run make clean after a broken build ...