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 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
Where We Are
This Makefile contains all of our work so far.
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.