|
From: | Eric Melski |
Subject: | Re: rule w/multiple targets causes failure in -j mode; how to fix |
Date: | Sun, 22 Mar 2009 09:32:01 -0700 |
User-agent: | Thunderbird 2.0.0.19 (X11/20081209) |
Jamie Cuesta wrote:
2. Use a dummy target to actually do the work, then make both your .o and .h targets depend on that dummy: output.h output.o: generate_output generate_output: input.c @echo Building output.o and output.h from input.c. @touch output.h @touch output.o This is a little clumsy, and it doesn't work so well with incremental builds, but it will at least protect you from collisions when doing a parallel build, because now there really is only one rule that updates both output files.This seems like the only viable choice in my situation, so I want to clearly understand the problems with it. Clumsiness: I suppose you say this because _two_ rules are needed just to make the original single-rule construct "-j-safe"? Since my makefile is programmatically generated, this is not a problem (I add this pattern to my makefile-gen program, and it's taken care of forever). That leaves "it doesn't work so well with incremental builds". This I don't understand: I assume make will still operate correctly (if .c is newer than either of .h or .o, then run rule to rebuild both), so in what way does this construct "[not] work so well with incremental builds"? Is it simply because internally make has to evaluate two rules instead of the more ideal one? Or am I missing something... ?
The thing is, in this example you don't have a dependency that says "if input.c is newer than output.h or output.o, rebuild those files." You have a dependency that says, "if input.c is newer than generate_output (whatever that is), rebuild it". As written, this makefile will rebuild output.h and output.o every time it is run, because make is comparing the times on output.h and output.o with generate_output. Since generate_output doesn't exist, make will run that rule. It doesn't matter if input.c is older than output.h and output.o -- there is no direct relationship between those files in this makefile.
You can work around that by having the generate_output rule also create a file on disk named "generate_output"; then on the second run, make will see that the file "generate_output" is not newer than output.h or output.o, and will not rebuild. But now you have this extra file kicking around that serves no purpose other than to work around a deficiency in your build tool. And you need to remember to manage that file along with your other objects -- it should get deleted by "make clean", for example. And if somebody does something like "touch generate_output" in between builds, that may mess up make's ability to detect that output.h and output.o need to be rebuilt.
Actually, a third option just occurred to me: output.h: output.o output.o: input.c @echo Building output.o and output.h from input.c @touch output.h @touch output.oI'm sure this has some drawback too, but I haven't had my morning coffee yet, so I'm not sure what that is.
Cheers, Eric Melski Electric Cloud, Inc. http://blog.electric-cloud.com/
[Prev in Thread] | Current Thread | [Next in Thread] |