On Fri, Feb 28, 2025 at 13:54:45 -0500, Paul Smith wrote:
> 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).

Ah! Yes, that is a difference. Ninja records the "last run" mtime as a
"shadow mtime" for the rule in its `.ninja_log` file. This is the mtime
used when deciding to rerun the rule or not. Another difference is that
this also encodes the command line last used for the output(s), so if
*that* changes, it is also considered out-of-date. CMake has command
line change detection, but it is much coarser: there's a file with
information about all command lines in a given target and if that file
changes, all commands in the target rerun.

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

Yes, this is reminding me of details I had eventually compressed to
"restat behavior isn't supported in make": it *works*, but is not
*useful* because it never results in a "do nothing" build.

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

If it does happen, it would be *wonderful* to reuse `ninja`'s
`.ninja_log` format. That would allow the usage of tools like
`ninjatracing`[1] to get performance graphs of arbitrary `make` builds.

Note that there is one fairly annoying thing with this in `ninja`: when
using `sudo ninja`, the log file is written using the elevated
permissions which makes further non-`sudo` usages…fail. See this issue:

    https://github.com/ninja-build/ninja/issues/1302

--Ben

[1] https://github.com/nico/ninjatracing

Reply via email to