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 <bug-make-bounces+martin.dorey=hds....@gnu.org> on behalf of Luke Shumaker <luke...@lukeshu.com> Sent: Friday, February 22, 2019 11:45 To: bug-make@gnu.org 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 Bug-make@gnu.org 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 Bug-make@gnu.org https://lists.gnu.org/mailman/listinfo/bug-make