[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Remaking when some "parameter" changes value
From: |
John Graham-Cumming |
Subject: |
Re: Remaking when some "parameter" changes value |
Date: |
Fri, 17 Feb 2006 11:28:59 +0100 |
User-agent: |
Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.6) Gecko/20040208 Thunderbird/0.5 Mnenhy/0.6.0.104 |
Nick Patavalis wrote:
My problem, in a nutshell, is this: How can I force a project be
remade, when one of the parameters passed to Make changes? When, for
example, the flags to the compiler, or to the linker, change?
As you are aware there's no built in way to do this in GNU Make. But it
is possible to build your own version of what Sun Make calls "keep
state" using GNU Make functions.
Here's an example Makefile that I've modified to work as you wish:
include signature
all: foo.o bar.o
FOO=$(FOOEY)
foo.o: foo.c
$(call do,$$(COMPILE.C) -DFOO=$$(FOO)$$(@F) -o $$@ $$<)
bar.o: bar.c
$(call do,$$(COMPILE.C) -DBAR=$$(BAR) -o $$@ $$<)
-include foo.sig bar.sig
There are three modifications from a standard Makefile: firstly there's
'include signature' at the start. (You'll see the definition of
signature below), then the commands for each rule have been wrapped in
$(call do,...) and any $'s in the commands have been quoted with an
extra $. Lastly the Makefile includes a .sig file for each .o being
created (if the .sig exists, hence the -include instead of include).
The .sig file is generated by code in signature when a rule is run and
is used to perform the 'command has changed' checking that you need.
Here, for example, is the contents of bar.sig after make has been run
for the first time:
$(eval @ := bar.o)
$(eval % := )
$(eval < := bar.c)
$(eval ? := bar.c)
$(eval ^ := bar.c)
$(eval + := bar.c)
$(eval * := bar)
bar.o: bar.force
$(if $(call sne,$(COMPILE.C) -DBAR=$(BAR) -o $@ $<,g++ -c -DBAR=
-o bar.o bar.c),$(shell touch bar.force))
The first set of lines captures the state of the automatic variables
within the rule to make bar.o, the next line says that bar.o depends on
a special file called bar.force and lastly there's a rather complex $(if
...) that uses the GMSL (see my sig for the GNU Make Standard Library)
string-not-equal (sne) function to check the current expansion of the
commands to make bar.o against the previous expansion. It's this $(if
...) that can detect a change in the commands to run a rule. If such a
change is detected bar.force is touched and hence bar.o will be rebuilt
because bar.force is newer.
The signature include is where the work is done:
include gmsl
last_target :=
dump_var = \$$(eval $1 := $($1))
define new_rule
@echo "$(call map,dump_var,@ % < ? ^ + *)" > $S
@$(if $(wildcard $F),,touch $F)
@echo $@: $F >> $S
endef
define do
$(eval S := $*.sig)$(eval F := $*.force)$(eval C := $1)
$(if $(call sne,$@,$(last_target)),$(call new_rule),$(eval
last_target := $@))
@echo "$(subst $$,\$$,$$(if $$(call sne,$1,$C),$$(shell touch $F)))"
>> $S
$C
endef
I won't go into all the details of how signature works, but essentially
the do macro is responsible for updating the .sig files as needed. I'll
write this up for my column on CM Crossroads next month, but you can
play around with the code (you need the GMSL and GNU Make 3.80 for this
to work) and you'll see that changing a parameter does work.
Here's an example of starting from scratch and then changing the values
of FOO and BAR in the Makefile above:
$ make
g++ -c -DFOO=foo.o -o foo.o foo.c
g++ -c -DBAR= -o bar.o bar.c
$ make
make: Nothing to be done for `all'.
$ make BAR=bar
g++ -c -DBAR=bar -o bar.o bar.c
$ make BAR=bar
make: Nothing to be done for `all'.
$ make BAR=baz
g++ -c -DBAR=baz -o bar.o bar.c
$ make BAR=baz FOO=foo
g++ -c -DFOO=foofoo.o -o foo.o foo.c
$ make BAR=bar FOO=foo
g++ -c -DBAR=bar -o bar.o bar.c
$ make
g++ -c -DFOO=foo.o -o foo.o foo.c
g++ -c -DBAR= -o bar.o bar.c
The only limitation of this scheme is that if you change the commands in
a rule by editing the Makefile you need to do a clean build or at least
delete the corresponding .sig file so that it gets remade.
John.
--
John Graham-Cumming
address@hidden
Home: http://www.jgc.org/
Blog: http://www.jgc.org/blog/
POPFile: http://getpopfile.org/
GNU Make Standard Library: http://gmsl.sf.net/
GNU Make Debugger: http://gmd.sf.net/
Fast, Parallel Builds: http://www.electric-cloud.com/
Sign up for my Spam and Anti-spam Newsletter
at http://www.jgc.org/