help-make
[Top][All Lists]
Advanced

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

Re: How to rebuild on recipe change?


From: Kirill Smelkov
Subject: Re: How to rebuild on recipe change?
Date: Tue, 16 Feb 2010 12:37:10 +0300
User-agent: Mutt/1.5.18 (2008-05-17)

Philip, thanks for answering. Some comments below:

On Mon, Feb 15, 2010 at 06:52:00PM -0800, Philip Guenther wrote:
> On Mon, Feb 15, 2010 at 9:57 AM, Kirill Smelkov <address@hidden> wrote:
> > I'm trying to do reliable incremental build system, and this means that
> > those and only those parts which depend on changed environment have to
> > be remade.
> >
> > However changed environment could be not only file changes, but also
> > changes to CFLAGS (global or target specific), or command recipe for
> > .cpp -> .o rule and the like.
> ...
> > So the question is:
> >
> >    How to do it? How to properly rebuild on recipe change without
> >    sacrificing clearness and performance?
> 
> So, the file foo.o should be built if any of its input files (foo.c,
> whatever foo.c #includes, etc) changes or if the command line used to
> build it change.

Right

> So, how about if you save the command line in a file
> and make that file a dependency of foo.o.  If the rule to build the
> command file only updates the file if the command actually changed,
> then you'll get the desired behavior, no?

Yes, this sort of works. But how about e.g. target specific variables?
Look:

> I.e., something like:
> --------
> # delete the normal rule, so that ours is preferred
> %.o: %.c
> 
> # provide ours that expects %.o_c to contain the command for building
> the .o file
> %.o: %.o_c %.c
>         $(shell cat $(filter %.o_c,$^)) $(OUTPUT_OPTION) $(filter %.c,$^)
> 
> # generate or update the file containing the command.  The FORCE is because
> # we need this to be rebuilt each time, but we can't declare it .PHONY (as 
> then
> # the %.o would always be rebuilt too, even if the %.o_c didn't change)
> %.o_c: FORCE
>         @+new='$(COMPILE.c)'; \
>         printf '%s\n' "$$new" | cmp -s - $@ || printf '%s\n' "$$new" >$@

When you dump command, you expand $(COMPILE.c) in %.o_c context, and
that looses e.g. target specific CFLAGS for e.g.

1.o : CFLAGS += -O6


Also, if $<, $^ and $+ are present in $(COMPILE.c) they are not the
same they would be when building %.o .  Yes, it is possible to leave
``$<'' and friends in command output as is (i.e. unexpanded), and to
later substitute them by hand, but that's not correct -- e.g. $+ could
change between runs, and we would not notice.

I know default $(COMPILE.c) does not have auto variables, and so the
whole target cmd has additional

    ... $(OUTPUT_OPTION) $(filter %.c,$^)

but is that 100% correct? e.g. $(OUTPUT_OPTION) could change between
runs and we won't notice. More, e.g. for link commands, $^ could change
(e.g. user adds new .o to, or removes unneeded .o from list of library
objects), and this wouldn't be noticed either.

----

The main problem here is that $(COMPILE.c) or whatever, gets expanded
not in the target context, and that's the main pity -- correct expansion
is only possible in target context in _recipe_ only.

Even second expansion does not work -- it correctly expand target
specific variables, but treats $<, $^ and $+ differently compared to
in-recipe context.


If only there could be a way to add hooks in place where make 1) already
found rule for target, but 2) before that rule actually gets executed!

This could be used to e.g. add FORCE prerequisite to force $@ rebuild,
or something more constrained... The main question here is to how to
inject make code which will get expanded in target context exactly, but
before that target gets run...

Then something like the following should do what I need cleanly:

---- 8< ----

# @.force-if-cmd-changed <cmd-patter-name>
@.force-if-cmd-changed =        \
        $(if $(call sne,$($1),$(cmd_$@)),\
                $(info $@: forcing rebuild due to CMD change)   \
                FORCE)

#         .------- says expand following in target context when rule is already
#         |        selected and add expansion result to prerequisites. We could
#         |        have ``&|'' as well.
#         v
%.o: %.c  & $(call @.force-if-cmd-changed,cmd_cc_o_c)
        $(cmd_cc_o_c)
        echo 'cmd_$@ := $(cmd_cc_o_c)' > address@hidden

-include *.cmd

---- 8< ----


How is that? Very similar to second expansion, but a bit different.


> That's pretty crude, but maybe it'll give you ideas on where to go.

Thanks, I appreciate it.

Kirill





reply via email to

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