0

I have a Makefile, roughly so:

.PRECIOUS: %.a %.b %.c

%.a:
        touch $@

%.b: %.a
        touch $@

%.c: %.b
        touch $@

If I create "test.c" with a make test.c, all the 3 files (test.a, test.b, test.c) are created correctly. However, if I now remove test.a, and then I try to re-create test.c, then nothing happens.

Reason is obvious: because test.c depends only on test.b, and test.b was not changed, not rebuild is needed. However, test.b should be rebuilt because test.a disappeared, and that should spread to test.c as well. I find this behavior as a highly un-intuitive side effect.

Can I somehow let make to handle "transitive" dependencies on the intuitive way? (I.e. after the deletion of test.a, all the targets must be rebuilt.)

The problem happens only with pattern rules.

(P.s. I need all the intermediate files, this is why the PRECIOUS. Default behavior of the GNU Make is that it deletes the intermediary files.)

6
  • The obvious solution is that I make "c" dependent of both "a" and "b". That works, question is, does a better solution exist. If not, then this solution is an acceptable answer.
    – peterh
    Commented Jan 10 at 17:51
  • I do not see the behavior you describe using GNU make 4.3. make c triggers touch a, touch b, touch c. If I then rm a; make c, I again get touch a, touch b, touch c. If I rm b; make c, then I get only touch b and touch c. That seems to be the desired behavior. Commented Jan 10 at 17:55
  • @AndyDalton You were right. Actually, my original Makefile had some % and after editing the question, the current version already shows the problem. Funny thing is that the direct dependencies are yes, rebuilt, only the transitive deps are not. I updated the minimal example and so also the question.
    – peterh
    Commented Jan 10 at 18:02
  • With that update, I see the behavior that you're describing. Unfortunately, I don't have any suggestions :/ Commented Jan 10 at 18:19
  • What about adding the directory test.a belongs to as a prerequisite to the target ?
    – MC68020
    Commented Jan 10 at 19:01

1 Answer 1

0

Typically, you would use a phony target traditionally named FORCE as a prerequisite for %.a, so that it is always built if it doesn't exist. Also, gnu make has a .NOTINTERMEDIATE special target that does not delete the intermediate files (but will do so on error and interrupt, unlike .PRECIOUS).

.NOTINTERMEDIATE: %.a %.b %.c
.PHONY: FORCE
%.a: FORCE
    touch $@
%.b: %.a
    touch $@
%.c: %.b
    touch $@
2
  • Which version of make are you using? With GNU make 4.4.1, using what you've posted if I do make test.c, it ends up touching Makefile.a, Makefile.b, Makefile.c, then tries to build an executable named Makefile (overwriting the makefile). Commented Jan 12 at 18:22
  • Yes, make always tries to update the makefilie first, and the built-in rules thinks Makefile can be built from Makefile.c and hence the cascade. You can add Makefile to the .PHONY target to avoid this. If the target %.c had been %.d for example, this wouldn't happen.
    – meuh
    Commented Jan 12 at 18:44

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .