[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Erroneously not updating intermediate/secondary dependency
From: |
Luke Shumaker |
Subject: |
Erroneously not updating intermediate/secondary dependency |
Date: |
Fri, 22 Feb 2019 14:45:03 -0500 |
User-agent: |
Wanderlust/2.15.9 (Almost Unreal) SEMI-EPG/1.14.7 (Harue) FLIM/1.14.9 (Gojō) APEL/10.8 EasyPG/1.0.0 Emacs/26 (x86_64-pc-linux-gnu) MULE/6.0 (HANACHIRUSATO) |
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
- Erroneously not updating intermediate/secondary dependency,
Luke Shumaker <=