Quick start
If you're working in a project that already uses make,
there should be a file called Makefile in the top-level directory.
Running:
$ make
should build the project from source.
What is make?
make is a tool designed to manage dependencies in a build process.
For instance, if you have two source files, a.in and
b.in, and you need to build b.in before you build
a.in, then you might have a Makefile in the same
directory that looks like this:
a.out: a.in b.out commands to generate a.out from a.in and b.out b.out: b.in commands to generate b.out from b.in
Now, suppose you want to build a.out; you run:
$ make a.out
At this point, make's thought process becomes:
-
Run
make b.out. -
If
a.outis newer thana.inandb.out, halt. -
If
a.outis older thana.inorb.out, run:commands to generate a.out from a.in and b.out
If you run:
$ make b.out
then make's thought process becomes:
- If
b.outis newer thanb.in, halt. - If
b.outis older thanb.in, run:commands to generate b.out from b.in
In short, when ordered to build a file,
make will ensure that all dependencies are up to date,
and it will not rebuild any those which need not be rebuilt.
Makefile structure
Makefiles contain definitions and rules.
A definition has the form:
VAR=value
A rule has the form:
output files: input files commands to turn inputs to outputs
All commands must be tab-indented.
To reference the variable VAR, surround it with
$(VAR).
A simple example for C
Here's a simple example for a C program that defines
foo() in foo.c, but uses it in bar.c.
CC=gcc bar: bar.c foo.h foo.o $(CC) -o bar bar.c foo.o foo.o: foo.c foo.h $(CC) -c foo.c run: ./bar clean: rm -f bar foo.o
Conventions
It's common to include pseudo-targets in makefiles to automate other parts of the development process.
make clean
The rule for clean
in the previous example
doesn't build a file called clean.
Rather, it deletes all of the build targets to allow a fresh build from scratch.
Including a clean rule is a common convention
for make.
make test
Running make test often runs
the test suite for the software.
make install
Running make install typically installs
the compiled binary in a PATH-accessible location.
For software using the autoconf toolchain,
the installation directory is set by running ./configure
command prior to using make.
make run
For simple programs, make run acts like an alias
to the compiled binary.
Generic rules
If a project contains many conversions of one file type to another,
e.g. .c to .o,
it gets tedious to write the commands over and over.
First, define file suffixes
with a .SUFFIXES declaration; for example:
.SUFFIXES: .tex .pdf
Then, create a generic rule for converting one suffix to another:
.input.output: commands to convert something.input into something.output
Within the commands, you can reference
the input filename with $<.
You can reference the output filename
with $@.
For a complete example with LaTeX:
all: doc.pdf .SUFFIXES: .tex .pdf .tex.pdf: pdflatex $<
Running make file.pdf will now run
pdflatex file.tex.
Complex generic rules
For complex generic rules, the pattern % may be used
in both inputs and outputs.
For example, we might want a LaTeX build to depend on both the source file and the auto-generated bibliography file:
%.dvi: %.tex %.blg latex $<
Somewhat confusingly, the commands for these generic rules cannot reference
% to insert the basename of the build target.
To refer to the basename of the target file, use $(basename $@).
Substituting shell commands
To substitute in the value of a shell command,
use $(shell command).
For instance, suppose you wanted to compile all
.java files simultaneously, you might have this rule:
Foo.class: $(shell find . -name *.java) javac $<
Further reading
Robert Mecklenberg provides one of the few comprehensive
overviews of (GNU) make in book form:
It's also available as an O'Reilly open book.
And, after make, there is
the autotool site: