Reputation: 161
I'm trying to get Make to build some data analysis, where there are file lists controlled by one overall parameter.
To write it explicitly would be something like:
A_EXTS = a b c d e
B_EXTS = f g h i j
C_EXTS = k l m n o
A.dat : $(foreach EXT, ${A_EXTS}, prefix1_${EXT}.dat prefix2_${EXT}.dat)
python analyse.py $^ > $@
B.dat : $(foreach EXT, ${B_EXTS}, prefix1_${EXT}.dat prefix2_${EXT}.dat)
python analyse.py $^ > $@
C.dat : $(foreach EXT, ${C_EXTS}, prefix1_${EXT}.dat prefix2_${EXT}.dat)
python analyse.py $^ > $@
Obviously the only difference between the three rules is the A
vs B
vs C
.
I thought to try something like
%.dat : $(foreach EXT, ${%_EXTS}, prefix1_${EXT}.dat prefix2_${EXT}.dat)
python analyse.py $^ > $@
…but that doesn't work; e.g. make B.dat
runs the rule for B.dat
but ignores the dependencies; $^
is set to the empty string.
The files starting prefix2_
are generated by another recipe, so I can't just specify them within the recipe, they need to be marked as dependencies here.
Is this possible to express these dependencies without repeating the same rule?
Upvotes: 0
Views: 429
Reputation: 100946
Well, you can't do it quite like you want to here, but it's not related to looking up variable names: it's because of expansion order.
Variables in targets and prerequisites are expanded when the makefile is parsed, but make doesn't expand the patterns in pattern rules until much later. That means when make expands the ${%_EXTS}
variable as it parses the makefile, it has no idea what the value of %
will be later when it's actually trying to build things.
You can use secondary expansion to delay expansion of variables until make's second pass where it is actually finding target names. I pulled the logic out into a separate variable and used call
to make it a bit more readable:
.SECONDEXPANSION:
EXPANDDEPS = $(foreach EXT,${$1_EXTS},prefix1_${EXT}.dat prefix2_${EXT}.dat)
%.dat : $$(call EXPANDDEPS,$$*)
python analyse.py $^ > $@
Upvotes: 1