I have %.foo
files that live in an $(A)
directory with additional year/month
substructure, eg $(A)/2014/05/x.foo
etc. With a Makefile, which I want to keep in the directory where the ./converter
lives, I want to convert all the %.foo
files in directories $(A)/*/*/
into a mirrored $(B)/*/*/
structure. Additional complication is that the converter
unfortunately converts a %.foo
file into a file with two extensions, ie %.bar.baz
and this behavior cannot be changed. How should I correctly construct the dependencies of the $(B)
files on $(A)
files? How should I write the %.bar.baz: %.foo
rule?
The problem is similar to this question. I tried with
AF := $(shell find $(A) -name \*.foo)
BF := $(patsubst $(A)/%.foo,$(B)/%.bar.baz,$(AF))
all: $(BF)
.PHONY: all
$(B)/%.bar.baz: %.foo
mkdir -p $(@D)
./convert $< $@ || rm $@
but with make
or gmake
I just get
make: *** No rule to make target 'b/2014/05/x.bar.baz', needed by 'all'. Stop.
This rule is wrong:
$(B)/%.bar.baz: %.foo
mkdir -p $(@D)
./convert $< $@ || rm $@
Let's see what make will do with the target you want to build, b/2014/05/x.bar.baz
. Make will look for a target pattern that matches this, and it finds $(B)/%.bar.baz
(because $(B)
expands to b
), so the pattern is really b/%.bar.baz
.
Given this pattern, what is the stem (the part that matches the %
)? It will be 2014/05/x
.
Given that stem, what is the prerequisite that make looks for when the prerequisite pattern is %.foo
? We replace the stem and we get 2014/05/x.foo
.
So make looks for the file 2014/05/x.foo
, but that file doesn't exist. The file that exists is a/2014/05/x.foo
(I will assume: you don't actually show us the value of the A
or B
variables). Since the prerequisite file doesn't exist, and make can't find a way to build it, make decides this pattern rule doesn't match. Since this pattern doesn't match make will look for some other pattern rule that will match. Since no other pattern rule matches either, make tells you it doesn't know how to build this target b/2014/05/x.bar.baz
.
So the simple answer is, don't forget to add the directory $(A)
to the prerequisite:
$(B)/%.bar.baz: $(A)/%.foo
mkdir -p $(@D)
./convert $< $@ || rm $@