Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Pattern match for files in multiple subdirectories where the names of the subdirectories is unknown

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).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

.PHONY: build

SUBDIRS := $(wildcard article/*)

build: $(SUBDIRS)/target.html

$(SUBDIRS)/target.html: $(SUBDIRS)/source.txt
    echo "Generate html..." > $(SUBDIRS)/target.html

>Solution :

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.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading