nickf
nickf

Reputation: 546005

Make target using a pattern

I'm doing something which it feels like should be pretty straightforward. I have source files in a directory called ./src which are transformed and saved to ./. For the sake of the question, I'll just say they get copied there.

Here's what the directory looks like before building:

/src/lib/foo.js
/src/lib/mod/bar.js
/src/bin/baz.js
/Makefile

Here's what should be there after building:

/src/lib/foo.js
/src/lib/mod/bar.js
/src/bin/baz.js
/lib/foo.js
/lib/mod/bar.js
/bin/baz.js
/Makefile

In my Makefile I have this:

SRC_FILES := src/lib/foo.js src/lib/mod/bar.js src/bin/baz.js
OUT_FILES := lib/foo.js lib/mod/bar.js bin/baz.js

These are generated from find and a pattern substitution, but are listed like this here for simplicity...

Now, what I was hoping would work would be:

%.js: src/%.js
    cp $< $@

But when I run make lib/foo.js I get Nothing to be done for 'lib/foo.js'.

Looking at the output from debugging, it appears to be trying to find a dependency named lib/src/foo.js. This is kind of what is described in the manual.

This feels as though it should be a really easy thing! What am I doing wrong?


Additionally, I tried:

$(OUT_FILES): $(SRC_FILES)
    cp $< $@

...which works, but it rebuilds every single file if any of the sources change. (Remember that my actual transformation isn't just cp, it's a relatively expensive operation, so this is undesirable)

Upvotes: 0

Views: 50

Answers (1)

nickf
nickf

Reputation: 546005

Found something which works. Using secondary expansion, you have access to the target variable in the dependencies. I saw this earlier, but missed the all-important thing: adding an empty target called .SECONDEXPANSION

.SECONDEXPANSION:

all: $(OUT_FILES)

%.js: src/$$@
    cp $< $@

Upvotes: 1

Related Questions