Ed Bennett
Ed Bennett

Reputation: 161

Can GNU Make use pattern matching to look up variables?

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

Answers (1)

MadScientist
MadScientist

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

Related Questions