OverviewTeaching: 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
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
%.dat : books/%.txt countwords.py python countwords.py $< $*.dat
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)
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
%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
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 $< $@
Use the wildcard
%as a placeholder in targets and dependencies.
Use the special variable
$*to refer to matching sets of files in actions.