Reputation: 327
I am writing a Makefile for a project with a large number of js files in a complex directory structure. When run it needs to perform some compilation on each file and save the results to a different directory with the same tree structure (right now that's simulated by a cp
). When I run make js
it builds as it should and when I run make js
again it says that there is no work to do. However when I modify one of the files and make js
it re-builds the entire tree instead of just the modified file.
SHELL := /bin/bash
BUILDDIR := build/gui/
RAWJSFILES := $(shell find app -name '*.js')
BUILT_RAWJSFILES := $(patsubst %, $(BUILDDIR)%,$(RAWJSFILES))
$(BUILDDIR):
mkdir -p $(BUILDDIR)
$(RAWJSFILES): $(BUILDDIR)
$(BUILT_RAWJSFILES): $(RAWJSFILES)
mkdir -p $(@D)
# compile step
cp $(shell python -c "print '$@'.lstrip('${BUILDDIR}')") $(@D)
.PHONY: js
js: $(BUILT_RAWJSFILES)
Upvotes: 1
Views: 45
Reputation: 80921
The line $(BUILT_RAWJSFILES): $(RAWJSFILES)
is setting the prerequisites of each file in $(BUILT_RAWJSFILES)
to all the files in $(RAWJSFILES)
.
To get the one-to-one mapping you want you need a pattern rule or a static pattern rule.
Also that embedded python snippet isn't at all doing what you intended for it to do there. It is removing the longest leading prefix from the value of $@
that contains any of the characters in BUILDDIR
namely build/gui/
(only not as a string as characters so that's equivalent to lstrip('/iugdlb')
). (Oh, also you don't need $(shell)
here you are already in a shell context so a normal command substitution would work just as well ($$(python ...)
.)
That being said if you use a pattern or static pattern rule you'll have easier ways to get the source filename then messing with python like that.
Something like this should work (untested):
$(BUILDDIR)%.js: %.js
mkdir -p $(@D)
cp $^ $(@D)
Upvotes: 1