I am trying to create a makefile pattern to transform the source files articles/*/source.txt
to target files articles/*/target.html
, where *
is one and/or multiple single-level directories with unknown names.
Each source.txt
file should when running make
generate a target.html
file in the same corresponding directory.
I was trying to use $(wildcard article/*)
to create a list of all directories i was targeting, however it seems to not be able to combine that list with a file fragment string (like $(SUBDIRS)/target.html
).
.PHONY: build
SUBDIRS := $(wildcard article/*)
build: $(SUBDIRS)/target.html
$(SUBDIRS)/target.html: $(SUBDIRS)/source.txt
echo "Generate html..." > $(SUBDIRS)/target.html
This cannot work:
build: $(SUBDIRS)/target.html
Suppose SUBDIRS
is article/foo article/bar article/baz
. What will the above expand to? There's no magical force in make that will see that a variable expands to multiple words, and that there's a postfix on the variable, and append it to every word individually. Instead, the above simply expands to the variable value followed by /target.html
:
build: article/foo article/bar article/baz/target.html
which is clearly not what you want. Ditto for the the rule.
You want this:
build: $(addsuffix /target.html,$(SUBDIRS))
(or you could use patsubst
instead if you prefer).
When writing the rule:
$(SUBDIRS)/target.html: $(SUBDIRS)/source.txt
you have the same problem, but the above solution still won't give you what you want. If you use the addsuffix
here you get this:
article/foo/target.html article/bar/target.html article/baz/target.html: article/foo/source.txt article/bar/source.txt article/baz/source.txt
which will sort of work but it means the same thing as this:
article/foo/target.html: article/foo/source.txt article/bar/source.txt article/baz/source.txt
article/bar/target.html: article/foo/source.txt article/bar/source.txt article/baz/source.txt
article/baz/target.html: article/foo/source.txt article/bar/source.txt article/baz/source.txt
so in other words, every target file depends on ALL the source files so if any source file changes, all the targets are recreated which is probably not what you want.
As alluded to by HolyBlackCat, you want a pattern rule which gives a template for how to build one target:
article/%/target.html: article/%/source.txt
make will apply this pattern rule to build each individual target.