[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: How to rebuild on recipe change?
Re: How to rebuild on recipe change?
Tue, 16 Feb 2010 03:19:31 -0800
On Tue, Feb 16, 2010 at 1:37 AM, Kirill Smelkov <address@hidden> wrote:
> Yes, this sort of works. But how about e.g. target specific variables?
>> 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
>> # 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
Nope, that works just fine with my example. Seriously, give it a shot.
I just noticed a bug in my example: the .SECONDARY rule should be
changed to .PRECIOUS, as .SECONDARY doesn't accept patterns. (This
has tripped me up before, yes)
> Also, if $<, $^ and $+ are present in $(COMPILE.c) they are not the
> same they would be when building %.o .
Well, in my experience, auto-dependency generation already handles
changes to prerequisite lists without any extra effort. How are those
variables changing without one of the files in the *previous* list
actually being changed (i.e., mtime bump)?
> 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.
Can you expand on how that would occur?
[Checking this over before sending it, I just realized what a horrible
pun that sentence was...]
> 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.
OUTPUT_OPTION is just "-o $@", so don't worry about other random
variables in it. I'm not sure why it was ever put into GNU make; I'm
trying to think of a way to use it that wouldn't be *better* done by
altering other variables and am coming up blank. IMO, the right
solution for this is to just use "-o $@" in that rule. In fact,
consider that another bug in what I originally suggested.
Note that in POSIX compliant mode, GNU make doesn't use OUTPUT_OPTION
in the default rules. Just Say No.
> 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.
Yes, automatic variables are only defined as necessary in the target
rule's context. You have two options:
1) detect changes to them via other means, or
2) abandon the idea of using make's built-in file dependency
logic to detect when commands have changed.
I've never had any problems doing choice #1, but perhaps you can
illustrate how you're running into it.
> # .------- says expand following in target context when rule is
> # | selected and add expansion result to prerequisites. We
> # | have ``&|'' as well.
> # v
> %.o: %.c & $(call @.force-if-cmd-changed,cmd_cc_o_c)
> echo 'cmd_$@ := $(cmd_cc_o_c)' > address@hidden
> How is that? Very similar to second expansion, but a bit different.
It sounds like (I haven't looked closely) there's a bug in
.SECONDEXPANSION. If that bug was fixed, would you need this
additional feature? If no (the fix would be sufficient), then I
strongly recommend that you just try to fix the bug (or work with
Paul, Boris, et al to fix it) instead of trying to get a subtle
feature added. If nothing else, consider how much more work
*documenting* this (with a good example of a problem it solves that
can't easily be otherwise solved!) would be!