bug-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Static multiple target rules


From: tom honermann
Subject: Re: Static multiple target rules
Date: Wed, 31 Mar 2010 04:19:29 -0700
User-agent: Thunderbird 2.0.0.24 (Windows/20100228)

On 3/30/2010 11:35 PM, tom honermann wrote:
On 3/29/2010 8:20 PM, Philip Guenther wrote:
Hmm.  SysV make has offered the desired feature with the syntax

b1 + b2 + b3: d1
        touch -r $^ $@
 
Ah, thank you!  I wasn't aware of a precedent syntax for this feature.  I definitely agree with
using this syntax over what I proposed for compatibility with sysV and (potentially) future
POSIX standardization if the sysV semantics are adequate.  I'll run some tests with the
Solaris 10 version and follow up with comparisons with the semantics I had proposed.
I adapted my prior example for the sysV group target syntax and did some testing with
the Solaris 10 make implementation:
all: y.tab.h y.tab.c y.output y.tab.o

clean:
        rm -f y.tab.h y.tab.c y.output y.tab.o

grammar.y:
        @touch $@

y.tab.h + y.tab.c + y.output: grammar.y
        @echo "Running yacc..."
        @sleep 1
        @touch y.tab.h y.tab.c y.output

y.tab.o: y.tab.c y.tab.h
        @echo "Compiling y.tab.c..."
        @sleep 1
        @touch $@

This worked as expected and I wasn't able to trigger any undesirable behavior.  Solaris
make seems to delay or recheck time stamps such that the following steps will cause
y.tab.o to be rebuilt.  Note that only y.output is out of date when the last make invocation
is made, but make recognizes that y.tab.h and/or y.tab.c has been rebuilt and therefore
regenerates y.tab.o as well.  Exactly what is desired.
$ make
$ touch grammar.y
$ touch y.tab.h y.tab.c
$ touch y.tab.o
$ make
Running yacc...
Compiling y.tab.c...
I went on to evaluate some other behaviors using this example:
Makefile:
all: a1 a2 a3

clean:
        rm -f a1 a2 a3

d1:
        @touch $@

a1 + a2 + a3: d1
        @echo "  \$$@:    >$@<"
        @echo "  \$$%:    >$%<"
        @echo "  \$$(@D): >$(@D)<"
        @echo "  \$$(@F): >$(@F)<"
        @touch -r d1 $@
$ make clean
rm -f a1 a2 a3
$ make
  $@:    >a1<
  $%:    ><
  $(@D): >.<
  $(@F): >a1<

Note that $@ expanded to the first requested target (from the default 'all' rule).
Separate commands were not run for targets a2 and a3.  Had the targets been
normal targets instead of group targets, the commands would have been run
three times each to generate a1, a2, and a3.
$ make
  $@:    >a2<
  $%:    ><
  $(@D): >.<
  $(@F): >a2<

Note that 'make clean' was not run here.  The commands above did not
generate a2 during the first make invocation.  Make now notices this and
invokes the rule to build a2.
$ make
  $@:    >a3<
  $%:    ><
  $(@D): >.<
  $(@F): >a3<

Same thing again.  Now we're all up to date.

Solaris make allows group members to be phony targets, but there are caveats.  The
example above shows that the implementation doesn't check to make sure all group
members were actually generated (which is good and consistent with normal phony
target rules).  However, here are is an example showing behavior which I find
somewhat baffling:
all: b1 b2

clean:
        rm -f b1 b2

b1 + b2: d1
        @echo "  \$$@:    >$@<"
        touch b1

Consider the following output:
$ make clean
rm -f b1 b2
$ make b1 b2
  $@:    >b1<
touch b1
`b2' is updated.
b1 was requested first.  b2, though not generated, is considered up to date.
$ make clean
rm -f b1 b2
$ make b2 b1
  $@:    >b2<
touch b1
  $@:    >b1<
touch b1

In this case, b2 was requested first and the rules run.  However, Solaris make then
ran the rules again to generate b1.  I would have expected it to consider b1 up to
date once b2 was built.  The implementation apparently checks to see if the
requested target was actually completed and only considers the group up to date
if it was.

Solaris make (at least Solaris 10) does support multiple group targets.  For an
example, see my most recent email to the mail list.

Solaris make does support archive members as target group members as well.

Solaris make has support for the .IGNORE and .SILENT special targets
however, prerequisites for these are only supported when the special .POSIX
target is also specified.  When running commands for a target group member,
the current target is used to determine whether the .IGNORE or .SILENT
behavior is in effect.  For example:
all: i1 i2
all: s1 s2

clean:
    rm -f i1 i2 s1 s2

.POSIX:
.IGNORE: i2
i1 + i2: d1
        @echo "  \$$@:    >$@<"
        touch i1 i2
        exit 1

.SILENT: s2
s1 + s2: d1
        @echo "  \$$@:    >$@<"
        touch s1 s2

In the following example runs, the current target is always the first one specified
on the command line.
$ make clean
rm -f i1 i2 s1 s2
$ make i1 i2
  $@:    >i1<
touch i1 i2
exit 1
*** Error code 1
make: Fatal error: Command failed for target `i1'

$ make clean
rm -f i1 i2 s1 s2
$ make i2 i1
  $@:    >i2<
touch i1 i2
exit 1
*** Error code 1 (ignored)
`i1' is updated.

Note that the error was not ignored when the 1st target was i1, but the error was
ignored when the 1st target was i2.
$ make clean
rm -f i1 i2 s1 s2
$ make s1 s2
  $@:    >s1<
touch s1 s2
exit 0
`s2' is updated.

$ make clean
rm -f i1 i2 s1 s2
$ make s2 s1
  $@:    >s2<
`s1' is updated.

Note that commands were echoed when the 1st target was s1, but were not when
the 1st target was s2.

The differences in the Solaris make implementation vs what I had proposed include:

1: Obvious syntax differences.  The Solaris syntax prohibits nested groups which
is likely a good thing.

2: I had proposed that $@ and $% expand to include a list of all the target group
members.  Solaris make expands these to only include the current target.  For
compatibility, it makes the most sense to follow the Solaris model.  Additional
variables could be introduced that expand to the list of all targets (ie, $(@^)) or
archive members (ie, $(%^)) and perhaps another set of variables that expands
to the list of targets that are out of date (ie, $(@?) and $(%?)).  Combinations
for selecting directory and file parts would be possible as well: $(@^D) and
$(@^F) for example.

3: I had offered three possibilities for handling special targets that could have
conflicting settings across group members.  The Solaris make implementation
uses the third possibility I mentioned - using the attributes associated with the
current target (the group member first requested).  This makes sense to me.

All in all, the Solaris make implementation makes sense to me and would fit my
needs.  The only part about it that I feel concern about is how it handles phony
target group members.  But, there may not be good use cases for phony members.
I couldn't find any documentation addressing this for the Solaris make
implementation.

Tom.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]