Introduction to Making Makefiles

pillmillipedes1 pts0 comments

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...

make echo shoes target socks trousers

Related Articles