A collegue just came across this, and I thought I'd ask if there's any neat solution to the following problem: I have a GNU makefile:
a: | b
touch $@
b:c
touch $@
c:
touch $@
Then I run:
~/tmp> make a
touch c
touch b
touch a
~/tmp> make a
make: `a' is up to date.
~/tmp> touch b
~/tmp> make a
make: `a' is up to date.
~/tmp> touch c
~/tmp> make a
touch b
It rebuilds b
but not a
if I touch c
. Is there a way to NOT rebuild b
if it is being invoked by an order-only prerequisite? ( in the real-life case b
is a file with hundreds of dependencies, which may not be around when make a
is invoked. I can't make b
's prerequisites be order-only as that would break make b
)
The behavior is fully correct. You instructed make
to ignore the tight dependency between a
and b
and depend only on b
presence. Whilst a
and c
share a date dependency.
This is the difference between a: b
and a: | b
.
If one wants to investigate that case (or other make
magic :) ):
Try the following, you'll see that make
is keen and tells you what it is doing for b
target:
% touch b
% LANG=C make -rd | awk '/^Considering/,/^$/ {print}'
Considering target file `a'.
Considering target file `b'.
Considering target file `c'.
Finished prerequisites of target file `c'.
No need to remake target `c'.
Finished prerequisites of target file `b'.
Prerequisite `c' is older than target `b'.
No need to remake target `b'.
Finished prerequisites of target file `a'.
Prerequisite `b' is order-only for target `a'. <--- "order-only"
No need to remake target `a'.
Now, add a tight dependency:
% echo "a:b" >> Makefile
And compare results:
% touch b
% LANG=C make -rd | awk '/^Considering/,/^$/ {print}'
Considering target file 'a'.
Considering target file 'b'.
Considering target file 'c'.
Finished prerequisites of target file 'c'.
No need to remake target 'c'.
Finished prerequisites of target file 'b'.
Prerequisite 'c' is older than target 'b'.
No need to remake target 'b'.
Pruning file 'b'.
Finished prerequisites of target file 'a'.
Prerequisite 'b' is order-only for target 'a'.
Prerequisite 'b' is newer than target 'a'. <--- additional "date dependency"
Must remake target 'a'.
touch a <--- 'a' is rebuilt
Putting child 0x1b09ec0 (a) PID 5940 on the chain.
Live child 0x1b09ec0 (a) PID 5940
Reaping winning child 0x1b09ec0 PID 5940
Removing child 0x1b09ec0 PID 5940 from chain.
Successfully remade target file 'a'.
I used make -r
(no implicit rules) as this example doesn't use them and it's boring to read.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With