Subject: bug#13107: timestamp bug when files are created just before make is run

From: Mikulas Patocka <[email-masked]>
Date: Thu, 6 Dec 2012 23:02:48 +0100 (CET)

Hi

Try this Makefile:
---
a : b
        echo build a
        touch a

b : c
        echo build b
        touch b
---
and run this script:
touch b;sleep 1;touch a c;make

You see
"echo build b
build b
touch b"
but it doesn't remake a.

The apparent problem is that after make rebuilds b, it compares b's time 
with a's time, finds that the times are equal (because a was touched just 
before make was run) and doesn't rebuild a.

I think it is a bug - when b is finished, make should find out whether the 
rule for b modified the file b (if b's time is greater or equal than the 
time when the rule for b was started, then b may have been modified) and 
rebuild a in this case.

---

This bug is causing real-world problems in automake-generated Makefiles. 
This is a simplified piece of Makefile from automake:
all : config.h
        $(MAKE) all-am

config.h : stamp-h1
        echo build config.h

stamp-h1 : config.h.in
        echo build stamp-h1
        rm -f stamp-h1
        touch config.h
        touch stamp-h1

config.h.in : am__configure_deps
        echo build config.h.in
        rm -f stamp-h1
        touch config.h.in

all-am :
        echo ALL-AM

Now, if you run this script, you trigger the bug:

touch config.h.in;sleep 1;touch am__configure_deps;sleep 1;touch config.h stamp-h1;make

- you see "build config.h.in", but the other files are not rebuild and 
all-am is executed
(the essential thing to trigger the bug is that make is run in the same 
second in which config.h and stamp-h1 were created)

The problem that really happens in a real build:

* The user runs autoheader && aclocal && automake && autoconf && ./configure && make -j4
* Configure runs ./config.status, ./config.status writes config.h and 
stamp-h1
* Make sees that am__configure_deps is newer than config.h.in
* Make runs the rule for config.h.in. It sets the new timestamp for 
config.h.in and deletes stamp-h1
* Now make sees that config.h.in has the same time as stamp-h1 (the 
timestamp is read from make's cache even if stamp-h1 no longer exists)
* Because of the same timestamp, make doesn't run the commands for 
stamp-h1 and config.h
* Make executes a subprocess to build the rule all-am

* The subprocess doesn't have the file cache of the parent process, so the 
subprocess knows that stamp-h1 is missing
* The subprocess sees a dependency config.h->stamp-h1, stamp-h1 doesn't 
exist
* The subprocess executes the rule for stamp-h1 which regenerates config.h 
- the problem is that this rule is executed in parallel with other rules 
that build C files that include config.h - changing config.h while it is 
being used results in build failure

Another possible solution for this bug would be to remove rm -f stamp-h1 
from config.h.in rule, but there is some complex explanation in 
/usr/local/share/automake-1.12/am/remake-hdr.am why rm -f stamp-h1 is 
there so it would likely fix one bug and trigger another one.

So it would be better to fix this in make.

Mikulas