0
votes

I'm trying to write a makefile that uses target-specific variables, but while the variables are set correctly in each target and prerequisite body, the prerequisites list itself isn't updated with the variable, thus causing the wrong prerequisite to be checked and called.

How can I update target-specific variables in the prerequisites too?

In the example below, both make foo and make bar should print "world", but make foo prints "hello".

X=hello

hello:
    echo "hello"

world:
    echo "world"

foo:X=world
foo:$(X)

bar:X=world
bar:
    make $(X)

The goal I'm trying to achieve is that different targets will build similar prerequisites - the same files, in different folders - by passing the folders as a target-specific variable. The issue is that as in the example below, if one target is called first (foo, in the example), calling the second will not do anything.

DIR=fooDir
FILE=$(DIR)/filename

$(FILE):
    touch $(FILE)
    echo $(FILE)

foo: $(FILE)

bar:DIR=barDir
bar: $(FILE)
1
never call make inside make directly as variables are then not propagated to children make. Use $(MAKE) instead. gnu.org/software/make/manual/html_node/MAKE-Variable.htmlPaulo Neves

1 Answers

2
votes

6.11 Target-specific Variable Values:

As with automatic variables, these values are only available within the context of a target’s recipe (and in other target-specific assignments).

But not in the prerequisite list. In other words, in foo:$(X) X is not target specific.


One way to achieve the desired results is:

same_files := filename another_filename

# ${1} is the target name.
# ${2} is the directory.
define similar_prerequisites
${1} : $(addprefix ${2}/,${same_files})
$(addprefix ${2}/,${same_files}) : ${2}
    touch $$@
${2} :
    mkdir $$@
endef

all : foo bar

foo bar :
    @echo "$@ prerequisites are $^"

$(eval $(call similar_prerequisites,foo,fooDir))
$(eval $(call similar_prerequisites,bar,barDir))

Output:

$ make
mkdir fooDir
touch fooDir/filename
touch fooDir/another_filename
foo prerequisites are fooDir/filename fooDir/another_filename
mkdir barDir
touch barDir/filename
touch barDir/another_filename
bar prerequisites are barDir/filename barDir/another_filename