Reputation: 3369
I want (GNU) make
to rebuild when variables change. How can I achieve this?
For example,
$ make project
[...]
$ make project
make: `project' is up to date.
...like it should, but then I'd prefer
$ make project IMPORTANTVARIABLE=foobar
make: `project' is up to date.
to rebuild some or all of project
.
Upvotes: 17
Views: 6884
Reputation: 956
Make wasn't designed to refer to variable content but Reinier's approach shows us the workaround. Unfortunately, using variable value as a file name is both insecure and error-prone. Hopefully, Unix tools can help us to properly encode the value. So
IMPORTANTVARIABLE = a trouble
# GUARD is a function which calculates md5 sum for its
# argument variable name. Note, that both cut and md5sum are
# members of coreutils package so they should be available on
# nearly all systems.
GUARD = $(1)_GUARD_$(shell echo $($(1)) | md5sum | cut -d ' ' -f 1)
foo: bar $(call GUARD,IMPORTANTVARIABLE)
@echo "Rebuilding foo with $(IMPORTANTVARIABLE)"
@touch $@
$(call GUARD,IMPORTANTVARIABLE):
rm -rf IMPORTANTVARIABLE*
touch $@
Here you virtually depend your target on a special file named $(NAME)_GUARD_$(VALUEMD5)
which is safe to refer to and has (almost) 1-to-1 correspondence with variable's value. Note that call
and shell
are GNU Make extensions.
Upvotes: 13
Reputation: 771
I might be late with an answer, but here is another way of doing such a dependency with Make conditional syntax (works on GNU Make 4.1, GNU bash, Bash on Ubuntu on Windows version 4.3.48(1)-release (x86_64-pc-linux-gnu)):
1 ifneq ($(shell cat config.sig 2>/dev/null),prefix $(CONFIG))
2 .PHONY: config.sig
3 config.sig:
4 @(echo 'prefix $(CONFIG)' >config.sig &)
5 endif
In the above sample we track the $(CONFIG)
variable, writing it's value down to a signature file, by means of the self-titled target which is generated under condition when the signature file's record value is different with that of $(CONFIG)
variable. Please, note the prefix on lines 1 and 4: it is needed to distinct the case, when signature file doesn't exist yet.
Of course, consumer targets specify config.sig
as a prerequisite.
Upvotes: 1
Reputation: 17383
You could use empty files to record the last value of your variable by using something like this:
someTarget: IMPORTANTVARIABLE.$(IMPORTANTVARIABLE)
@echo Remaking $@ because IMPORTANTVARIABLE has changed
touch $@
IMPORTANTVARIABLE.$(IMPORTANTVARIABLE):
@rm -f IMPORTANTVARIABLE.*
touch $@
After your make
run, there will be an empty file in your directory whose name starts with IMPORTANTVARIABLE.
and has the value of your variable appended. This basically contains the information about what the last value of the variable IMPORTANTVARIABLE
was.
You can add more variables with this approach and make it more sophisticated using pattern rules -- but this example gives you the gist of it.
Upvotes: 10