You want Make to automatically build all sources in a given folder without having to specify them each time in the Makefile.
You can combine a wildcard to match all the sources, then use a patsubst to name the targets from these, and finally use a static pattern rule to generate the commands to build these.
Note that you could also use a for loop in a shell script inside the Makefile, but you might as well not use Make at that point :)
Example: Generating Graphs with Graphviz
In this example you want to generate PNG images from all the Graphviz dot files in your current directory. These can take a while so you want to use Make to only rebuild the images you’ve modified.
General wildcard patterns
Build all the dot files in the current directory to PNG files.
SOURCES=$(wildcard *.dot) TARGETS=$(patsubst %.dot,%.png,$(SOURCES)) all: $(TARGETS) %.png: %.dot dot -Tpng -o $@ $<
❯ make dot -Tpng -o my-graph.png my-graph.dot dot -Tpng -o my-other-graph.png my-other-graph.dot ❯ touch my-graph.dot ❯ make dot -Tpng -o my-graph.png my-graph.dot
Wildcards with subdirectories
This is a little more sophisticated, you want a directory with sources to go into a build directory. I include this mostly because I can’t remember the right amount of times to include the
build/ bit in the static patern and the
See also: order only pre-requisites.
BUILDDIR=build SOURCES=$(wildcard src/*.dot) TARGETS=$(patsubst src/%.dot,$(BUILDDIR)/%.png,$(SOURCES)) all: $(TARGETS) $(TARGETS): | $(BUILDDIR) # build the build directory first $(BUILDDIR): mkdir $(BUILDDIR) $(BUILDDIR)/%.png: src/%.dot dot -Tpng -o $@ $<
Note: I originally had
$(TARGETS): $(SOURCES) | $(BUILDDIR) but this caused all the targets to be rebuilt when one source changed. Defeating one of the goals of this approach.
❯ make mkdir build dot -Tpng -o build/my-graph.png src/my-graph.dot dot -Tpng -o build/my-other-graph.png src/my-other-graph.dot ❯ touch src/my-graph.dot ❯ make dot -Tpng -o build/my-graph.png src/my-graph.dot