Pattern Rules
Overview
Teaching: 10 min
Exercises: 0 minQuestions
How can I define rules to operate on similar files?
Objectives
Write Make pattern rules.
Our Makefile (available via git checkout 05-patterns) still has
repeated content. The rules for each .dat
file are identical apart
from the text and data file names. We can replace these rules with a
single pattern rule which
can be used to build any .dat
file from a .txt
file in books/
:
%.dat : books/%.txt countwords.py
python countwords.py $< $*.dat
%
is a Make wildcard. $*
is a special
variable which gets replaced by the stem with
which the rule matched.
This rule can be interpreted as:
“In order to build a file named [something].dat
(the target)
find a file named books/[that same something].txt
(the dependency)
and run countwords.py [the dependency] [the target]
.”
If we re-run Make,
$ make clean
$ make dats
then we get:
python countwords.py books/isles.txt isles.dat
python countwords.py books/abyss.txt abyss.dat
python countwords.py books/last.txt last.dat
Note that we can still use Make to build individual .dat
targets as before,
and that our new rule will work no matter what stem is being matched.
$ make sierra.dat
which gives the output below:
python countwords.py books/sierra.txt sierra.dat
Using Make Wildcards
The Make
%
wildcard can only be used in a target and in its dependencies. It cannot be used in actions. In actions, you may however use$*
, which will be replaced by the stem with which the rule matched.
Our Makefile is now much shorter and cleaner:
# Generate summary table.
results.txt : testzipf.py isles.dat abyss.dat last.dat
python $< *.dat > $@
# Count words.
.PHONY : dats
dats : isles.dat abyss.dat last.dat
%.dat : books/%.txt countwords.py
python countwords.py $< $*.dat
.PHONY : clean
clean :
rm -f *.dat
rm -f results.txt
This episode has introduced pattern rules, and used the $*
variable
in the dat
rule in order to explain how to use it.
Arguably, a neater solution would have been to use $@
to refer to
the target of the current rule (see below),
but then we wouldn’t have learned about $*
.
%.dat : books/%.txt countwords.py
python countwords.py $< $@
Key Points
Use the wildcard
%
as a placeholder in targets and dependencies.Use the special variable
$*
to refer to matching sets of files in actions.