Introduction to making Makefiles
Introduction to making Makefiles
Johannes Franken
make is an interpreter for Makefiles. A Makefile is much like a shell script with additional directions,<br>which qualify make to focus on the required lines. This will save you a lot of time.<br>Unfortunately common documentation stresses on compiling C programs. This guide shows how to use make for<br>workaday tasks, that have nothing to do with the C programming language.
Contents
What's in those Makefiles?
Explicit rules
Prerequisites
Referencing existing files
Implicit rules
User-defined variables and functions
Combining multiple Makefiles
Double-colon rules
Comparing timestamps
Patterns
Built-in functions
Automatic variables
Links
What's in those Makefiles?
A Makefile basically consists of
Definitions of variables and functions,
e.g. myshell=bash
Comments,
e.g. # converting postscript to pdf
Includes,
e.g. -include Makefile.local
Rules,
e.g. %.pdf: %.ps; -@ps2pdf $
Explicit rules
Basics
The generic anatomy of a rule is as follows:
target [ more targets] :[:] [ prerequisites ] [; commands]<br>[ commands ]<br>[ commands ]<br>...
Everything in square brackets is optional.<br>Rules that have got commands are called explicit, those which haven't are called implicit. This<br>chapter is about explicit rules.
Mind the tab key () prefacing the commands past the first line.<br>Use a semicolon to stuff multiple commands into one single line, or a backslash to join split lines.
Example
The following Makefile:
hello:<br>@echo hello \<br>world
diskfree:; df -h /
defines two rules (with targets hello and diskfree) and (explicitly...) assigns each of them a<br>short command. Now we can specifically call those commands:
$ make hello<br>hello world<br>$ make diskfree<br>df -h /<br>Filesystem Size Used Avail Use% Mounted on<br>/dev/hda6 43G 37G 3.6G 92% /
BTW: The at-sign (@) in front of the command prevents make from announcing the command it's<br>going to do.
Observation 1: If you don't tell make a target, it will simply do the first<br>rule:
$ make<br>hello world
Observation 2: If you tell make multiple targets, it will do them all in<br>order:
$ make diskfree hello<br>df -h /<br>Filesystem Size Used Avail Use% Mounted on<br>/dev/hda6 43G 37G 3.6G 92% /<br>hello world
Prerequisites
When getting dressed every morning, the order of installations should result from the following dependency tree:
It makes sure you're already wearing socks and trousers before getting into the shoes. We pronounce:<br>Socks and trousers are prerequisites for shoes.
and minute for the Makefile:
shoes: socks trousers<br>@echo put on shoes
Since make will substitute the target's name wherever it reads $@, we can generalize to:
shoes: socks trousers<br>@echo put on $@
If you pursue this method for the full tree in one-lined notation, you will get the following Makefile:
.PHONY: coat shoes mobile sweater socks\<br>trousers shirt pants undershirt
# target prerequisite command<br># ------------------------------------------------<br>coat: shoes mobile sweater; @echo put on $@<br>shoes: socks trousers; @echo put on $@<br>mobile: trousers; @echo put on $@<br>sweater: shirt; @echo put on $@<br>socks: ; @echo put on $@<br>trousers: pants shirt; @echo put on $@<br>shirt: undershirt; @echo put on $@<br>pants: ; @echo put on $@<br>undershirt: ; @echo put on $@
BTW: The .PHONY-directive tells make which target names have nothing to do with potentially<br>existing files of the same name. The next example will work out on that.<br>The result looks quite promising:
$ make coat | nl<br>1 put on socks<br>2 put on pants<br>3 put on undershirt<br>4 put on shirt<br>5 put on trousers<br>6 put on shoes<br>7 put on mobile<br>8 put on sweater<br>9 put on coat
Just in case I just wanted to get into my sweater and everything what's neccessary for it:
$ make sweater | nl<br>1 put on undershirt<br>2 put on shirt<br>3 put on sweater
BTW: That |nl doesn't belong to make. This little unix tool just numbers make's output<br>lines.
Referencing existing files
Task: In the last example make assumed there always was no prerequisite satisfied at<br>invocation time, means you have to be naked before getting dressed. Well, I prefer having a mug of coffee after<br>installing the basics and before putting on the uncomfortable articles. Now, how can I allow the following sequence to<br>work?
$ make shirt trousers socks<br>$ drink coffee<br>$ make coat
Basic approach: Ascertaining the steps to the coat must be split in two parts. For this to work,<br>make has to save the state after the first run. So I create an empty file after finishing each target, with<br>the filename equal to the target's name. When I now take out the .PHONY-line, make will conclude<br>from an existing file to a satisfied target. Exactly speaking, it will compare the timestamps of target's and<br>prerequisite's files. See next chapter for details on this.
Solution: The following Makefile:
# target prerequisite command<br># ----------------------------------------------------------<br>coat: shoes mobile sweater; @echo put on $@; touch $@<br>shoes: socks...