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