UtilitiesMake
In a typical coding project, some files will be processed to produce other files as output. For example, programs written in C are compiled into
We call the output files target files, and the input files are called source files. The source-target relationships of a project are a crucial component of the structure of the project, because the processing steps are required to reproduce the analysis or update the target files to reflect changes in the source. However, this important structure is not usually apparent from the source and target files themselves.
There are at least two ways to address this problem: (1) document the processing steps in a README file, or (2) write a Makefile, which can be processed by a command-line utility called make to actually carry out the processing steps. The second approach documents the source-target relationships and makes them executable.
Suppose, for example, that we have a file called raw-data.csv
which contains some data we are meant to analyze. We write some code in a file called clean-data.py
to process that data and write a file called clean-data.csv
. Then we run model.py
to do some analysis and come up with a model that we save in a file called model.pkl
. Our Makefile would look something like this:
all : model.pkl
model.pkl : model.py clean-data.csv
python model.py
clean-data.csv : clean-data.py raw-data.csv
python clean-data.py
clean :
rm model.pkl
rm clean-data.csv
.PHONY all
The basic formula for a Makefile entry is
target : dependencies
recipe
The command-line function make
looks at whether the dependencies have changed since the target was last built, if they have then it runs the commands in the corresponding recipe.
The target
can either be an actual target file or a phony target, which is a name used to refer to a given processing step. The phony targets should be declared in a line that begins .PHONY
and lists the phony targets. It's conventional to include the phony targets all
and clean
. These correspond to the operations "build everything" and "remove the target files".
Specific targets can be invoked at the command line by running make targetname
. For example, make all
builds everything and make clean
removes the target files. The target may be omitted, in which case it defaults to the first target in the file.
Exercise
Write a Makefile which runs pdflatex my-document.tex
to produce my-document.pdf
whenever my-document.tex
changes. Include the phony targets all
and clean
. Assume that pdflatex
will produce auxiliary files my-document.aux
and my-document.log
.
Solution. We remove the auxiliary files with clean
and make all
include just the target my-document.pdf
:
all : my-document.pdf
my-document.pdf : my-document.tex
pdflatex my-document.tex
clean :
rm my-document.aux
rm my-document.log
.PHONY all clean