On Fri, 2025-02-28 at 19:26 +0100, Ben Boeckel via Gcc wrote:
> > In POSIX make, including GNU Make, if a command doesn't modify the
> > modification time of the target then that target is not considered
> > updated, and other targets which list it as a prerequisite are not
> > invoked:
> 
> Hmm. My understanding was that if a recipe is run, its outputs are
> assumed to have been updated. I forget where I saw that, but it
> sticks in my mind for some reason. Experimenting with GNU Make indeed
> does exhibit `restat = 1` behavior out-of-the-box. That's good to
> know :). I'll update my priors.

There is one issue related to this: I don't know if Ninja addresses
this or not: maybe this is what people were thinking of?

Because the modification time of the target is not updated, the recipe
for the the target will always be run (but targets that depend on it
will not be run).

E.g., in my previous example I had:

  ~$ touch three; make MKTWO=echo
  echo two
  two

Now if I run it again after touching "three", the command for "two" is
again run as you'd expect, and "one" is not since "two"'s timestamp is
not changed:

  ~$ touch three; make MKTWO=echo
  echo two
  two

BUT!  Now if I do NOT update "three", "two" is STILL updated, and will
continue to be as long as the "two" target's timestamp is not changed:

  ~$ make MKTWO=echo
  echo two
  two

  ~$ make MKTWO=echo
  echo two
  two

If the recipe to create "two" is complex/long-running then this is not
great.

Only when we allow "two" to actually be modified (in my example, by not
overriding the MKTWO variable), will we get back to "normal" behavior:

  ~$ make
  touch two
  touch one

  ~$ make
  make: 'one' is up to date.

This is the best that make can do, because it relies solely on the
filesystem as its database of "build state" and doesn't preserve any
build state of its own.  Since "two"'s timestamp was not modified make
has no way to know that its recipe was actually run previously.

If the recipe to build "two" is expensive, it's probably better to just
bite the bullet and allow "two" to be updated whenever its
prerequisites change.

The only way for make to do better would be for it to keep its own
database of up-to-date notations, alongside or in addition to the
filesystem's modification time.  That would be a major structural
change, of course.

Reply via email to