You can get all the info on this page in more detail from man make or
from the
GNU Make Manual. A nice intro to makefiles, that works through
one example in detail (and is not focusing on compiling C programs) can also
be found on
jfranken.
Contents
- Overview
- Comments
- Targets
- Prerequisites
- Commands
- Rules
- Macros
- Patterns
- Functions
- Variables
- Including
- Shell
- Example
make is a tool to automate rebuilding of files that are
dependend on other files. The dependency rules are written in a
Makefile
.
Rules consist of
targets that depend on so-called
prerequisites. Whenever any of the prerequisites
changed, the target will be rebuilt, using
shell
commands given by the rule (or using global commands
given for the involved name
patterns, if no specific
rule was found). Since a prerequisite can be the target for another rule,
you can build large trees of prerequisites, and make can infer, which files
to update, if some file in the tree changed.
A
# at line start turns the line into a comment line that will
be ignored by make. Use backslashes
\ at the end of a line to split
a long line into several lines on screen. Lists are spearated by white
space.
Normally, make expects the targets and prerequisites to be files, so it
can compare their timestamps to decide if one of the prerequisites is newer
than the target, and the target has to be updated using the rule.
If you specify a target for which no file exists (a so called "phony"
target), there is no timestamp to compare, and the rule will
always
be run. You can also treat a target for which a file exists as phony
(forcing its rule to be always run), by assigning it to the .PHONY special
name. Also, a target which ultimately depends on phony targets can not
compare timestamps, and will always be run.
Special names
Special names are target names that make make treat their prerequisites
in a special way. They are all starting with a dot and written in upper
case, and there aree many more than the ones listed here.
.PHONY prerequisites of .PHONY are considered to be phony
targets. make will run its commands regardless of whether a file with that
name exists or what its last-modification time is.
.IGNORE prerequisites for .IGNORE ignore errors in execution of
the commands run for those particular files.
.EXPORT_ALL_VARIABLES this tells make to export all variables to
child processes. It is more of a general option and uses no
prerequisites.
Here is an example of prerequisites.
For this in one-lined notation, you will get the following Makefile:
# target prerequisite commands
# ----------------------------------------------------
house: roof plumbing electrics; @echo $@; touch $@
plumbing: pipes basement; @echo $@; touch $@
roof: walls; @echo $@; touch $@
electrics: walls wires; @echo $@; touch $@
walls: basement bricks; @echo $@; touch $@
pipes: ; @echo $@; touch $@
basement: ; @echo $@; touch $@
bricks: ; @echo $@; touch $@
wires: ; @echo $@; touch $@
The touch command serves to create the targets as files, so that when you
ran
make plumbing, and then
make house, pumbing, pipes and
basement would already exist and not have to be build again.
Commands can be any shell commands.
@ at the beginning of a
command means "dont print the line before executing",
- means "dont
exit on error".
Rules can be written in one line for short rules
target(s) : [prerequisites] [; shell-command(s)]
Or in the full format for more involved commands (note the TAB)
target(s) : [prerequisites]
[TAB shell-command]
[TAB shell-command]
...
Make starts with the first rule that has a name not starting with a dot,
if not invoked for a specific rule. The other rules are processed because
their targets appear as prerequisites of this goal, and so on. If some rule
is not needed for this, that rule is not processed. If several targets are
given for a rule, it's as if there were as many rules, each with one
target.
You can split each rule into two parts:
- An implicit rule stating the prerequisites, and
- an explicit one for the commands.
Any rules in the last example lead to the same commands and differed in
their prerequisites only. For those rules that have no prerequisites (e.g.
bricks) you don't even need an implicit rule. The explicit ones can
be pooled, because of their commands being all identic. Thus you get a
shorter and pretty clear Makefile:
# An explicit rule assigns the commands for several targets
house plumbing roof electrics walls pipes basement bricks wires: ; @echo $@; touch $@
# Implicit rules state the prerequisites
house: roof plumbing electrics
plumbing: pipes basement
roof: walls
electrics: walls wires
walls: basement bricks
Use
= or
:= to assign values to variables (so called
macros), depending on if potentially contained variables and
functions should be expanded at
using or
declaration time.
Fringe space is stripped. Macros assigned with
= must be declared
above any uses, or they will still be empty.
To retrieve the stored value, write
$(myvar). Macros are
expanded by substituting the assigned values textually for the name. To have
make executing the value (like a function), write
$(call
myvar).
Often you have long lists of files that all have a similar form (similar
extensions, names, etc), and have to be processed in the dsame way. In this
case, you will not want to write a rule for every single file, what you want
is a rule that says "for files that look like that, do this". Patterns allow
you to do this. A target pattern is composed of a `%' between a prefix and a
suffix, either or both of which may be empty. For example:
%.class: %.java; javac $<
The way it works is that any name that matches the target pattern will
invoke the rule. The part of the name that matched the wildcard will be
substituted for the wildcard in the prerequisites.
Pattern rules may have more than one target. Unlike normal rules, this
does not act as many different rules with the same prerequisites and
commands. If a pattern rule has multiple targets, `make' knows that the
rule's commands are responsible for making all of the targets. The commands
are executed only once to make all the targets.
The used to be special suffix rules. These are now superceded by pattern
rules.
Often, simple patterns are not enough, and you will want to mangle
filenames in various other ways. Here is a bunch of built-in funtions for
this purpose.
$(subst from,to,text) |
Replace from with
to in text. |
$(patsubst pattern,replacement,text) |
Replace words matching pattern with
replacement in text. |
$(strip string) |
Remove excess whitespace characters
from string. |
$(findstring find,text) |
Locate find in text. |
$(filter
pattern...,text) |
Select words in text that
match one of the pattern words. |
$(filter-out pattern...,text) |
Select words in text that do not match any
of the pattern words. |
$(sort list) |
Sort the words in list
lexicographically, removing duplicates. |
$(dir names...) |
Extract the directory part of each file
name. |
$(notdir names...) |
Extract the non-directory part of
each file name. |
$(suffix names...) |
Extract the suffix (the last dot and following
characters) of each file name. |
$(basename names...) |
Extract the base name (name without
suffix) of each file name. |
$(addsuffix suffix,names...) |
Append suffix to each word in
names. |
$(addprefix
prefix,names...) |
Prepend prefix to each word in
names. |
$(join list1,list2) |
Join two parallel lists of words. |
$(word n,text) |
Extract the nth word
(one-origin) of text. |
$(words text) |
Count the number of words in text. |
$(wordlist s,e,text) |
Returns the list of words in text
from s to e. |
$(firstword names...) |
Extract the first word of names. |
$(wildcard
pattern...) |
Find file names matching a shell file
name pattern (not a `%' pattern). |
$(error text...) |
When this function is evaluated, make generates a fatal
error with the message text. |
$(warning text...) |
When this function is evaluated, make
generates a warning with the message text. |
$(shell command) |
Execute a shell command and return its output. |
$(origin variable) |
Return a string describing how the
make variable variable was defined. |
$(foreach var,words,text) |
Evaluate text with var bound to
each word in words, and concatenate the results. |
$(call var,param,...) |
Evaluate the variable var replacing
any references to $(1),$(2) with the first, second, etc.
param values. |
There are some predefined variables for use in rules (called
dynamic
macros, because they look a bit like macros and there contents are set
dynamically during rule evaluation):
$@ |
The name of the target. |
$% |
The target member name, when the target is an archive
member. |
$< |
The name of the first (or only)
prerequisite. |
$? |
The names of all the prerequisites that are newer than
the target, with spaces between them. |
$^
$+ |
The names of all the prerequisites,
with spaces between them. The value of $^ omits duplicate
prerequisites, while $+ retains them and preserves their
order. |
$* |
The stem with which an implicit rule matches. |
$(@D)
$(@F) |
The directory part and the
file-within-directory part of $@ |
$(*D)
$(*F) |
The directory part and the file-within-directory part
of $* |
$(%D)
$(%F) |
The directory part and the
file-within-directory part of $% |
$(<D)
$(<F) |
The directory part and the file-within-directory part
of $< |
$(^D)
$(^F) |
The directory part and the
file-within-directory part of $^ |
$(+D)
$(+F) |
The directory part and the file-within-directory part
of $+ |
$(?D)
$(?F) |
The directory part and the
file-within-directory part of $? |
When your project is large, a single giant makefile can become ratehr
unwiedly. You can split your makefiles into several files and inline those
during runtime. When make encounters an
include-command, it will
stop processing the current Makefile, read the included Makefile and then
continue where it left off. If you don't want it to abort when the included
Makefile's missing, just say
-include Makefile(s) (the minus sign
generallly make s make ignore errors).
Escaping variables in make: When using $ variables inside make (for shell
commands, or Perl special vars) write $$ instead of $.
Make treats every line as running in a new subshell, and thus forgetting
about the previous lines. This will shoot down shell scripts that have loops
or if statements spanning several lines. So you ahve to put your whole
conditional on one line. Remember, when writing one-line shell conditionals,
you have to end every block and condition with a semicolon. So
for x in a b c do
echo $x
done
becomes
for x in a b c;\
do\
echo $$x;\
done
# Example Makefile
sourcefiles = Main.java Gui.java Logic.java
compiler=javac
jc=$(compiler -warn)
all: $(sourcefiles) docs clean
# A phony target, not really the name of a file. It is
# just a name for some commands to be executed when you make an explicit
# request.
clean:
-@ $(RM) *~
-@ $(RM) *.class
# % is the wildcard char for targets or prerequisites (like
# in SQL), $< is the current prerequisite (points to the target on the
# left), $@; is the current target (looks a bit like a target for
# shooting)
%.class: %.java; $(jc) $<