Idea: Add .COMMANDCHANGE and .CACHE

classic Classic list List threaded Threaded
20 messages Options
Reply | Threaded
Open this post in threaded view
|

Idea: Add .COMMANDCHANGE and .CACHE

David A. Wheeler
Idea: Add .COMMANDCHANGE and .CACHE

Problem:

Paul Smith noted on Sun, 09 Jun 2019 22:11:32 -0400:
> Most of the requests I see these days that would require a "last state
> database" wouldn't be helped by md5 checks: mainly they're asking for
> things like rebuilding targets automatically when compiler options have
> changed etc. Things like that can be done today with a lot of fancy
> trickery but people would rather it "just worked".

As noted above, "make"
detects when *external* files change, but if a command *inside* a Makefile
changes (including its expanded parameters) then make doesn't notice the change.
This could be resolved if make could automatically notice a change in
expanded command. Doing this will require the ability to store state somehow.

In addition, sometimes recipes take a while, and it'd be nice to be able to
cache old results. If we have to store state anyway,
we may as well support caching previous results.


Proposed solution:

I propose a new special target .COMMANDCHANGE.
Its dependencies (or all targets if no target is listed) add an implied dependency
on the expanded commands of the rule.  Thus, if the commands (once expanded)
change, the rule will be considered obsolete & be rerun.

This requires a way to notice a change.  Instead of a conventional database
(which is hard to share across instances & can be complicated to implement),
I propose using a directory specified in MAKESTATE
(by default ".makestate") for storing shared state.

