I have make target like this:
test.%
export var1=$(basename $*) && export var2=$(subst .,,$(suffix $*))
and I use like test.var1.var2
Now I want to do one more level like test.var1.var2.var3
. How can I get that in a Makefile?
edit:
The reason I want to do this is because I am using Makefile for deploying multiple apps. And I want many variables. So that user can deploy like
make install.{app1}.{test}.{build_number}
Use subst
to replace dots with spaces so that it becomes a list. Then use word
to access a specific element:
word-dot = $(word $2,$(subst ., ,$1))
test.%:
export var1=$(call word-dot,$*,1) && export var2=$(call word-dot,$*,2) && export var3=$(call word-dot,$*,3)
Which outputs:
$ make test.foo.bar.baz
export var1=foo && export var2=bar && export var3=baz
As an aside (that will actually take up most of my answer), if you know in advance what the options are, you could go with some robust metaprogramming. Say you want to generate test-{app}
targets for some APPS
:
tmpl-for = $(foreach x,$2,$(call $1,$x))
rule-for = $(foreach x,$2,$(eval $(call $1,$x)))
APPS := foo bar baz
tmpl-test = test-$1
define test-vars-rule
$(call tmpl-test,$1): APP := $1
.PHONY: $(call tmpl-test,$1)
endef
$(call rule-for,test-vars-rule,$(APPS))
$(call tmpl-for,tmpl-test,$(APPS)):
@echo Testing app: $(APP)
The first two lines are "library" functions that will call a "template" (tmpl-for
) or generate a rule (rule-for
) for each element in the list you provide as the second argument. I create a tmpl-test
which takes the app name and gives test-{app}
. I define a rule template which takes the app name and sets a target-specific APP
variable for the appropriate test-{app}
target (which is also made phony by the way). Then I use rule-for
to create all my rules for setting APP
. Finally I write the actual body of my target, and I get the list of all possible targets using tmpl-for
.
$ make test-foo
Testing app: foo
$ make test-bar
Testing app: bar
$ make test-baz
Testing app: baz
$ make test-blah
make: *** No rule to make target 'test-blah'. Stop.
It sounds complex, and it is, but if you properly abstract the templating functions it can produce flexible and easily maintainable build systems.