43

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

3 Answers 3

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.

5
  • Thank you this indeed helped :)
    – Kamath
    Commented Mar 12, 2012 at 5: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." - gnu.org/software/make/manual/make.html
    – PonyEars
    Commented Jun 19, 2014 at 0:50
  • 4
    +1: unlike .SECONDARY, this is POSIX: pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html Commented Mar 18, 2015 at 5:09
  • I guess this would not work for filename foo.bar.c or a.b.o etc.?
    – Dilawar
    Commented Jul 26, 2019 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
    Commented Jul 27, 2019 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:
4
  • 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 gnu.org/software/make/manual/make.html)
    – PonyEars
    Commented Jun 19, 2014 at 0: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
    Commented Dec 5, 2014 at 0: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
    Commented Dec 8, 2015 at 19:37
  • At the moment, pattern rules don't work in .SECONDARY prerequisites, see bug #55533. Explicit file names work.
    – ruvim
    Commented Nov 19, 2019 at 8: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 ...

0

Not the answer you're looking for? Browse other questions tagged or ask your own question.