Alexander Solovyov
Alexander Solovyov

Reputation: 1535

Makefile: using variable with computed name as prerequisite

In Make it's possible to compute variable names in runtime using double-evaluation, like $($(var)).

I'm interested if it's possible somehow to make this work:

one.js_DEPS=a b
two.js_DEPS=c b

all: one.js two.js

%.js: $(%.js_DEPS)
    cat $^ > $@

I can make this work by declaring two rules with explicit dependencies, like this:

one.js: $(one.js_DEPS)

But this seems a bit anti-DRY. So I'm wondering if I miss something because make doesn't seem to understand me. I use GNU Make 3.81.

Upvotes: 1

Views: 2222

Answers (2)

Eldar Abusalimov
Eldar Abusalimov

Reputation: 25493

This could be done using Secondary Expansion.

JS := one.js two.js

all: $(JS)

.SECONDEXPANSION:

one.js_DEPS := a b
two.js_DEPS := c b

$(JS) : $$($$(@F)_DEPS)
    cat $^ > $@

But in fact, the goal can be achieved much simply, without using any GNU Make extensions, as thiton has suggested in his answer:

all: one.js two.js

one.js : a b
two.js : c b

%.js :
    cat $^ > $@

Upvotes: 1

thiton
thiton

Reputation: 36049

% and implicit rules are somewhat second-class citizens in make, since variable expansion seems to happen before implicit rule expansion. So, in your above Makefile, $(%.js_DEPS) is expanded to the empty string before % is substituted.

Alternative:

 %.js: %.js_DEPS
     cat $^ > $@

 %.js_DEPS :
     cat $^ > $@

 .INTERMEDIATE: one.js_DEPS two.js_DEPS

or simply:

 one.js : a b
 two.js : c d
 %.js :
     cat $^ > $@

Upvotes: 2

Related Questions