Package: make Version: 3.81-8.2 Severity: grave Justification: renders package unusable Control: block 725629 with -1
Hi, consider this Makefile: ----- Makefile/Makefile.in ----- all: do_something foo: echo '# foo' > $@ Makefile: Makefile.in foo cat Makfile.in foo > $@ ----- ----- If 'foo' does not exist, any execution of the 'all' target should first create 'foo' and recreate 'Makefile'. This works fine, unless foo is created with the same timestamp as the existing Makefile. Attached is a slightly more advanced proof-of-concept Makefile.in, run it as time make -f Makefile.in loop It should run forever, but on all machines where I tried it, it terminated after some time because Makefile was not updated: $ time make -f Makefile.in loop make clean make[1]: Entering directory '/home/andreas/725629' rm -f blah cp Makefile.in Makefile make[1]: Leaving directory '/home/andreas/725629' set -x ; while make test ; do make clean ; done + make test make[1]: Entering directory '/home/andreas/725629' echo 'foobar:' >blah echo ' @echo FOOBAR' >>blah cat Makefile.in blah > Makefile if ! grep -q ^foobar: Makefile ; then echo FAIL ; ls -lart --time-style=full-iso Makefile* blah ; exit 1 ; else echo OK ; fi OK make[1]: Leaving directory '/home/andreas/725629' + make clean make[1]: Entering directory '/home/andreas/725629' rm -f blah cp Makefile.in Makefile make[1]: Leaving directory '/home/andreas/725629' [... skipped some iterations ...] + make test make[1]: Entering directory '/home/andreas/725629' echo 'foobar:' >blah echo ' @echo FOOBAR' >>blah cat Makefile.in blah > Makefile if ! grep -q ^foobar: Makefile ; then echo FAIL ; ls -lart --time-style=full-iso Makefile* blah ; exit 1 ; else echo OK ; fi OK make[1]: Leaving directory '/home/andreas/725629' + make clean make[1]: Entering directory '/home/andreas/725629' rm -f blah cp Makefile.in Makefile make[1]: Leaving directory '/home/andreas/725629' + make test make[1]: Entering directory '/home/andreas/725629' echo 'foobar:' >blah echo ' @echo FOOBAR' >>blah if ! grep -q ^foobar: Makefile ; then echo FAIL ; ls -lart --time-style=full-iso Makefile* blah ; exit 1 ; else echo OK ; fi FAIL -rw-r--r-- 1 andreas andreas 377 2016-04-11 03:03:37.588201637 +0200 Makefile.in -rw-r--r-- 1 andreas andreas 22 2016-04-11 03:40:50.757214074 +0200 blah -rw-r--r-- 1 andreas andreas 377 2016-04-11 03:40:50.757214074 +0200 Makefile Makefile:2: recipe for target 'test' failed make[1]: *** [test] Error 1 make[1]: Leaving directory '/home/andreas/725629' real 0m0.152s user 0m0.012s sys 0m0.016s It terminates even faster on a filesystem with one-second-resolution: anbe@exodar:~/725629$ time make -f Makefile.in loop make clean make[1]: Entering directory '/home/anbe/725629' rm -f blah cp Makefile.in Makefile make[1]: Leaving directory '/home/anbe/725629' set -x ; while make test ; do make clean ; done + make test make[1]: Entering directory '/home/anbe/725629' echo 'foobar:' >blah echo ' @echo FOOBAR' >>blah if ! grep -q ^foobar: Makefile ; then echo FAIL ; ls -lart --time-style=full-iso Makefile* blah ; exit 1 ; else echo OK ; fi FAIL -rw-r--r-- 1 anbe anbe 266 2016-04-11 02:45:46.000000000 +0200 Makefile.in.old -rw-r--r-- 1 anbe anbe 377 2016-04-11 03:08:04.000000000 +0200 Makefile.in -rw-r--r-- 1 anbe anbe 22 2016-04-11 03:09:25.000000000 +0200 blah -rw-r--r-- 1 anbe anbe 377 2016-04-11 03:09:25.000000000 +0200 Makefile Makefile:2: recipe for target 'test' failed make[1]: *** [test] Error 1 make[1]: Leaving directory '/home/anbe/725629' real 0m0.080s user 0m0.000s sys 0m0.000s I could reproduce this on different architectures, with different filesystems (ppc64el/ext4, hurd-i386/ext2 amd64/xfs,tmpfs) and with the make packages from wheezy, jessie and stretch. An example where this bug (non-deterministically) breaks the build process on some architectures, is #725629. Andreas
test: Makefile if ! grep -q ^foobar: Makefile ; then echo FAIL ; ls -lart --time-style=full-iso Makefile* blah ; exit 1 ; else echo OK ; fi Makefile: Makefile.in blah cat Makefile.in blah > $@ blah: echo 'foobar:' >$@ echo ' @echo FOOBAR' >>$@ clean: rm -f blah cp Makefile.in Makefile loop: Makefile make clean set -x ; while make test ; do make clean ; done