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

From: Philip Guenther <[email-masked]>
Date: Thu, 6 Dec 2012 15:53:40 -0800

On Thu, Dec 6, 2012 at 2:02 PM, Mikulas Patocka
<[email-masked]> wrote:
> 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.

That's not the rule that make has always followed and, indeed, is
required by the standard to follow.  To quote POSIX:

        The make utility attempts to perform the actions required to ensure
        that the specified targets are up-to-date. A target is considered
        out-of-date if it is older than any of its prerequisites or if
it does not
        exist. The make utility shall treat all prerequisites as targets
        themselves and recursively ensure that they are up-to-date, processing
        them in the order in which they appear in the rule. The make utility
        shall use the modification times of files to determine whether the
        corresponding targets are out-of-date.

The fact that the timestamp on a prerequisite has changed do *not*
mean that it's newer than the target; it may have been copied from
some other file which, while newer, is still older than the target
file.  So the change to the make algorithm described in the paragraph
above that starts "I think it is a bug" would not be correct;
something more precise about what timestamps would be considered
"newer" would be necessary.

Note that this problem doesn't arise on systems with high precision
file timestamps.  Many systems have provided those since the mid 90's;
I'm appalled that the modern system that process the involved shell
commands fast enough for this to regularly be a problem don't provide
microsecond or better timestamp precision.

> 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)
...
> 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.

Hmm, adding a "sleep 1" after that rm -f and before the touch
config.h.in would work without reintroducing the issue described in
that explanation, no?

Philip Guenther