Automation and Make

Pattern Rules

Overview

Teaching: 15 min
Exercises: 15 min
Questions
  • 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 wordcount.py
        python wordcount.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 wordcount.py [the dependency] [the target].”

If we re-run Make,

$ make clean
$ make dats

then we get:

python wordcount.py books/isles.txt isles.dat
python wordcount.py books/abyss.txt abyss.dat
python wordcount.py books/last.txt last.dat

Our new rule will work no matter what stem is being matched.

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 : *.dat zipf_test.py
	    python zipf_test.py *.dat > $@

# Count words.
.PHONY : dats
dats : isles.dat abyss.dat last.dat

%.dat : books/%.txt wordcount.py
      python wordcount.py $< $*.dat

.PHONY : clean
clean :
      rm -f *.dat
      rm -f results.txt

Where We Are

This Makefile contains all of our work so far.

Key Points