This entry was originally submitted to Debian Package of the day, but rejected because make is well known.
Figure 1:The file
In is used to produce
InterM that is itself
used to produce
Out depends directly on
InterM and indirectly on
I agree that most programmers and administrators know GNU make. Sadly, it is ignored by most others. GNU
make solves a very common problem that everyone faces when processing more than one file with more than one programm. It keeps track which file has been changed and which files have to be regenerated.
Consider the abstract example of some output file
Out that is produced out of an intermediate file
InterM that itself is generated from some input file
In (see Figure 1). If
In is changed
make will reproduce
InterM and finally
Out. But if you only tweak
InterM you don’t want it to be overidden by the output of
Make will not do that unless
In is newer than
InterM (i.e. was changed after you tweaked with
We will take a short look at an example from the real-world of LaTeX. LaTeX is a typesetting system that produces nicely typeset postscript-files or PDF-files out of files containing the text in a special markup language. Assume that your LaTeX file
sample.tex includes two postscript (ps) figures like Figure 1 and 2 (get the tarball of the example here). These postscript files are generated from two description files by a software called graphviz.
sample.tex you typically type
dot -Tps -o figure1.ps figure1.dot # to produce Figure 1 dot -Tps -o figure2.ps figure2.dot # to produce Figure 2 latex sample.tex # to compile using latex dvips -o sample.ps sample.dvi # to generate a postscript-file
While editing your document, you have to type the above over and over again. This is tedious and error-prone. You may easily forget to run
dot after changing the figures or even forget what commands to use if you do not edit the text for a while. You may put the above in a shellscript, but then you have to add every figure to your shellscript and if you process a lot of figures it might take much longer than needed to compile your file, since all the figures are generated everytime you run your
Make solves both of these problems. Figure 2 illustrates the dependencies of the files. The information which file depends on which and how to produce one from the other is stored in a so called
Makefile. For our case it might look like this:
FIGURES=figure1.ps figure2.ps all: sample.ps # first rule sample.dvi: sample.tex $(FIGURES) # second rule latex sample.tex %.ps:%.dot # third rule dot -Grankdir=LR -Tps -o $@ $< %.ps:%.dvi # fourth rule dvips -o $@ $<
make detects a change of a file (here the green
figure1.dot) it rebuilds all parents that depend on it (here all red nodes).
So what does this mean?
- The first line defines a variable
FIGURES. If you want to include another figure in your build-process all you have to do is add it here.
- The second paragraph is called a rule (we will refer to it as first rule). It requests
maketo produce the left output (here:all) out of the right input (here: sample.ps). For reasons that will become clear later, we do not tell
makehow to produce “all”. Everything behind a hash
#is a comment.
- In the second rule the output depends on
sample.texand the figures. Note that the variable
FIGUREShas to be preceeded by a dollar sing and embraced by brackets. To fullfill this rule
makehas to run
latex. We tell it to do so by a line starting with a tab (here marked as ““; it is a very common beginners error to use spaces instead of tabs!). So whenever the dependencies are fullfilled but sample.dvi is not up to date,
- The third and fourth rule tell
makehow to produce a ps-file out of a dot-file or a dvi-file. The percentage sign
%is a wildcard character (similar to
*in the shell). The special variable
$@contains the target of the rule (the filename, which matches the left side) while
$<contains the source or dependency of the rule (the right side).
If you type
Makefile in the current directory will be scanned. Without any further arguments
make will try to build the target of the first rule in the
Makefile that is -in our case-
all. The target
all depends on
sample.ps that itself can be build from
sample.dvi by the last rule (
make needs to invoke the second rule, but first it must meet its dependencys: the figures. The third rule tells
make how to produce the figures and the dependacy is met since the dot-files exist. Once the ps-files are produced, the dependencys of the second rule are fullfilled and
latex to produce
sample.dvi that is then converted by the fourth rule to produce
make stops, since there is nothing to do for
all (this is called a phony target).
If you run
make again it will not do much but just say:
make: Nothing to be done for `all'.
Now change something in
figure1.dot and run
make another time. This time
make will rebuild
sample.ps to incorporate your changes (see Figure 2).
Everyone who uses the command line to mangle several input files into some output files.
- The GNU Make Manual.
- There are plenty of make-tutorials on the internet although very few focus on non-programmers.
- An example of a sophisticated Makefile for LaTeX.
- TeXFAQ about make
Other packages doing similar things:
mktex is a special tool that might be a handy replacement of
makeif you’re only focused on LaTeX.
- There exist many other buildtools avoiding some of make’s flaws.
You can find the most recent version of GNU make at ftp://ftp.gnu.org/gnu/make/.
Make is available for Debian and Ubuntu (and any other Linux-distribution).