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.out
is newer thana.in
andb.out
, halt. -
If
a.out
is older thana.in
orb.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.out
is newer thanb.in
, halt. - If
b.out
is 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: