[Top][All Lists]

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

Re: rule w/multiple targets causes failure in -j mode; how to fix

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 (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.o

I'm sure this has some drawback too, but I haven't had my morning coffee yet, so I'm not sure what that is.


Eric Melski
Electric Cloud, Inc.

reply via email to

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