Hi Paul,

> There is a straightforward and portable way to do this even with
> traditional make, it's just not as nice (but, nicer than changing all
> the recipes to use test IMO! :)).
> If you have a rule like this:
>   <a1> <b2> ... : <prereqs>
>           <command>
> where <command> generates all targets with one invocation, then your
> best bet is to modify this rule into two rules:
>   <a1> <b2> ... : .sentinel ;
>   .sentinel: <prereqs>
>           <command>
>           @touch $@
> Note, it's critical to include the semicolon here.  Or if you prefer to
> be more explicit you can write something like:
>   <a1> <b2> ... : .sentinel
>           : do nothing
> This will work properly.

Thanks for showing this idiom.

I think this can be improved a bit: Instead of 'touch .sentinel' I would
use 'echo > .sentinel'. Because if you use 'touch .sentinel' and the build
directory is on an NFS mount and the clock of the NFS server is ahead the
clock of localhost (I have seen this quite frequently), the timestamp of
.sentinel will be behind the timestamp of the newest <prereqs>, and thus
another "make" run will execute the rule again.

Still, I don't like these '.sentinel' or stamp files, because they
add complexity:
  * The developer has to decide whether the stamp file should go into
    the build dir or $(srcdir). The general rule should be that if
    <command> uses only build tools that are guaranteed to be present,
    then <a1> <b2> ... and the stamp file should go into the build dir,
    whereas if they use less common tools (e.g. bison), they should
    all go into $(srcdir).
  * The automake dist target needs to be adjusted to include this stamp
  * Version control (.gitignore) needs to be adjusted to include this
    stamp file.

I'll use the rule with a phony target and 'test ... -ot ...', unless you
find a problem with it (other than the potential portability problem
redarding 'test').


Reply via email to