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: Mon, 29 Mar 2010 19:54:35 -0700
User-agent: Thunderbird 2.0.0.24 (Windows/20100228)

On 3/2/2010 5:18 PM, tom honermann wrote:
On 3/2/2010 2:45 AM, Edward Welbourne wrote:
I've been struggling for some time now with how to write rules for commands that generate multiple targets
A familiar and annoying problem: make really believes in commands that
generate just one (relevant) file, and doesn't fit so well with ones
that generate several.
And yet, pattern rules do have such support. I'd love to see a syntax added to enable static multiple target rules. Since parenthesis are already treated specially in target names (for archive rules), perhaps a syntax like the following could be used without harming backward compatibility.

   (y.tab.h y.tab.c y.output): grammar.y
       yacc -d -v $^
Paul, would you be opposed to a patch that implements support for static multiple target rules using the above syntax? Any particular concerns or requirements you would have? I'm not sure when I
might find the time, but I might be able to put something together.

Here are some examples of how I think the functionality should work:

   (y.tab.h y.tab.c y.output): grammar.y
       yacc -d -v $^

Any request for y.tab.h, y.tab.c, or y.output would result in a single execution of the rule. Timestamps would be updated for all three targets regardless of which target(s) were requested. Parallel builds would recognize requests for any of these targets as requiring a
single invocation of the rule.

   a1 (b1 b2 b3): d1
       touch -r $^ $@

Note the space between 'a1' and the left parenthesis. This is required so that the target is
not parsed as an archive member.

Any request for b1, b2, or b3 would again result in a single execution of the rule. $@ would expand to include the set of all group targets regardless of which target(s) within the grouping were requested. For example, 'make b2 b3' would invoke 'touch' exactly
once with $^ expanding to "d1" and $@ expanding to "b1 b2 b3".  Running
'make a1 b2' would invoke 'touch' twice. Once for a1 and again for the b1 b2 b3 group. To generate target a1, 'touch -r d1 a1' would be run. To generate b2, 'touch -r d1 b1 b2 b3'
would be run.

   (dir1/b1 dir1/b2 dir2/c1): d1
       echo "$(@D)"
       echo "$(@F)"

The directory and file-within-directory automatic variables would expand to lists of the relevant parts. For example, 'gmake dir1/b2' would echo "dir1dir1 dir2" followed by "b1 b2 c1".

   (b1 (c1 c2)): d1

I haven't come up with an appropriate behavior for groups within groups. I suggest treating
this as a syntax error until someone comes up with a reasonable use case.

   (a1(foo1.o bar1.o) a2(foo2.o bar2.o)): d1
       echo "$%"
       echo "$@"

This can be treated as a single group consisting of four archive members: a1(foo1.o), a1(bar1.o), a2(foo2.o) a2(bar2.o). In this case, $% would expand to the list of archive
member names.  For example, running 'gmake a1(bar1.o)' would echo
"foo1.o bar1.o foo2.o bar2.o". followed by "a1(foo1.o) a1(bar1.o) a2(foo2.o) a2(bar2.o)"

Handling of special targets requires more consideration since this could introduce conflicts.
.PHONY, .PRECIOUS, .INTERMEDIATE and .SECONDARY don't raise immediate
concerns for me. But .IGNORE and .SILENT could create conflicting requirements. I
see three options for dealing with these:
1: Ignore these attributes in these cases.
2: Use the attributes associated with the first element in the group list.
3: Use the attributes of the first group member for which gmake decides the rules must be run.

Note that the above syntax is similar to pattern rules for archive members:

   (%.o): %.c
       $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $*.o
       $(AR) r $@ $*.o
       $(RM) $*.o

I haven't looked at the make source code yet to determine if this will create parsing complications
or ambiguities.

Tom.




reply via email to

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