make kindaclean; make --debug=all says:
Finished prerequisites of target file 'a-derived.src'.
Prerequisite 'a.out' of target 'a-derived.src' does not exist.
No need to remake target 'a-derived.src'.
https://www.gnu.org/software/make/manual/html_node/Chained-Rules.html#Chained-Rules
teaches:
The first difference is what happens if the intermediate file does not exist.
If an ordinary file b does not exist, and make considers a target that depends
on b, it invariably creates b and then updates the target from b. 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.
By using .SECONDARY with no prerequisites, you've marked everything as
intermediate. Marking just a.out as .SECONDARY seems enough to cause the
problem.
________________________________
From: Bug-make <[email protected]> on behalf of
Luke Shumaker <[email protected]>
Sent: Friday, February 22, 2019 11:45
To: [email protected]
Subject: Erroneously not updating intermediate/secondary dependency
***** EXTERNAL EMAIL *****
I believe that I have found a bug present in both Make 4.2.1 (as shipped by Arch
Linux) and in the latest git commit (214865ed5c66d8e363b16ea74509f23d93456707).
Here is a simple Makefile demonstrating the bug:
all: a-derived.out
.PHONY: all
kindaclean:
rm -f -- *.out
clean: kindaclean
rm -f -- a-derived.src
.PHONY: kindaclean clean
%.out: %.src
{ echo 'build'; date; ls -l $^; } > $@
a-derived.src: a.out
{ echo 'generate'; date; ls -l $^; } > $@
a-derived.out: a.out # Make sure that "a.out" isn't skipped as
intermediate
.SECONDARY:
For clarity, here is the dependency graph; "==" indicates an explicit
rule, "--" indicates an implicit rule:
all >===> a-derived.out >---> a-derived.src >===> a.out >---> a.src
`>=======================>'
The bug is that when running
$ echo foo > a.src
$ make
{ echo 'build'; date; ls -l a.src; } > a.out
{ echo 'generate'; date; ls -l a.out; } > a-derived.src
{ echo 'build'; date; ls -l a-derived.src a.out; } > a-derived.out
$ make kindaclean
rm -f -- *.out
$ make
{ echo 'build'; date; ls -l a.src; } > a.out
{ echo 'build'; date; ls -l a-derived.src a.out; } > a-derived.out
The "a-derived.src" does not get updated, despite both of thes
conditions being met: (1) its dependency "a.out" getting updated, and
(2) it being used in a later recipe.
We can instrument the Makefile to more explicitly demonstrate the
failure:
define sanitycheck
if ! test -e $1; then \
echo '=> dependency "$(strip $1): $(strip $2)" skipped because
dependent "$(strip $1)" does not exist'; \
elif ! test -e $2; then \
echo '=> dependency "$(strip $1): $(strip $2)" skipped because
dependency "$(strip $2)" does not exist'; \
elif test $2 -nt $1; then \
echo '=> dependency "$(strip $1): $(strip $2)" failed because
dependency "$(strip $2)" is newer than dependant "$(strip $1)"'; \
ls -l $1 $2; \
exit 1; \
else \
echo '=> dependency "$(strip $1): $(strip $2)" passed'; \
fi
endef
all: a-derived.out
@$(call sanitycheck, a.out , a.src )
@$(call sanitycheck, a-derived.src , a.out )
@$(call sanitycheck, a-derived.out , a-derived.src )
.PHONY: all
kindaclean:
rm -f -- *.out
clean: kindaclean
rm -f -- a-derived.src
.PHONY: kindaclean clean
%.out: %.src
{ echo 'build'; date; ls -l $^; } > $@
a-derived.src: a.out
{ echo 'generate'; date; ls -l $^; } > $@
a-derived.out: a.out # Make sure that "a.out" isn't skipped as
intermediate
.SECONDARY:
Which yields:
$ echo foo > a.src
$ make
{ echo 'build'; date; ls -l a.src; } > a.out
{ echo 'generate'; date; ls -l a.out; } > a-derived.src
{ echo 'build'; date; ls -l a-derived.src a.out; } > a-derived.out
=> dependency "a.out: a.src" passed
=> dependency "a-derived.src: a.out" passed
=> dependency "a-derived.out: a-derived.src" passed
$ make kindaclean
rm -f -- *.out
$ # wait a momenent, so the timestamps are visibly different
$ make
{ echo 'build'; date; ls -l a.src; } > a.out
{ echo 'build'; date; ls -l a-derived.src a.out; } > a-derived.out
=> dependency "a.out: a.src" passed
=> dependency "a-derived.src: a.out" failed because dependency "a.out"
is newer than dependant "a-derived.src"
-rw-r--r-- 1 lukeshu lukeshu 89 Feb 22 13:45 a-derived.src
-rw-r--r-- 1 lukeshu lukeshu 85 Feb 22 13:47 a.out
make: *** [Makefile:17: all] Error 1
--
Happy hacking,
~ Luke Shumaker
_______________________________________________
Bug-make mailing list
[email protected]
https://nam04.safelinks.protection.outlook.com/?url=https%3A%2F%2Flists.gnu.org%2Fmailman%2Flistinfo%2Fbug-make&data=01%7C01%7CMartin.Dorey%40hitachivantara.com%7C39c24e17d2914b68964308d698fed009%7C18791e1761594f52a8d4de814ca8284a%7C0&sdata=6uJzMYFWkMGPLpN7OCR32wm2d7lCsdQ0vX7KhL3YRbA%3D&reserved=0
_______________________________________________
Bug-make mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/bug-make