tiwo
tiwo

Reputation: 3369

make targets depend on variables

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

Answers (4)

Grwlf
Grwlf

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

Vladislav Rishe
Vladislav Rishe

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

Reinier Torenbeek
Reinier Torenbeek

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

Thor
Thor

Reputation: 47219

You probably want to use ifdef or ifeq depending on what the final goal is. See the manual here for examples.

Upvotes: 3

Related Questions