Re: Static multiple target rules
On 3/30/2010 2:14 AM, Edward Welbourne wrote: y.tab.h y.tab.c y.output: yacc.ts I don't actually see that y.output serves any role in this; simply remove every reference to it and your example should be clearer. It actually does serve a roll for testing purposes. Try the following with this test case: gmake clean gmake rm y.output gmake gmake With GNU make 3.81, the second to last gmake invocation rebuilds y.output which also rebuilds y.tab.h and y.tab.c, but y.tab.o (now out of date) doesn't get rebuilt. An additional gmake invocation is necessary to get everything up to date - which is not desirable behavior. y.tab.o: y.tab.c y.tab.h I don't understand .INTERMEDIATE well enough to know why this chain fails to lead to y.tab.o's rule being run after yacc.ts's rule has been run, in your -j case. Something strange is going on, I think what is happening is that time stamps are being checked too early in some cases. Make can't infer that y.tab.h, y.tab.c, and y.output are updated by the commands for yacc.ts. Depending on when it checks the time stamps for those files, it may see the times before or after the commands for yacc.ts are run. I recall seeing emails regarding GNU make caching time stamps, so that could contribute to this. Parallel builds would behave differently since a shared cache isn't used and each process would have to check time stamps on its own. So, behavior varies. ___ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make
Re: Static multiple target rules
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. It appears the sysV implementation doesn't let you declare multiple groups with a single rule, but that's not a restriction of the syntax itself. Yes, that syntax has a meaning in GNU make (treating '+' as a target), but it's clearly not a portable name for a target. (Indeed, plus-sign is not part of the POSIX Portable Filename Character Set.) I'm not sure if multiple groups has good use cases or not. I proposed supporting it mainly because I felt there was a clear, reasonable, and consistent behavior and specifying the behavior felt important since the syntax didn't preclude it. (similar to nested groups except that nested groups don't seem to have a clear and reasonable behavior) I suspect very few people would be upset by the inability to specify a target named '+'. Those that are impacted would likely be able to change the file/target name to something else. However, if there is substantial concern, than a backward compatibility option could be added to disable the new semantics. The proposed syntax already has a conflicting special meaning in GNU make (multiple archive-member target) for what would be the common case of a single group. That is, this: (b1 b2 b3): d1 whatever currently means the b1, b2, or b3 members of any archive library depend on d1 and are updated by running 'whatever'. The fact that it's a special syntax means that it's more likely to actually be in use out there. How will the proposed change affect Makefiles using that syntax? Are you sure about this syntax? I can't find any descriptions of it in the GNU make manual. I do see archive pattern rules with a syntax such as '(%.o): %.c', but no static rules like this. I tried this syntax and gmake treated it as three separate targets: '(b1', 'b2', 'b3)'. This suggests we could use parenthesis for the syntax, but I have no objections to the sysV syntax. As Eddy pointed out, the sysV syntax avoids the issue of nested groups. (While I don't think the sysV syntax is *great*, I personally think it's a better choice than overloading the meaning of parentheses.) Yup, I agree. If only for compatibility. ___ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make
Re: Static multiple target rules
On 3/30/2010 2:08 AM, Edward Welbourne wrote: (While I don't think the sysV syntax is *great*, I personally think it's a better choice than overloading the meaning of parentheses.) +1 It also avoids the problem of having to make sense of nesting, e.g. (b1 (c1 c2)): d1 True, but it introduces the problem of making sense of these: + b1 + b2 +: d1 b1 + + b2: d1 b1 + b2 b3: d1 Solaris 10 make appears to silently drop dangling and extra '+' connectors - which is convenient for handling macros that are empty when expanded. It also appears to silently insert missing '+' connectors if there are any '+' connectors in the target group. Thus, I think Solaris make would treat the following rules as equivalent to the ones above: + b1 b2: d1 + b1 b2 b3: d1 ___ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make
Re: Static multiple target rules
On 3/31/2010 1:01 AM, tom honermann wrote: True, but it introduces the problem of making sense of these: + b1 + b2 +: d1 b1 + + b2: d1 b1 + b2 b3: d1 Solaris 10 make appears to silently drop dangling and extra '+' connectors - which is convenient for handling macros that are empty when expanded. It also appears to silently insert missing '+' connectors if there are any '+' connectors in the target group. Thus, I think Solaris make would treat the following rules as equivalent to the ones above: + b1 b2: d1 + b1 b2 b3: d1 Strike that. It seems Solaris make does not insert '+' connectors and does support multiple target groups. This behavior can be seen with rules that fail to actually produce all group members. all: a1 a2 a3 a4 clean: rm -f a1 a2 a3 a4 d1: @touch $@ a1 + a2 a3 + a4: d1 touch $@ The above Makefile has two target groups: a1+a2 and a3+a4. The group target rule however will only build the current target. $ make clean rm -f a1 a2 a3 a4 $ make a1 a2 touch a1 Only a1 is built. Solaris make assumes a2 was built as well (or treats it similar to GNU make .PHONY targets) $ make clean rm -f a1 a2 a3 a4 $ make a1 a3 touch a1 touch a3 Both a1 and a3 are built in this last case since a1 and a3 are not in the same group. $ make clean rm -f a1 a2 a3 a4 $ make a1 a2 a3 a4 touch a1 touch a3 $ make a1 a2 a3 a4 `a1' is up to date. touch a2 `a3' is up to date. touch a4 The first make invocation builds a1 and a3 and assumes a2 and a4 were built. A second invocation causes a2 and a4 to actually get built. Tom. ___ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make
Re: Static multiple target rules
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 $@:
Re: Static multiple target rules
y.tab.h y.tab.c y.output: yacc.ts I don't actually see that y.output serves any role in this; simply remove every reference to it and your example should be clearer. y.tab.o: y.tab.c y.tab.h I don't understand .INTERMEDIATE well enough to know why this chain fails to lead to y.tab.o's rule being run after yacc.ts's rule has been run, in your -j case. Something strange is going on, Eddy. ___ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make
Re: Static multiple target rules
On 3/3/2010 2:03 AM, Edward Welbourne wrote: Another possibility crossed my mind over-night, with which I haven't experimented, but that seems like it theoretically should work. Replace the touch-file with a phony rule: yacc.ts: grammar.y yacc -d -v $^ y.tab.h y.tab.c y.output .PHONY: yacc.ts Because it's phony, and we never create it, it'll never exist and make shouldn't care that no such file exists; because the three real targets depend on it, any need for any of them shall force it to be made (causing them to all exist); but if more than one of them needs made, an individual run of make shall only make the phony once yet still know that it's made it, so not need to run yacc again for the sake of the others that depend on it. But I may be confused about proper use of .PHONY - please experiment and report your results ! Eddy. You're a genius! .PHONY didn't do the trick, but .INTERMEDIATE did: .INTERMEDIATE: yacc.ts 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 $@ yacc.ts: grammar.y @echo Running yacc... @sleep 1 @touch y.tab.h y.tab.c y.output y.tab.h y.tab.c y.output: yacc.ts y.tab.o: y.tab.c y.tab.h @echo Compiling y.tab.c... @sleep 1 @touch $@ The only problem I could find with this approach is that downstream targets might not get rebuilt as expected. For example, run gmake once to build everything, then remove y.output and run gmake again. Using make 3.81 on Linux, y.output is rebuilt which also rebuilds y.tab.c and y.tab.h, but y.tab.o is not rebuilt (as might be expected since y.tab.h and y.tab.c were regenerated). This makes sense because gmake has no way of knowing that rebuilding y.output would also regenerate y.tab.h and y.tab.c. A full solution for static multiple target rules would recognize that these files had been regenerated and would also rebuild y.tab.o. But, I think this is good enough for my use cases. Thanks Eddy! Tom. ___ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make
Re: Static multiple target rules
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. ___ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make
Re: Static multiple target rules
On Mon, Mar 29, 2010 at 7:54 PM, tom honermann tom.honerm...@oracle.com wrote: 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? ... 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. Hmm. SysV make has offered the desired feature with the syntax b1 + b2 + b3: d1 touch -r $^ $@ It appears the sysV implementation doesn't let you declare multiple groups with a single rule, but that's not a restriction of the syntax itself. Yes, that syntax has a meaning in GNU make (treating '+' as a target), but it's clearly not a portable name for a target. (Indeed, plus-sign is not part of the POSIX Portable Filename Character Set.) The proposed syntax already has a conflicting special meaning in GNU make (multiple archive-member target) for what would be the common case of a single group. That is, this: (b1 b2 b3): d1 whatever currently means the b1, b2, or b3 members of any archive library depend on d1 and are updated by running 'whatever'. The fact that it's a special syntax means that it's more likely to actually be in use out there. How will the proposed change affect Makefiles using that syntax? (While I don't think the sysV syntax is *great*, I personally think it's a better choice than overloading the meaning of parentheses.) Philip Guenther ___ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make
Re: Static multiple target rules
The only downsides to this I see are: 1: The duplicate file storage. Probably not a big deal. 2: The extra processing time to archive and extract the files. Again, probably not a big deal. 3: The why'd they do that? questions coming from people unfamiliar with the technique. all valid problems. 4: It doesn't address that nagging feeling that make should be able to support this. Quite. Another possibility crossed my mind over-night, with which I haven't experimented, but that seems like it theoretically should work. Replace the touch-file with a phony rule: yacc.ts: grammar.y yacc -d -v $^ y.tab.h y.tab.c y.output .PHONY: yacc.ts Because it's phony, and we never create it, it'll never exist and make shouldn't care that no such file exists; because the three real targets depend on it, any need for any of them shall force it to be made (causing them to all exist); but if more than one of them needs made, an individual run of make shall only make the phony once yet still know that it's made it, so not need to run yacc again for the sake of the others that depend on it. But I may be confused about proper use of .PHONY - please experiment and report your results ! Eddy. ___ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make
Re: Static multiple target rules
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. The next thing to try is using a proxy or timestamp file: yacc.ts: grammar.y yacc -d -v $^ touch $@ y.tab.h y.tab.c y.output: yacc.ts A quarter of an hour after reading your mail, I had a mildly perverted idea: instead of a touch-file, use a tar-file ! The problem you point to is when the touch file exists but the files we want don't: we need a command for the rule that declares their dependency on it; and that command needs to be able to generate the outputs from the fake file. yacc.ts: grammar.y yacc -d -v $^ tar cf $@ y.tab.h y.tab.c y.output y.tab.h y.tab.c y.output: yacc.ts tar xf $ -m Note the crucial -m in the extracting tar, so that we touch the outputs after the tar-file has been created, thereby avoiding re-extracting every time we run make. Not sure how well that'd work but it *looks* like it should ... and it should generalise reasonably well. Unfortunately I can't, just yet, see how to turn it into a pattern rule for general .y file processing, Eddy. ___ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make
Re: Static multiple target rules
Correcting myself: I missed out the $@ in y.tab.h y.tab.c y.output: yacc.ts tar xf $ -m $@ which ensures that each target is the only thing extracted when the rule to generate it is executed, Eddy. ___ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make
RE: Static multiple target rules
instead of a touch-file, use a tar-file ! Yeah, one of my company's makefiles uses a similar intermediate file to good effect. We've been using the touch-file or sentinel solution elsewhere for years. I'd previously suggested replacing the sentinels with tar files so we could get rid of all the hackery we have to address the problem Tom raised about non-existent targets. We have a macro that's used to convert missing source file names to the name of the corresponding sentinel file and then code to force that sentinel to rebuild. It's complicated, ugly and fragile. What really motivated me to reply, however, was: Note the crucial -m in the extracting tar I would have made that mistake, so thanks for pointing it out before I stepped on the rake! -Original Message- From: bug-make-bounces+mdorey=bluearc@gnu.org [mailto:bug-make-bounces+mdorey=bluearc@gnu.org] On Behalf Of Edward Welbourne Sent: Tuesday, March 02, 2010 02:45 To: tom honermann Cc: bug-make@gnu.org Subject: Re: Static multiple target rules 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. The next thing to try is using a proxy or timestamp file: yacc.ts: grammar.y yacc -d -v $^ touch $@ y.tab.h y.tab.c y.output: yacc.ts A quarter of an hour after reading your mail, I had a mildly perverted idea: instead of a touch-file, use a tar-file ! The problem you point to is when the touch file exists but the files we want don't: we need a command for the rule that declares their dependency on it; and that command needs to be able to generate the outputs from the fake file. yacc.ts: grammar.y yacc -d -v $^ tar cf $@ y.tab.h y.tab.c y.output y.tab.h y.tab.c y.output: yacc.ts tar xf $ -m Note the crucial -m in the extracting tar, so that we touch the outputs after the tar-file has been created, thereby avoiding re-extracting every time we run make. Not sure how well that'd work but it *looks* like it should ... and it should generalise reasonably well. Unfortunately I can't, just yet, see how to turn it into a pattern rule for general .y file processing, Eddy. ___ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make ___ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make
Re: Static multiple target rules
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 $^ The next thing to try is using a proxy or timestamp file: yacc.ts: grammar.y yacc -d -v $^ touch $@ y.tab.h y.tab.c y.output: yacc.ts A quarter of an hour after reading your mail, I had a mildly perverted idea: instead of a touch-file, use a tar-file ! The problem you point to is when the touch file exists but the files we want don't: we need a command for the rule that declares their dependency on it; and that command needs to be able to generate the outputs from the fake file. yacc.ts: grammar.y yacc -d -v $^ tar cf $@ y.tab.h y.tab.c y.output y.tab.h y.tab.c y.output: yacc.ts tar xf $ -m $@ Note the crucial -m in the extracting tar, so that we touch the outputs after the tar-file has been created, thereby avoiding re-extracting every time we run make. Not sure how well that'd work but it *looks* like it should ... and it should generalise reasonably well. Unfortunately I can't, just yet, see how to turn it into a pattern rule for general .y file processing, Eddy. Nice idea! I like this much better than the workaround I had used involving $(shell...) and removing the time-stamp file. The only downsides to this I see are: 1: The duplicate file storage. Probably not a big deal. 2: The extra processing time to archive and extract the files. Again, probably not a big deal. 3: The why'd they do that? questions coming from people unfamiliar with the technique. 4: It doesn't address that nagging feeling that make should be able to support this. Tom. ___ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make
Static multiple target rules
I've been struggling for some time now with how to write rules for commands that generate multiple targets and I have so far been unable to find an elegant solution that works reliably. I know pattern rules have support for specifying multiple targets, but they don't seem to be appropriate for all scenarios. As an example, lets consider the venerable 'yacc' command: yacc -d -v grammar.y This will produce the following files: y.tab.h, y.tab.c, and y.output Myself and many others have naively tried a rule like the one below and then been surprised to see 'yacc' get invoked multiple times (especially in parallel builds). y.tab.h y.tab.c y.output: grammar.y yacc -d -v $^ The fine GNU make manual describes this syntax and its behavior well (section 4.10 - Multiple Targets in a Rule in the manual I'm looking at). This syntax and behavior are very useful - just not for specifying multiple targets for a single command! The next thing to try is using a proxy or timestamp file: yacc.ts: grammar.y yacc -d -v $^ touch $@ y.tab.h y.tab.c y.output: yacc.ts This solves the problem of 'yacc' getting run multiple times while preserving the desired behavior that 'yacc' is only invoked when its targets are out of date. However, if 'yacc.ts' exists, is newer than 'grammar.y', and any of 'y.tab.h', 'y.tab.c', or 'y.output' do not exist, then 'yacc' won't get run to re-generate them (since make sees that 'yacc.ts' is up to date and concludes that the other targets must be up to date as well). A solution for that last problem might look something like this: $(shell [ -f y.tab.h -a -f y.tab.c -a -f y.output ] || rm -f yacc.ts) yacc.ts: grammar.y yacc -d -v $^ touch $@ y.tab.h y.tab.c y.output: yacc.ts This works, but is rather inelegant - especially if there are many more output files than in my simple example. Is there a better way to write rules for generating multiple targets such as this? Has anyone proposed extensions to GNU make to support static multiple target rules? Tom. ___ Bug-make mailing list Bug-make@gnu.org http://lists.gnu.org/mailman/listinfo/bug-make