Every time a non-.PHONY expanded target with .COMMANDCHANGE and a non-empty rule
is being considered for execution, the
change state file $(MAKESTATE)/$(FIRST TARGET).sha256 is first examined.
If the file doesn't exist, or its contents do not match the SHA-256 hash
of the expanded command for that target, then the target is considered
out-of-date and the rule is re-run.
If the set of commands executes successfully, then its SHA-256 hash
is written to $(MAKESTATE)/$(FIRST TARGET).sha256
(after creating its directory if necessary).
(Note: this could be stored in a directory name, instead of file contents,
so file opening wouldn't be necessary.  However, that would make it
easy to have a weird inconsistent state where there are multiple entries,
and I think it's worth avoiding that problem.)

If first_target is an absolute path the state path
will still be in $(MAKESTATE) by treating the target name as beginning as ".TREEROOT".
E.g., if the target is /usr/share/mystuff/stuff,
then the change state file is .makestate//usr/share/mystuff/stuff.sha256.
(This might require some nonsense on Windows, but it's doable.)

In addition, if an executed rule is the target of .CACHE, has 1+ commands,
and MAKESTATECACHENUM is defined as a positive integer, then that rule's
execution results are cached:

* After after executing
  all of the generated targets are copied (preserving all metadata possible)
  into $(MAKESTATE)/$(FIRST_TARGET).cache/$(SHA256 of expanded command)/$(TARGET_NAME).
  It then looks at "$(MAKESTATE)/$(FIRST_TARGET).cache" to see if there are
  more than MAKESTATECACHENUM entries, and if so, recursively deletes
  the oldest entries to get it down to that number.
  My guess is MAKESTATECACHENUM should default to 3.
* Before executing a rule that's outdated, check for
   $(MAKESTATE)/$(FIRST_TARGET).cache/$(SHA256 of expanded command)/$(TARGET_NAME).
   If it exists, copy its contents to the appropriate targets and *delete* targets
   of the rule if there's no corresponding entry.
   Note that .TREEROOT still applies.

I suspect .COMMANDCHANGE is a terrible name; better ones welcome.

--- David A. Wheeler


_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add .COMMANDCHANGE and .CACHE

Britton Kerin
On Mon, Jun 10, 2019 at 9:20 AM David A. Wheeler <[hidden email]> wrote:

>
> Idea: Add .COMMANDCHANGE and .CACHE
>
> Problem:
>
> Paul Smith noted on Sun, 09 Jun 2019 22:11:32 -0400:
> > Most of the requests I see these days that would require a "last state
> > database" wouldn't be helped by md5 checks: mainly they're asking for
> > things like rebuilding targets automatically when compiler options have
> > changed etc. Things like that can be done today with a lot of fancy
> > trickery but people would rather it "just worked".
>
> As noted above, "make"
> detects when *external* files change, but if a command *inside* a Makefile
> changes (including its expanded parameters) then make doesn't notice the change.
> This could be resolved if make could automatically notice a change in
> expanded command. Doing this will require the ability to store state somehow.

The trickery required is not too fancy:

     foo.o: foo.c Makefile
             ...
or

     foo.o: foo.c $(PARANOID_REBUILD)
             ...

Then use when desired:
     (export PARANOID_REBUILD=Makefile && Make)

I do something like one or other (depending on project size) of these
most everywhere.

> In addition, sometimes recipes take a while, and it'd be nice to be able to
> cache old results. If we have to store state anyway,
> we may as well support caching previous results.

This is IMO an entirely new and mostly orthogonal project from Make,
and there is
already ccache (and presumably similar things for other langs).

Britton

>
>
> Proposed solution:
>
> I propose a new special target .COMMANDCHANGE.
> Its dependencies (or all targets if no target is listed) add an implied dependency
> on the expanded commands of the rule.  Thus, if the commands (once expanded)
> change, the rule will be considered obsolete & be rerun.
>
> This requires a way to notice a change.  Instead of a conventional database
> (which is hard to share across instances & can be complicated to implement),
> I propose using a directory specified in MAKESTATE
> (by default ".makestate") for storing shared state.
>
> Every time a non-.PHONY expanded target with .COMMANDCHANGE and a non-empty rule
> is being considered for execution, the
> change state file $(MAKESTATE)/$(FIRST TARGET).sha256 is first examined.
> If the file doesn't exist, or its contents do not match the SHA-256 hash
> of the expanded command for that target, then the target is considered
> out-of-date and the rule is re-run.
> If the set of commands executes successfully, then its SHA-256 hash
> is written to $(MAKESTATE)/$(FIRST TARGET).sha256
> (after creating its directory if necessary).
> (Note: this could be stored in a directory name, instead of file contents,
> so file opening wouldn't be necessary.  However, that would make it
> easy to have a weird inconsistent state where there are multiple entries,
> and I think it's worth avoiding that problem.)
>
> If first_target is an absolute path the state path
> will still be in $(MAKESTATE) by treating the target name as beginning as ".TREEROOT".
> E.g., if the target is /usr/share/mystuff/stuff,
> then the change state file is .makestate//usr/share/mystuff/stuff.sha256.
> (This might require some nonsense on Windows, but it's doable.)
>
> In addition, if an executed rule is the target of .CACHE, has 1+ commands,
> and MAKESTATECACHENUM is defined as a positive integer, then that rule's
> execution results are cached:
>
> * After after executing
>   all of the generated targets are copied (preserving all metadata possible)
>   into $(MAKESTATE)/$(FIRST_TARGET).cache/$(SHA256 of expanded command)/$(TARGET_NAME).
>   It then looks at "$(MAKESTATE)/$(FIRST_TARGET).cache" to see if there are
>   more than MAKESTATECACHENUM entries, and if so, recursively deletes
>   the oldest entries to get it down to that number.
>   My guess is MAKESTATECACHENUM should default to 3.
> * Before executing a rule that's outdated, check for
>    $(MAKESTATE)/$(FIRST_TARGET).cache/$(SHA256 of expanded command)/$(TARGET_NAME).
>    If it exists, copy its contents to the appropriate targets and *delete* targets
>    of the rule if there's no corresponding entry.
>    Note that .TREEROOT still applies.
>
> I suspect .COMMANDCHANGE is a terrible name; better ones welcome.
>
> --- David A. Wheeler
>
>
> _______________________________________________
> Bug-make mailing list
> [hidden email]
> https://lists.gnu.org/mailman/listinfo/bug-make

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add .COMMANDCHANGE and .CACHE

David A. Wheeler
On Mon, 10 Jun 2019 12:10:26 -0800, Britton Kerin <[hidden email]> wrote:

> The trickery required is not too fancy:
>
>      foo.o: foo.c Makefile
>              ...
> or
>
>      foo.o: foo.c $(PARANOID_REBUILD)
>              ...
>
> Then use when desired:
>      (export PARANOID_REBUILD=Makefile && Make)

No.

That's not at *ALL* the same thing.  With those uses, *all* rules
are rerun if *ANY* change happens in the Makefile, even if almost
all the rules and parameters do not change at all.
Since the whole point of make is to "only run what's needed",
that doesn't resolve the problem at all.

In contrast, ".COMMANDCHANGE" would only run a rule
if that PARTICULAR rule changed (once expanded) in the Makefile.
In many cases that would skip much of the work.
Which is the point.


> > In addition, sometimes recipes take a while, and it'd be nice to be able to
> > cache old results. If we have to store state anyway,
> > we may as well support caching previous results.
>
> This is IMO an entirely new and mostly orthogonal project from Make,
> and there is
> already ccache (and presumably similar things for other langs).

Caching is new functionality, that's why it's a proposal :-).

But I don't think it's orthogonal.

(1) The point of make is to "do only the tasks that are needed";
  Caching previous results seems like a very reasonable part
  of the definition of doing only what's needed.
(2) Not all languages have a ccache-like functionality.
(3) make is widely used for tasks other than compiling source code
   (e.g., to implement data processing pipelines), which again
   means that they don't have a ccache-like ability
(4) Implementing caches in make solves the problem *once* for
  *all* uses of make, instead of requiring every user to recreate it.
(5) Make is in a very good spot to know what's going to be done.
(6) The implementation will be trivial, probably ~20 lines of code
  plus the hashing function.  While the functionality will be significant
  for *users*, there should be practically no maintenance burden
  due to its small size.

--- David A. Wheeler
_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add .COMMANDCHANGE and .CACHE

Britton Kerin
In reply to this post by David A. Wheeler
On Mon, Jun 10, 2019 at 2:18 PM David A. Wheeler <[hidden email]> wrote:

>
> On Mon, 10 Jun 2019 12:10:26 -0800, Britton Kerin <[hidden email]> wrote:
> > The trickery required is not too fancy:
> >
> >      foo.o: foo.c Makefile
> >              ...
> > or
> >
> >      foo.o: foo.c $(PARANOID_REBUILD)
> >              ...
> >
> > Then use when desired:
> >      (export PARANOID_REBUILD=Makefile && Make)
>
> No.
>
> That's not at *ALL* the same thing.  With those uses, *all* rules
> are rerun if *ANY* change happens in the Makefile, even if almost

No, just the rules that :Makefile, which you can easily tune if it matters.
Heck, you can include some_fragment.mk that has the recipes that
are a concern and depend on that if you really need that granularity,
and then the dependency that you want is explicit.

> all the rules and parameters do not change at all.
> Since the whole point of make is to "only run what's needed",
> that doesn't resolve the problem at all.
>
> In contrast, ".COMMANDCHANGE" would only run a rule
> if that PARTICULAR rule changed (once expanded) in the Makefile.
> In many cases that would skip much of the work.
> Which is the point.

I get it, I just doubt it's worth the extra feature for something that
can be expressed in terms of existing features.

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add .COMMANDCHANGE and .CACHE

David A. Wheeler
On Mon, 10 Jun 2019 15:40:53 -0800, Britton Kerin <[hidden email]> wrote:
> No, just the rules that :Makefile, which you can easily tune if it matters.
> Heck, you can include some_fragment.mk that has the recipes that
> are a concern and depend on that if you really need that granularity,
> and then the dependency that you want is explicit.

Using a lot of some_fragment.mk files gets you *closer*, but it's not
the same thing.  My proposed .COMMANDCHANGE depends on
the *expanded* set of commands, not the original commands.
That way, if you change a value (say CCFLAGS) the set of commands
is considered *different* and will be re-run.

For example:

In file x.c.mk:
x.o: x.c
<TAB>$(CC) $(CCFLAGS) -o x.o x.c

In file Makefile:
include x.c.mk

main: x.o x.c.mk
...


Let's say I run this with:
  make CCFLAGS="-O1" main
and in run #2 say:
  make CCFLAGS="-O3" main

In run #2 the file x.c.mk has not changed,
and x.o is still after x.c.
Therefore, x.o will not be regenerated.

If we add:
.COMMANDCHANGE:

then a change to CCFLAGS *will* cause re-execution
of the rule that generates x.o.

--- David A. Wheeler

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add .COMMANDCHANGE and .CACHE

David A. Wheeler
In reply to this post by David A. Wheeler
On further reflection I noticed a bug in my .CACHE proposal.

Below is a discussion of the bug, and my proposed solution to it.
The proposed solution turns out to be a minor change,
but it might not be obvious why it needed changing.
So I'm explaining that in detail below.

TL; DR version: If .CACHE is enabled, the cache contents
are stored in a filesystem key constructed this way:
 $(MAKESTATE)/$(FIRST_TARGET).cache/$(quick_hash).sha256/$(slow_hash).sha256/

The result is that users can add a simple ".CACHE" entry
in their Makefile, and magically get caching for whatever they want
cached.  That's nice functionality for what I expect will be
relatively few lines of code.  Sure, users can write code to cache
things themselves, but I think getting that functionality with
a single additional line in the Makefile is valuable.

--- David A. Wheeler

================================

Bug:

I proposed both .COMMANDCHANGE and .CACHE simultaneously
because they both require a database of past activity
(in my proposal, the database is stored in the filesystem).
However, they have a difference my first proposal didn't fully
account for.

The ".COMMANDCHANGE" only needs to detect when a rule
needs to be *rerun* even if all the prerequisites are older than the targets.
Thus, I believe the SHA256 of the expanded command (as proposed)
is enough to work.

I proposed that .CACHE use the first target name and the
"$(SHA256 of expanded command)" as the key for data retrieval, but
in fact this does *not* work. The cached results depend on many things
*OTHER* than the contents of the expanded command, in particular,
they depend on the filenames & contents of all inputs of the command
(we'll assume that they are all identified as prerequisites)
and all the filenames of the targets.

So we need to replace "$(SHA256 of expanded command)"
with something else that depends not only on the expanded command,
but also on all the exact prerequisite names and their file contents.


Solution:

First: In many cases we do *NOT* want to read the contents of all the inputs,
because the inputs may be large.  So we should find a way to
quickly detect important differences without always reading entire files.

So instead, let's do two calculations:
1. a quick hash calculation that's also based on target names (in order) and file lengths.
   We'll differentiate between a 0-length existing file and a non-existent file;
    .PHONY targets always don't exist (for this purpose).
2. A slower hash calculation that's based on the contents of all the prerequisites.
    We only do this calculation if the quick calculation says we might be
    able to use the cache.

The proposal is to tweaked as follows when .CACHE is applied to a rule.
The cached results (using the target names)
of a rule execution will be stored and later retrieved
from a directory with the following name:
 $(MAKESTATE)/$(FIRST_TARGET).cache/$(quick_hash).sha256/$(slow_hash).sha256/

The hashes are calculated as possible:

quick_hash_data = sequence of "prerequisite info", blank line, and expanded command line.
  Each "prerequisite info" is the expanded prerequisite name,
  tab, its file length (empty if non-existent including .PHONY prerequisites),
  and a terminating newline.
  This is followed by a single newline-only blank line.
  This is followed by the expanded-by-make command line with a terminating newline
  (note that the *expanded* version is used, so if $(CFLAGS) is referenced in the command,
  and the user changes the CFLAGS value, then the quick_hash_data will be different).
quick_hash = sha256(quick_hash_data)
slow_hash_data = sequence of newline-terminated sha256(prerequisite contents)
slow_hash = sha256(slow_hash_data)

Note that slow_hash is a "hash of hash".  This means that, for example,
text moving from the end of one prerequisite to the beginning of the
next prerequisite will still cause completely different hashes.

When trying to determine if a cached value is available, the
quick_hash is calculated first & the directory checked.
If any prerequisite name changes, or if any length changes, then
the cache will change, so in many cases we can quickly determine
if a cache changed without completely reading possibly-big files.

To help cache debugging, I suggest that the directory
 $(MAKESTATE)/$(FIRST_TARGET).cache/$(quick_hash)
include a file named "quick_hash" which contains the quick_hash_data.
This can be written when the other cached values are written.

Note that if automatic variables are used in the command,
that continues to be a non-problem.  The automatic variables are expanded before
being included in the command hash, so their changes will be detected.
In particular, if "$?" is used in the command it will be expanded and then
have its SHA256 calculated, so differences in $? will cause the cache to
be ignored (that's the safest course, so that's a good thing).

I've been using SHA256, but another hash algorithm could be used.
We probably don't need every digit; we can cut off after a certain
reasonable number of digits.

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add .COMMANDCHANGE and .CACHE

Britton Kerin
In reply to this post by David A. Wheeler
On Mon, Jun 10, 2019 at 5:14 PM David A. Wheeler <[hidden email]> wrote:

>
> On Mon, 10 Jun 2019 15:40:53 -0800, Britton Kerin <[hidden email]> wrote:
> > No, just the rules that :Makefile, which you can easily tune if it matters.
> > Heck, you can include some_fragment.mk that has the recipes that
> > are a concern and depend on that if you really need that granularity,
> > and then the dependency that you want is explicit.
>
> Using a lot of some_fragment.mk files gets you *closer*, but it's not
> the same thing.  My proposed .COMMANDCHANGE depends on
> the *expanded* set of commands, not the original commands.
> That way, if you change a value (say CCFLAGS) the set of commands
> is considered *different* and will be re-run.

I know, but you can put whatever you want in included files, including
variables.  You can't capture eg vars from the environment but if you're doing
much of that you're missing half the  point of make anyway (recipe capture).
You want make to add implicit dependencies on recipes, which is both a
different granularity than everything else in make (sub-file) and implicit
rather than explicit.  Seems somewhat weird.

And I think cache is harder that you're imagining to get right.  Plenty of make
files use some explicitly mentioned target as a proxy for other unmentioned
files which may be created in dependencies.  So you'd probably want to have all
the recipes in dependencies of a target represented in it's key.

All that said I have to admit I don't mind the idea as much as I did when I
first heard it.  Who knows by tomorrow I may like it :)

Britton

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add .COMMANDCHANGE and .CACHE

David A. Wheeler
On Mon, Jun 10, 2019 at 5:14 PM David A. Wheeler <[hidden email]> wrote:
> > Using a lot of some_fragment.mk files gets you *closer*, but it's not
> > the same thing.  My proposed .COMMANDCHANGE depends on
> > the *expanded* set of commands, not the original commands.
> > That way, if you change a value (say CCFLAGS) the set of commands
> > is considered *different* and will be re-run.

On Tue, 11 Jun 2019 04:14:04 -0800, Britton Kerin <[hidden email]> wrote:
> I know, but you can put whatever you want in included files, including
> variables.  You can't capture eg vars from the environment but if you're doing
> much of that you're missing half the  point of make anyway (recipe capture).

As you noted, in many ways that's misusing make.

If there's a weird special case where that's important,
there's a simple solution for that: simply
expand the environment variable in the recipe somewhere.
E.g., if the commands depend on the setting of env variables
$FOO and $BAR but you never pass them, you could do this:

BB: CC
<TAB>@printf '' "$FOO" "$BAR"
<TAB>do-stuff

And now when the command is expanded and hashed,
changing FOO or BAR will cause the rule to be considered obsolete.

> All that said I have to admit I don't mind the idea as much as I did when I
> first heard it.  Who knows by tomorrow I may like it :)

Come to the dark side, we have cookies!

--- David A. Wheeler

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add .COMMANDCHANGE and .CACHE

Edward Welbourne-3
On Mon, Jun 10, 2019 at 5:14 PM David A. Wheeler <[hidden email]> wrote:
>>> Using a lot of some_fragment.mk files gets you *closer*, but it's not
>>> the same thing.  My proposed .COMMANDCHANGE depends on
>>> the *expanded* set of commands, not the original commands.
>>> That way, if you change a value (say CCFLAGS) the set of commands
>>> is considered *different* and will be re-run.

On Tue, 11 Jun 2019 04:14:04 -0800, Britton Kerin <[hidden email]> wrote:
>> I know, but you can put whatever you want in included files, including
>> variables.  You can't capture eg vars from the environment but if you're doing
>> much of that you're missing half the  point of make anyway (recipe capture).

David A. Wheeler (11 June 2019 15:19)
> As you noted, in many ways that's misusing make.

A fairly common change between runs of make is to select between
optimised (release) builds and variously instrumented builds (debug,
coverage, ...).  While I always prefer to do out-of-source builds and
have a separate build tree for each flavour of build, building in the
source tree is a conventional and widespread practice.  One then has to
make clean when switching between flavours.  Having make recognise when
the command it would run is different from what it last ran, as another
reason to run the command (just like a changed prerequisite), would save
that need to make clean (which it's all too easy to forget).

        Eddy.

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add .COMMANDCHANGE and .CACHE

thutt
Edward Welbourne writes:
 > On Mon, Jun 10, 2019 at 5:14 PM David A. Wheeler <[hidden email]> wrote:
 > >>> Using a lot of some_fragment.mk files gets you *closer*, but it's not
 > >>> the same thing.  My proposed .COMMANDCHANGE depends on
 > >>> the *expanded* set of commands, not the original commands.
 > >>> That way, if you change a value (say CCFLAGS) the set of commands
 > >>> is considered *different* and will be re-run.
 >
 > On Tue, 11 Jun 2019 04:14:04 -0800, Britton Kerin <[hidden email]> wrote:
 > >> I know, but you can put whatever you want in included files, including
 > >> variables.  You can't capture eg vars from the environment but if you're doing
 > >> much of that you're missing half the  point of make anyway (recipe capture).
 >
 > David A. Wheeler (11 June 2019 15:19)
 > > As you noted, in many ways that's misusing make.
 >
 > A fairly common change between runs of make is to select between
 > optimised (release) builds and variously instrumented builds (debug,
 > coverage, ...).  While I always prefer to do out-of-source builds and
 > have a separate build tree for each flavour of build, building in the
 > source tree is a conventional and widespread practice.  One then has to
 > make clean when switching between flavours.  Having make recognise when
 > the command it would run is different from what it last ran, as another
 > reason to run the command (just like a changed prerequisite), would save
 > that need to make clean (which it's all too easy to forget).

 Considering that many build systems created with Make do not properly
 perform incremental builds (because all the necessary rules are not
 written, or are written incorrectly), it's also a way to trivially
 make a build that is mysteriously broken because one or more files
 will not be properly rebuilt.

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add .COMMANDCHANGE and .CACHE

Paul Smith-20
In reply to this post by David A. Wheeler
On Mon, 2019-06-10 at 13:14 -0400, David A. Wheeler wrote:
> Idea: Add .COMMANDCHANGE and .CACHE

Unlike some of the other ideas I think this one needs a lot of thought
and consideration.  To me it seems the most complex and the most likely
to have unintended side-effects or for the implementation to fail to
meet the needs of users in a way which makes it hard to use generally,
unless it's thought about deeply.

It's good to start thinking about what a feature like this would
entail, but I would leave it until last.  At least.


_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add .COMMANDCHANGE and .CACHE

David A. Wheeler
> On Mon, 2019-06-10 at 13:14 -0400, David A. Wheeler wrote:
> > Idea: Add .COMMANDCHANGE and .CACHE

On Tue, 11 Jun 2019 11:06:51 -0400, Paul Smith <[hidden email]> wrote:
> Unlike some of the other ideas I think this one needs a lot of thought
> and consideration.  To me it seems the most complex and the most likely
> to have unintended side-effects or for the implementation to fail to
> meet the needs of users in a way which makes it hard to use generally,
> unless it's thought about deeply.
>
> It's good to start thinking about what a feature like this would
> entail, but I would leave it until last.  At least.

I'm fine with working on these later after other things.

I think .COMMANDCHANGE (possibly with a new name) is not a big issue.
It's a *conservative* change from the point of view of correctness.

I *do* understand that there are reasonable concerns about .CACHE.
Like any cache, if it's given incorrect inputs it will produce incorrect outputs.
However, I think there are ways to mitigate that risk,
it's purely opt-in, it gives a potential massive speed increase, and
it's an addition that can be used by a large number of make users.
People really like massive speed increases :-).

Details below.

--- David A. Wheeler


============= DETAILS ===============================

I think .COMMANDCHANGE is not complex.
Since it caches the expanded command, at worst it will re-run a script
when before it would not have done so.
So it's relatively low risk; at worst, it'll run a command more often than before.
It won't rerun if only an environment variable changes, but that is *already* true.
I'm hoping that there's a better name than .COMMANDCHANGE.

I *agree* that .CACHE is more complex to use.
Its implementation is NOT complex - indeed, it can be
implemented in relatively few lines of code.
The challenge is that while .COMMANDCHANGE causes execution
to happen more than now, .CACHE can cause an execution to be
*completely* skipped and its cache results would be used instead.

The risk of .CACHE is that it can produce "wrong results", and
that is a valid concern.  In any cache system (including this one)
the cache key must be calculated from an absolutely complete
set of all relevant inputs, and the output (target) list *must*
be a complete statement of the resulting targets.
If there are multiple targets, using "&:" (not ":") may be critically
important, not just something that can be caught on the next
run of "make".  If environment variables' settings matter, they
need to be included in the inputs.  For example, the environment variables
could be expanded somewhere in the command (e..g, @printf '' "$MYVAR").
That means that .CACHE makes the system even more dependent
on accurate statements about targets & prerequisites.
For example: I didn't include read/write/execute permissions of prerequisites
in the inputs to the cache keys on purpose.  However, technically their
permission values can have an effect, and the current .CACHE doesn't handle that.

I'd love to hear ways of reducing the risks of .CACHE.  Some ideas:
1. We could define a "CACHEENV" variable, a list of all environment variables
   whose expansions would be included in the cache key.
   Adding a few environment variables to this list would mean that changing any
   of them would cause current cached values to be skipped.
2. When multiple targets are listed in a traditional rule (":" not "&:"),
   after running a rule in non-parallel mode, check to see if any of the
   other targets were modified.  If they were, warn or error out & explain the problem
   ("use &: instead of :, or create an intermediary value on line XYZ").
   This might be a good idea anyway, even if .CACHE isn't added...
   I just got bit by this mistake yesterday!  Automatically detecting common
   mistakes, and warning about them, is often a great idea.

I think it's still worth eventually having .CACHE.  Make already requires that
dependencies be accurately stated, and people
are already using cache systems like ccache.

When a new release of GNU Make comes out, some people may just
wonder "why would I want that?".  It's very valuable to support advanced
features, but if you haven't encountered the use case it may be hard for
people to appreciate a feature's advantages.  It will be *easy* to explain
why people might want a cache built into GNU make: if it works, their
edit-compile-run cycle time could be drastically reduced *regardless*
of what they use make for.
That would make caching, all by itself, a reason to upgrade to
a later version of GNU make.

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add .COMMANDCHANGE and .CACHE

Britton Kerin
> I think .COMMANDCHANGE is not complex.
> Since it caches the expanded command, at worst it will re-run a script
> when before it would not have done so.
> So it's relatively low risk; at worst, it'll run a command more often than before.
> It won't rerun if only an environment variable changes, but that is *already* true.

True but it's a sort of misleading way to look at things.  With .COMMANDCHANGE
you're effectively saying "add this thing and you can efficiently intermingle
build system changes with other development without worry".  Fail to deliver on
that promise and the feature will likely cause net pain.

> I'm hoping that there's a better name than .COMMANDCHANGE.
>
> I *agree* that .CACHE is more complex to use.
> Its implementation is NOT complex - indeed, it can be
> implemented in relatively few lines of code.
> The challenge is that while .COMMANDCHANGE causes execution
> to happen more than now, .CACHE can cause an execution to be
> *completely* skipped and its cache results would be used instead.
>
> The risk of .CACHE is that it can produce "wrong results", and
> that is a valid concern.  In any cache system (including this one)
> the cache key must be calculated from an absolutely complete
> set of all relevant inputs, and the output (target) list *must*
> be a complete statement of the resulting targets.
> If there are multiple targets, using "&:" (not ":") may be critically
> important, not just something that can be caught on the next

I'm unlikely to ever use &, because I predate it by decades and  stamps/proxies
have always worked fine for me (I've never been tempted to edit or delete a
proxied file and been burned as a result).  So it would be nice if
.COMMANDCHANGE/.CACHE still worked without &, and I think to be really correct
it must since nothing in existing make forbids these common arrangements.

> run of "make".  If environment variables' settings matter, they
> need to be included in the inputs.  For example, the environment variables
> could be expanded somewhere in the command (e..g, @printf '' "$MYVAR").
> That means that .CACHE makes the system even more dependent
> on accurate statements about targets & prerequisites.
> For example: I didn't include read/write/execute permissions of prerequisites
> in the inputs to the cache keys on purpose.  However, technically their
> permission values can have an effect, and the current .CACHE doesn't handle that.
>
> I'd love to hear ways of reducing the risks of .CACHE.  Some ideas:
> 1. We could define a "CACHEENV" variable, a list of all environment variables
>    whose expansions would be included in the cache key.
>    Adding a few environment variables to this list would mean that changing any
>    of them would cause current cached values to be skipped.

To be conservative and automatic I would probably include the entire
environment and then explicitly subtract out e.g. X/DBUS garbage if feature was
provided to do so.  I guess this could be done with text functions easily enough
too though.

 > 2. When multiple targets are listed in a traditional rule (":" not "&:"),
>    after running a rule in non-parallel mode, check to see if any of the
>    other targets were modified.  If they were, warn or error out & explain the problem
>    ("use &: instead of :, or create an intermediary value on line XYZ").
>    This might be a good idea anyway, even if .CACHE isn't added...
>    I just got bit by this mistake yesterday!  Automatically detecting common
>    mistakes, and warning about them, is often a great idea.

Again, I think what you really want is a key derived from all the recipes in
the entire dependency DAG of the target.  I think this picks up the case you're
considering here, plus others where significant side effects exist that aren't
explicitly mentioned in the DAG at all.

Britton

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add .COMMANDCHANGE and .CACHE

David A. Wheeler
On Tue, 11 Jun 2019 14:25:10 -0800, Britton Kerin <[hidden email]> wrote:

> > I think .COMMANDCHANGE is not complex.
> > Since it caches the expanded command, at worst it will re-run a script
> > when before it would not have done so.
> > So it's relatively low risk; at worst, it'll run a command more often than before.
> > It won't rerun if only an environment variable changes, but that is *already* true.
>
> True but it's a sort of misleading way to look at things.  With .COMMANDCHANGE
> you're effectively saying "add this thing and you can efficiently intermingle
> build system changes with other development without worry".  Fail to deliver on
> that promise and the feature will likely cause net pain.

True, but it's hard to image what could be missing.
This is already *WAY* more specific than what make normally does.

By default make doesn't consider the modification date of a script,
you have to even add THAT to the list of prerequisites.  When it's added to the
list of prerequisites, make *only* considers the modification time of the script,
and does NOT consider if the parameters used to call it
from the makefile (so if the parameters make change, it won't rerun).

.COMMANDCHANGE, by contrast, is FAR more conservative
than the typical use of commands as prerequisites.
If the any text in the script changes, or if anything changes in how its
parameters are expanded is changed, it will force a rerun.

If a key underlying environment variable changes then yes, it will be missed,
but that is *already* true in make, and at least in COMMANDCHANGE
you can include the environment variable in the key's data source.

I can't imagine what would be missing from .COMMANDCHANGE
that "make" normally considers.  Any other argument would already
be true for make as it is.

The argument changes for .CACHE of course.
In that, the failure mode is a bigger deal & there's a possibility that
something has been missed.  So let's discuss!!


> I'm unlikely to ever use &, because I predate it by decades and  stamps/proxies
> have always worked fine for me (I've never been tempted to edit or delete a
> proxied file and been burned as a result).  So it would be nice if
> .COMMANDCHANGE/.CACHE still worked without &, and I think to be really correct
> it must since nothing in existing make forbids these common arrangements.

.COMMANDCHANGE will work just fine if you don't use "&:"
and just use ":". For example, stamps and proxies will work very nicely.
For example, if you say:
~~~~
BB CC: .COMMANDCHANGE DD EE
<TAB>command
~~~~
Then for BB and CC there will be *separate* hashes that record
the command run for them.

The issue with .CACHE is more complicated.
Any caching system needs to know:
(1) what inputs could affect the output, and
(2) what the outputs are.

When determining the outputs (#2): if there's one target
*OR* there are multiple targets expressed using "&:",
then the answer is easy.

The bigger problem is when there are multiple outputs
AND they are not listed in a single rule.  Detecting when someone
did "BB CC: ..." and expected it to mean "BB CC &:" will prevent
*that* mistake.  If the user switches to "&:" then no issue.

BUT: If the user uses an intermediate marker, then maybe we
need to do more.  It's conventional use this construct
to indicate when multiple outputs are generated from a single command:

~~~~
BB CC: marker ;
maker: prerequisites
<TAB>command
~~~~

If we naively ran the "marker" rule with .CACHE, then
the cache would only have the marker - not BB or CC. Whups.

One solution comes to mind: when "make"ing a ":" rule
with a single target "marker", look for all the rules that depend ONLY
on that marker (ignoring special targets) and have a
present-but-empty rule.  Their targets are always considered
as the additional outputs of creating marker
when creating a .CACHE.  It's an odd rule, but I think it
solves the problem with generality.  Traditionally this is how
"multiple outputs from a single recipe" is represented, so
to cache the outputs we need to detect that traditional representation.

> To be conservative and automatic I would probably include the entire
> environment and then explicitly subtract out e.g. X/DBUS garbage if feature was
> provided to do so.  I guess this could be done with text functions easily enough
> too though.

I imagine we could have some sort of setting that did that, i.e.,
"include everything in environment EXCEPT these environment variables".

> Again, I think what you really want is a key derived from all the recipes in
> the entire dependency DAG of the target.  I think this picks up the case you're
> considering here, plus others where significant side effects exist that aren't
> explicitly mentioned in the DAG at all.

I think that's way too conservative.  If the inputs are the same, and the
command produces the same outputs from the same inputs, that should
be enough.  The dependency DAG is already captured in the dependency tree
that make already processes.

--- David A. Wheeler

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Idea: Add command-line option for reporting potential makefile errors

David A. Wheeler
In reply to this post by thutt
Problem:

Makefiles often have errors, and they lay dormant because they're undetected.

On Tue, 11 Jun 2019 07:44:31 -0700, <[hidden email]> wrote:
>  Considering that many build systems created with Make do not properly
>  perform incremental builds (because all the necessary rules are not
>  written, or are written incorrectly), it's also a way to trivially
>  make a build that is mysteriously broken because one or more files
>  will not be properly rebuilt.

Of course, that's a potential problem for *any* use of make.
Garbage in, garbage out.  I use automated dependency generation
where I can, but the generators can have bugs & not
all situations have a generator.


Potential solution:

Perhaps there should be a make flag that attempts to detect & warn
about missing dependency information during make execution,
to help people fix their makefiles.

Basically, when running a rule, make could enable strace to see
what is *actually* getting checked/read & written, compare that to what the
rule *claims* are the prerequisites & targets, and then complain about differences.

I did some brief experiments using:
 strace -f -e trace=%file gcc -o b.o b.c

As expected, there are a huge number of special-case events.
But if you only consider file-related events in a specific directory or down
(which could probably default to the current directory), including
relative paths, most of the events that would not normally go in a
makefile disappear. It's also helped if you limit the set of system calls that
need to be considered (e.g., openat is really important on Ubuntu).

It might be much easier if this required other tools (like strace) to work,
instead of directly implementing the tracing in make.
This mechanism could be slow, but that's okay; I envision doing this
checking occasionally, instead of doing it on every run.
This might not be implemented on all platforms, but it would be useful
on many platforms & help people fix their makefiles for all.

--- David A. Wheeler

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add command-line option for reporting potential makefile errors

Tim Murphy-4
If you use strace to detect dependencies you might have to do a thorough patent search. I will say no more because it's not my place to.

Regards

Tim

On Wed, 12 Jun 2019, 03:09 David A. Wheeler, <[hidden email]> wrote:
Problem:

Makefiles often have errors, and they lay dormant because they're undetected.

On Tue, 11 Jun 2019 07:44:31 -0700, <[hidden email]> wrote:
>  Considering that many build systems created with Make do not properly
>  perform incremental builds (because all the necessary rules are not
>  written, or are written incorrectly), it's also a way to trivially
>  make a build that is mysteriously broken because one or more files
>  will not be properly rebuilt.

Of course, that's a potential problem for *any* use of make.
Garbage in, garbage out.  I use automated dependency generation
where I can, but the generators can have bugs & not
all situations have a generator.


Potential solution:

Perhaps there should be a make flag that attempts to detect & warn
about missing dependency information during make execution,
to help people fix their makefiles.

Basically, when running a rule, make could enable strace to see
what is *actually* getting checked/read & written, compare that to what the
rule *claims* are the prerequisites & targets, and then complain about differences.

I did some brief experiments using:
 strace -f -e trace=%file gcc -o b.o b.c

As expected, there are a huge number of special-case events.
But if you only consider file-related events in a specific directory or down
(which could probably default to the current directory), including
relative paths, most of the events that would not normally go in a
makefile disappear. It's also helped if you limit the set of system calls that
need to be considered (e.g., openat is really important on Ubuntu).

It might be much easier if this required other tools (like strace) to work,
instead of directly implementing the tracing in make.
This mechanism could be slow, but that's okay; I envision doing this
checking occasionally, instead of doing it on every run.
This might not be implemented on all platforms, but it would be useful
on many platforms & help people fix their makefiles for all.

--- David A. Wheeler

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add command-line option for reporting potential makefile errors

David Boyce-3
In reply to this post by David A. Wheeler
In this context it might be worth mentioning two projects of mine, one simple/lightweight and the other complex and semi-abandoned. I will not describe them here in detail because the links do so.

1. Poor Man's File Auditor (https://github.com/boyski/pmaudit)

This is a lightweight, unambitious, but reliable way of figuring out which files were used during the course of a build. It works well in local disk and some NFS configurations; I'm currently battling some NFS caching issues which make its reliability dependent on things like server vendor and mount options. In other words the current version works for some NFS configurations and not yet others but it should work in any filesystem supporting the relatime mount option (which is the default in modern Linux). It's just a matter of figuring out how to force cache flushes which varies per server implementation.


This is/was a large project aimed at recording not only the files used by a given build but the commands as well, thus a goal similar to the .COMMANDCHANGE and .CACHE features being explored here. Rather than relying on strace/ptrace technology it intercepts system calls using LD_PRELOAD semantics. The original goal was to replicate the ClearCase file auditing and "wink-in" capabilities, for those who remember that system, in pure Linux without any special filesystem. It was going quite well some years ago but then, as often happens, my day job and personal life had other ideas so I had to drop it though not for any technical reason. IIRC the client (recording) side was stable on Linux; I'd also written a server to handle wink-ins from distributed builds but the first attempt was a mess. I had a design for a server rewrite which is where things stopped when I had to drop the project. However, the client works standalone for build auditing and I still use it from time to time. The output format is a little mysterious but it comes with a few Python scripts to parse and interpret it.

David B

On Tue, Jun 11, 2019 at 7:10 PM David A. Wheeler <[hidden email]> wrote:
Problem:

Makefiles often have errors, and they lay dormant because they're undetected.

On Tue, 11 Jun 2019 07:44:31 -0700, <[hidden email]> wrote:
>  Considering that many build systems created with Make do not properly
>  perform incremental builds (because all the necessary rules are not
>  written, or are written incorrectly), it's also a way to trivially
>  make a build that is mysteriously broken because one or more files
>  will not be properly rebuilt.

Of course, that's a potential problem for *any* use of make.
Garbage in, garbage out.  I use automated dependency generation
where I can, but the generators can have bugs & not
all situations have a generator.


Potential solution:

Perhaps there should be a make flag that attempts to detect & warn
about missing dependency information during make execution,
to help people fix their makefiles.

Basically, when running a rule, make could enable strace to see
what is *actually* getting checked/read & written, compare that to what the
rule *claims* are the prerequisites & targets, and then complain about differences.

I did some brief experiments using:
 strace -f -e trace=%file gcc -o b.o b.c

As expected, there are a huge number of special-case events.
But if you only consider file-related events in a specific directory or down
(which could probably default to the current directory), including
relative paths, most of the events that would not normally go in a
makefile disappear. It's also helped if you limit the set of system calls that
need to be considered (e.g., openat is really important on Ubuntu).

It might be much easier if this required other tools (like strace) to work,
instead of directly implementing the tracing in make.
This mechanism could be slow, but that's okay; I envision doing this
checking occasionally, instead of doing it on every run.
This might not be implemented on all platforms, but it would be useful
on many platforms & help people fix their makefiles for all.

--- David A. Wheeler

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add command-line option for reporting potential makefile errors

David A. Wheeler
In reply to this post by Tim Murphy-4
On Wed, 12 Jun 2019 19:22:09 +0100, Tim Murphy <[hidden email]> wrote:
> If you use strace to detect dependencies you might have to do a thorough
> patent search. I will say no more because it's not my place to.

The odds of an *enforceable* patent on strace seem extremely remote from
the information I could find.

In the US, utility patents last 20 years
from the earliest filing date of the application on which the patent was granted.
Strace was originally written in 1991-1992, and ported to Linux in 1993.
All patents through 1999-06-11 have expired, many years after strace was created.
We only need the basic capability provided by the strace of 1993, so
the probability that there is a problem *today* seems pretty remote.

In addition, if there's a valid patent on strace (a dubious premise),
there's a plausible defense that it's strace that is infringing and/or inducing infringement.

It's true that the PTO often grants patents to prior art, sometimes *long*
pre-existing prior art.  The problem of garbage patents is well-known.
The PTO doesn't grant enough review time (shame on the PTO), and
people are incentivized to submit fraudulent patents (shame on them).
But those fraudulent patents are, according to law, supposed to get tossed out by courts.
If avoiding garbage patents is the criterion, then no one could write software.

I have no way to do a "thorough" patent search if that phrase has some special meaning.
I'm not a lawyer, and I'm not being paid to do this.
If someone can do such searches for me, fantastic.
If someone has a specific patent number, let me know.
But since no one has decided to give me $BIGNUM to pay a lawyer,
I can only do what I can.

That said, I did use Google & searched for "strace patent".
I only found this:
  https://patents.google.com/patent/US8230399
I didn't read this patent in detail, because I found that it
describes something that is *NOT* strace
(strace is discussed to *contrast* what they propose). So that isn't relevant.

What's needed for this functionality is very basic "notice when the system
tries to check or open a file".  Many mechanisms use such services, not just this,
and you'd think they'd have been sued by now.

Thanks.

--- David A. Wheeler

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add command-line option for reporting potential makefile errors

Paul Smith-20
In reply to this post by David A. Wheeler
On Tue, 2019-06-11 at 22:09 -0400, David A. Wheeler wrote:
> Basically, when running a rule, make could enable strace to see
> what is *actually* getting checked/read & written, compare that to
> what the rule *claims* are the prerequisites & targets, and then
> complain about differences.

At this time my opinion is that this is a "bridge too far" and I'm not
inclined to accept any changes like this.  I feel that it's too far
outside of (what I consider) make's purview, too system-specific,
tricky to get right (consider recursion... are you going to be watching
all the submakes and all the things THEY watch?) etc.

As DavidB pointed out, there are already project that attempt to
provide some of these features and I'm perfectly fine with asking people who want them, to go find them.  And if you consult with him you'll no doubt learn that "just use strace" is far too simplistic for what is actually needed to make this work well.

I get that having a make that "does everying right out of the box" is
seductive, but I'm not on board at this point.

I would be willing to work with people who wanted to implement such
things as loadable modules in GNU make, to ensure that the loadable
module API is enhanced in such a way that writing a module like this is
feasible.  Currently it would be difficult since it's not easy to
modify the rules database through that API (you basically have to call
the eval function... which makes it possible but not ideal) and there
are no hooks into the module when running recipes themselves.

So, conversations about the existence or validity of patents in this
area are moot as far as I'm concerned :).


_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make
Reply | Threaded
Open this post in threaded view
|

Re: Idea: Add command-line option for reporting potential makefile errors

David A. Wheeler
On Wed, 12 Jun 2019 16:02:15 -0400, Paul Smith <[hidden email]> wrote:
> I get that having a make that "does everying right out of the box" is
> seductive, but I'm not on board at this point.

I actually don't care about whether or not it's "in the box" of make.
I care about making it easy to perform the check.
If it's something you have to separately install & invoke that's fine,
as long as it's *easy*.

However, it has to be *easy*.  The install must be no more than
"apt-get install make-audit" or "pip3 install make-audit" or similar.
Normal use must be no more than "make-audit [target]".
If it's any more complicated then that's a bug.  Nobody likes complicated
things for normal use cases.  It also needs to eventually handle make in
its full generality (e.g., if a user sets .ONESHELL to perl, it should still work).


> I would be willing to work with people who wanted to implement such
> things as loadable modules in GNU make, to ensure that the loadable
> module API is enhanced in such a way that writing a module like this is
> feasible.  

As long as there's a mechanism that works easily that'd be great.

However, it's not clear to me that the hooks needed are easily available.
Also, the loadable modules stuff requires that I have a compiled object.
That's a big pain to set up & makes it difficult to create an
easy-to-install system across platforms.

I'd rather be able to simply call a program or shell script.
If I'm calling a command I'm already paying a price anyway.
In the short term I can abuse .ONESHELL and SHELL=, but that will struggle
wrapping Makefiles that already use .ONESHELL and SHELL=.

Would there be an appetite for a new Makefile variable that could specify
how to wrap a command about to be executed?
I haven't worked out the details, but that would make much
easier to wrap programs & would be very general.

> As DavidB pointed out, there are already project that attempt to
> provide some of these features

I took a look at his Poor Man's File Auditor (https://github.com/boyski/pmaudit).
It doesn't quite do what I want, but his approach looks like a *much* more
promising direction than using strace.

Instead of trying to use strace, pmaudit simply checks the atime & mtime
before & after execution.  That's extraordinarily portable (it even works on Cygwin)
and FAR less fussy.  It can't monitor lstat & friends, but I think that's okay.
inotify can't notice lstats either, strace imposes a huge performance overhead, and
LD_PRELOAD is fussy & hard to keep up with (I know, I've done complicated things with it).
The pmaudit approach appears simple & rock-solid.

--- David A. Wheeler

_______________________________________________
Bug-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/bug-make