Vous êtes sur la page 1sur 5

Ecriture dun Makefile

ENSIMAG 1A
Anne scolaire 20082009

Un Makefile est un fichier, utilis par le programme make, regroupant une srie de commandes permettant dexcuter un ensemble dactions, typiquement la compilation dun
projet. Un Makefile peut tre crit la main, ou gnr automatiquement par un utilitaire (exemples : automake, gmake, . . .). Il est constitu dune ou de plusieurs rgles de la
forme :
cible: dpendances
commandes
Lors du parcours du fichier, le programme make value dabord la premire rgle rencontre, ou celle dont le nom est spcifi en argument. Lvaluation dune rgle se fait
rcursivement :
1. les dpendances sont analyses : si une dpendance est la cible dune autre rgle,
cette rgle est son tour value ;
2. lorsque lensemble des dpendances a t analys, et si la cible est plus ancienne que
les dpendances, les commandes correspondant la rgle sont excutes.

Exemple

Ce qui suit prsente la cration dun Makefile pour un exemple de projet. Supposons
pour commencer que ce projet regroupe trois fichiers exemple.h, exemple.c et main.c.

1.1

Makefile de base

Un fichier Makefile de base de ce projet pourrait scrire :


mon_executable: exemple.o main.o
gcc -o mon_executable exemple.o main.o
exemple.o: exemple.c
gcc -o exemple.o -c exemple.c -Wall -O
main.o: main.c exemple.h
gcc -o main.o -c main.c -Wall -O
1

En effet pour crer lexcutable mon_executable, nous avons besoin des fichiers objets
exemple.o et main.o. make va dabord rencontrer exemple.o, et va donc valuer la rgle
dont ce fichier est la cible. La seule dpendance de cette rgle tant exemple.c, qui nest
pas cible dune autre rgle, make va excuter la commande :
gcc -o exemple.o -c exemple.c -Wall -O
De la mme faon, make va ensuite analyser la rgle dont main.o est la cible et excuter
la commande :
gcc -o main.o -c main.c -Wall -O
Finalement, toutes les dpendances de la rgle initiale ayant t analyses, make va excuter la commande :
gcc -o monexecutable exemple.o main.o

1.2

Un premier raffinement

Pour amliorer ce Makefile, on peut rajouter quelques cibles standards :


all : placer gnralement au dbut du fichier ; les dpendances associes correspondent
lensemble des excutables produire ;
clean : normalement pas de dpendance ; la commande associe supprime tous les
fichiers intermdiaires (notamment les fichiers objets) ;
mrproper : la commande correspondante supprime tout ce qui peut tre regnr, ce
qui permet une reconstruction complte du projet lors de lappel suivant make.
Notre Makefile devient donc ici :
all: mon_executable
mon_executable: exemple.o main.o
gcc -o mon_executable exemple.o main.o
exemple.o: exemple.c
gcc -o exemple.o -c exemple.c -Wall -O
main.o: main.c exemple.h
gcc -o main.o -c main.c -Wall -O
clean:
rm -f *.o core
mrproper: clean
rm -f mon_executable
2

1.3

Introduction de variables

Il est possible de dfinir des variables dans un Makefile. Elles se dclarent sous la forme
NOM=valeur et sont appeles sous la forme $(NOM), peu prs comme dans un shellscript.
Parmi quelques variables standards pour un Makefile de projet C ou C++, on trouve :
CC qui dsigne le compilateur utilis ;
CFLAGS qui regroupe les options de compilation ;
LDFLAGS qui regroupe les options ddition de liens ;
EXEC ou TARGET qui regroupe les excutables.
Pour notre projet exemple, cela donne :
CC=gcc
CFLAGS=-Wall -O
LDFLAGS=
EXEC=mon_executable
all: $(EXEC)
mon_executable: exemple.o main.o
$(CC) -o mon_executable exemple.o main.o $(LDFLAGS)
exemple.o: exemple.c
$(CC) -o exemple.o -c exemple.c $(CFLAGS)
main.o: main.c exemple.h
$(CC) -o main.o -c main.c $(CFLAGS)
clean:
rm -f *.o core
mrproper: clean
rm -f $(EXEC)
Il existe aussi, et cest encore plus intressant car trs puissant, des variables internes au
Makefile, utilisables dans les commandes ; notamment :
$@ : nom de la cible ;
$< : nom de la premire dpendance ;
$ : liste des dpendances ;
$? : liste des dpendances plus rcentes que la cible ;
$* : nom dun fichier sans son suffixe.
On peut donc encore compacter notre Makefile :
CC=gcc
CFLAGS=-Wall -O
LDFLAGS=
3

EXEC=mon_executable
all: $(EXEC)
mon_executable: exemple.o main.o
$(CC) -o $@ $^ $(LDFLAGS)
exemple.o: exemple.c
$(CC) -o $@ -c $< $(CFLAGS)
main.o: main.c exemple.h
$(CC) -o $@ -c $< $(CFLAGS)
clean:
rm -f *.o core
mrproper: clean
rm -f $(EXEC)

1.4

Rgles dinfrences

On voit nanmoins quil y a encore moyen damliorer ce Makefile : en effet les rgles dont
les deux fichiers objets sont les cibles se ressemblent fortement. Or justement, on peut
crer des rgles gnriques dans un Makefile : il suffit dutiliser le symbole % la fois pour
la cible et pour la dpendance. Il est galement possible de prciser sparement dautres
dpendances pour les cas particuliers, par exemple pour ne pas oublier la dpendance au
fichier exemple.h pour la rgle dont main.o est la cible. Ceci nous donne :
CC=gcc
CFLAGS=-Wall -O
LDFLAGS=
EXEC=mon_executable
all: $(EXEC)
mon_executable: exemple.o main.o
$(CC) -o $@ $^ $(LDFLAGS)
main.o: exemple.h
%.o: %.c
$(CC) -o $@ -c $< $(CFLAGS)
clean:
rm -f *.o core
mrproper: clean
4

rm -f $(EXEC)

1.5

Liste des fichiers objets et liste des fichiers sources

On peut encore simplifier ce Makefile. En effet, on constate que la gnration de lexcutable dpend de tous les fichiers objets. Ceci peut tre long crire dans le cas dun
gros projet ! Pour simplifier lcriture, sachant que tous les fichiers objets correspondent
aux fichiers sources en remplaant lextension .c par lextension .o, on peut utiliser les
variables SRC et OBJ et dfinir OBJ=$(SRC :.c=.o). SRC sera dfinie par la liste des fichiers
sources . . . ce qui na fait que dplacer le problme ! L encore, une syntaxe particulire
permet de simplifier le Makefile : SRC=$(wildcard *.c). wildcard permet lutilisation
de la variable $* en dehors dune commande.
Le Makefile du projet exemple devient finalement :
CC=gcc
CFLAGS=-Wall -O
LDFLAGS=
EXEC=mon_executable
SRC=$(wildcard *.c)
OBJ=$(SRC:.c=.o)
all: $(EXEC)
mon_executable: $(OBJ)
$(CC) -o $@ $^ $(LDFLAGS)
main.o: exemple.h
%.o: %.c
$(CC) -o $@ -c $< $(CFLAGS)
clean:
rm -f *.o core
mrproper: clean
rm -f $(EXEC)
Il existe encore bien dautres possibilits pour simplifier un Makefile. Il est notamment
possible de crer des Makefile pour des sous-rpertoires correspondant des sous-parties
du projet, et davoir un Makefile matre trs simple qui appelle ces sous-Makefile,
avec la variable MAKE. Il existe galement des outils de gnration automatique.

Vous aimerez peut-être aussi