(June 2018)
https://www.gnu.org/software/make/manual/html_node/Quick-Reference.html#Quick-Reference
The make
utility recompiles only those parts of a program that need to be recompiled.
It can do more than just compile C code — it automatically changes some files of any kind when other files change.
It needs a “Makefile” to tell it what to do.
The Makefile contains one or more rules.
Here’s a simple example.
We write the text of our book in the Markdown file “body.md”, and we want to ultimately produce “book.pdf”.
We produce “book.pdf” using pdflatex
to process “book.tex”.
The “book.tex” file wraps/includes (\input{.body.tex}
) the file “body.tex”.
We produce “body.tex” from “body.md” using pandoc
.
Our book contains a map, which we produce using Graphviz (dot
).
We could do this using a shell script, like:
#!/bin/sh
dot -Tsvg map.dot > map.svg
pandoc --wrap=none -f markdown+pipe_tables -o body.tex body.md
pdflatex book.tex
pdflatex book.tex
…but this runs dot
every time, even if when we didn’t change our map.
Instead, using the following Makefile, make
only run Graphviz when “map.dot” had changed.
book.pdf: book.tex body.tex img/map.svg
pdflatex book.tex
pdflatex book.tex
book.tex: body.md
pandoc --wrap=none -f markdown+pipe_tables -o body.tex body.md
img/map.svg: map.dot
dot -Tsvg map.dot > img/map.svg
The file must be named Makefile
, and exist in the directory where we run make
.
The general format of a rule is:
target: prerequisite …
command
…
The target is usually a file name, but doesn’t need to be.
A prerequisite(s) must match the name of an existing file or a target in the Makefile.
A rule does not require any prerequisites; zero prerequisites is valid.
Any specified prerequisite must exist before the target can be created.
For each prerequisite that matches a target, make
evaluates the matching rule before proceeding (and so forth down the tree of prerequisites).
For each target, if one of its prerequisites is newer, make
runs its commands.
Each command is passed to the shell (executed in its own sub-shell).
clean:
rm book.pdf body.tex img/map.svg
We can specify a target on the command-line to limit what happens (e.g., make clean
instead of simply make
).
By default, make
runs the first rule in the Makefile (which make
calls the “default goal”).
Long lines can be broken with backslashes (\
).
Comment lines start with #
.
Gotcha’s:
cd
to a particular directory to run, do it in one line, like cd src; fix.sh foo.txt
.Preview the build process without executing anything with make -n
or make --dry-run
.
objects = main.o kbd.o command.o display.o \
insert.o search.o files.o utils.o
…
clean :
rm mybinary $(objects)
A phony target is one that is not really the name of a file, like “clean”.
clean:
rm *.o *.tmp
What if our project contains a file named “clean”?
Explicitly tell make
that “clean” is a phony target with the special target .PHONY
, like:
.PHONY: clean
clean:
rm *.o *.tmp
Make checks the exit status of each shell return. By default, make abandons execution of the current rule if a command return a non-zero exit status. To ignore errors from a command, prefix it with a dash:
clean:
-rm -f *.o
$ make --just-print
$ make --print-data-base
$ make --warn-undefined-variables
$ make --debug
By default, make
echos its commands to STDOUT.
To silence a particular command, prefix it with @
, like:
clean:
@rm -f *.o
To silence everything, add:
ifndef VERBOSE
.SILENT:
endif
We can override the above by invoking make
like:
$ make VERBOSE=1