3

Consider this Makefile:

.PHONY: all

all: main.txt

main.txt: build/main.txt
    cp build/main.txt .

%/main.txt: %/data.txt
    cp $*/data.txt $*/main.txt

%/data.txt:
    touch $*/data.txt

After running make, build/data.txt is removed automatically. Why is this the case?

I tried adding .PRECIOUS: build/% to the file, but it it not help, the file was still removed. How can I prevent this?

HerpDerpington
  • 3,751
  • 4
  • 27
  • 43
  • Does this answer your question? [How to undo intermediate file deletion](https://stackoverflow.com/questions/9638275/how-to-undo-intermediate-file-deletion) – Joe Aug 12 '20 at 11:08
  • @Joe As I have written, adding `.PRECIOUS build/%` does not work. It only works when explicitly naming the file. I want to preserve all files in the directory, – HerpDerpington Aug 12 '20 at 11:12
  • 1
    `.SECONDARY`, not `.PRECIOUS`, and see https://stackoverflow.com/questions/27090032/why-secondary-does-not-work-with-patterns-while-precious-does for whether a pattern can be used there. – Joe Aug 12 '20 at 11:15
  • An even simpler solution is simply to list the intermediate file as a prerequisite of _some_ target. It doesn't have to be a target you ever expect to run. Even something like `keepme: build/data.txt` is sufficient to force the file to be non-intermediate. Maybe it would be useful to you to create a rule that builds just the data and you create a rule like `data: build/data.txt` – MadScientist Aug 12 '20 at 12:58
  • 1
    I urge you to _NOT_ use `.PRECIOUS` for this. Declaring the target precious has other, probably unpleasant side-effects. For example, if your build is killed while the `build/data.txt` file is half-written then declaring it `.PRECIOUS` will prevent make from cleaning it up. That means the next run of make will see that half-built file with a newer timestamp and decide it's up to date and not rebuild it, causing problems until you go in and delete it by hand. `.PRECIOUS` has a specific use and should not be used only for its side effect of disable intermediacy. – MadScientist Aug 12 '20 at 13:01
  • 1
    If you want to force something to not be intermediate, the best way is to make it a prerequisite of some target as I mentioned above. – MadScientist Aug 12 '20 at 13:02

1 Answers1

0

According to the GNU Make documentation

You can also list the target pattern of an implicit rule (such as ‘%.o’) as a prerequisite file of the special target .PRECIOUS to preserve intermediate files created by rules whose target patterns match that file’s name.

the prerequisite for.PRECIOUS needs to be the (exact) target pattern of an existing implicit rule.

In your case this would be %/data.txt instead.

The documentation hints at this, but is not particularly clear about it.

As a side note: As far as I can tell build/main.txt is not automatically deleted since it is explicitly named as a prerequisite for the main.txt target and build/data.txt is automatically deleted since it is never explicitly named.

arand
  • 154
  • 1
  • 8