Siddhant Srivastava
Siddhant Srivastava

Reputation: 1

Makefile target dependency not honored

#!make

.PRECIOUS: a/b/c/%_pqr
a/b/c/%_pqr:
        echo $@
        touch $@

.PRECIOUS: a/b/c/%_abc
a/b/c/%_abc: a/b/c/pqr_pqr
        echo $@
        touch $@

When I run first time, it honors its dependency:

make a/b/c/pqr_abc -f 1.mk
echo a/b/c/pqr_pqr
a/b/c/pqr_pqr
touch a/b/c/pqr_pqr
echo a/b/c/pqr_abc
a/b/c/pqr_abc
touch a/b/c/pqr_abc

But if I delete "a/b/c/pqr_pqr" file and then run this target again, it doesn't do the needful:

rm -f a/b/c/pqr_pqr; make a/b/c/pqr_abc -f 1.mk
make: `a/b/c/pqr_abc' is up to date.

As per my understanding, it should run both targets again. Please somebody help me.

Upvotes: 0

Views: 71

Answers (1)

raspy
raspy

Reputation: 4271

Both your targets are implicit and therefore intermediate. As per documentation:

The first difference is what happens if the intermediate file does not exist. [...] But if b is an intermediate file, then make can leave well enough alone. It won’t bother updating b, or the ultimate target, unless some prerequisite of b is newer than that target or there is some other reason to update that target.

Therefore since pqr_abc already exists and pqr_pqr is an intermediate file and has no prerequisites (so no prerequisites have changed), it will not be regenerated.

As per make's understanding pqr_pqr would need to be created only to generate pqr_abc from it (this is the definition of intermediate file), and since pqr_abc already exists, there is no need to regenerate it.

If you want the file to be regenerated every time, it has to be mentioned explicitly, so that it is no longer considered an intermediate file, i.e.:

$ cat Makefile
a/b/c/%_pqr:
        touch $@

a/b/c/%_abc: a/b/c/pqr_pqr
        touch $@

a/b/c/pqr_pqr:

The last line defines explicit target, but it does not define recipe, which will still be invoked from implicit rule. Note that it will no longer be considered intermediate and will not be automatically removed, so .PRECIOUS directives are also not needed.

Output:

$ make a/b/c/pqr_abc
touch a/b/c/pqr_pqr
touch a/b/c/pqr_abc

$ make a/b/c/pqr_abc
make: 'a/b/c/pqr_abc' is up to date.

$ rm a/b/c/pqr_pqr
$ make a/b/c/pqr_abc
touch a/b/c/pqr_pqr
touch a/b/c/pqr_abc

Upvotes: 1

Related Questions