Reputation: 20080
I am designing a simple makefile that defines one target which takes an argument, and I would like to define a second target that invokes the first target in a loop, once per every variable defined in an array variable at the top of the Makefile.
my_loop_var = var1 var2
my_thing:
echo $MY_VAR
all:
invoke my_thing once for each value of my_loop_var
What is the right way to solve this?
Upvotes: 1
Views: 812
Reputation: 28965
Note: $MY_VAR
will probably expand as Y_VAR
because make will try to expand variable M
, which is probably undefined, and concatenate Y_VAR
to the result. Use $(VARNAME)
to expand make variable VARNAME
. It is only with single-character variable names that you can expand with $X
.
There is not really a "right way". There are many ways. The most straightforward from your specifications (but the less natural) would be something like:
my_loop_var := var1 var2
my_thing:
echo "$(MY_VAR)"
.PHONY: all my_thing
all:
for v in $(my_loop_var); do $(MAKE) my_thing MY_VAR="$$v"; done
The recipe of all
is a shell loop that re-invokes make
with the my_thing
goal and with each value in my_loop_var
passed as the value of make variable MY_VAR
.
Note the $$v
to escape the first expansion that make always performs before passing the recipe to the shell. With just $v
make would expand the recipe as ... MY_VAR="" ...
and the result would not be what you expect.
Note also the use of the MAKE
make variable instead of directly calling make
(have a look at the documentation if you want to understand why it is better like this).
all
and my_thing
are declared as phony because they are not real file names that their recipes create, and make needs to know this kind of things.
But a much more make-ish way would be something like:
my_loop_var := var1 var2
my_thing_targets := $(addprefix my_thing_,$(my_loop_var))
.PHONY: all $(my_thing_targets)
all: $(my_thing_targets)
$(my_thing_targets): my_thing_%:
echo "$*"
Here we define as many my_thing_something
targets as there are something
values in my_loop_var
. And explain make how to build such targets with a static pattern rule. In the recipe of a pattern rule the $*
automatic variable expands as the part that matched the %
pattern. So, this static pattern rule says that if we need to build my_thing_something
, the recipe is echo "something"
.
We declare all these my_thing_something
targets as prerequisites of all
such that if you type make
or make all
, make will build all the my_thing_something
targets.
This second solution is better for at least two reasons. First, make is invoked only once, which is better, at least for performance. Second, make can parallelize the build of the my_thing_something
if you use the -j N
option (to allow make to run up to N
jobs in parallel). This also is better for performance.
But it is also a matter of style. Very frequently if you use shell loops in your recipes, especially to invoke make again, it is the sign that you did not really understand what make is intended for and how it works. The make language is not a scripting language (even if the recipes are written in shell language, which is a scripting language); make is designed to "loop" over all targets to build, without the need for explicit loops.
Upvotes: 2