Fichier Makefile

Puisque la commande make sert à générer des fichiers, le contenu du Makefile est centré sur ce concept. Tout fichier (résultat ou source) est considéré comme un but. les fichiers à mettre à jour sont donc autant de buts à atteindre.

Exemple

Voici un exemple simplifié mais complet :

exemple : extension.o main.o
	gcc -ansi -pedantic -o exemple extension.o main.o -lm
 
extension.o : extension.c extension.h
	gcc -ansi -pedantic -c extension.c
 
main.o : main.c extension.h
	gcc -ansi -pedantic -c main.c

Règles de dépendance

L'essentiel d'un Makefile est composé de règles. La première ligne d'une règle établit une dépendance entre le but principal (le premier nom) et les buts secondaires (les noms après les deux points). Les lignes qui suivent, si elles commencent par une tabulation, donnent les commandes à exécuter pour générer le but principal.

Lorsque make veut mettre à jour un fichier, il cherche la règle qui prend ce fichier comme but principal. S'il n'y en a pas, on considère que le fichier est déjà à jour (c'est le cas pour tous les fichiers sources). S'il trouve une règle, la mise à jour est possible, mais pas forcément nécessaire.

make commence par mettre à jour tous les buts secondaires (par la même méthode). Il compare ensuite la date de dernière modification de tous les buts. Si le but principal est plus récent que les buts secondaires, il n'y a rien à faire. Sinon, la mise à jour est nécessaire : on exécute les commandes associées à la règle.

But initial

Une invocation de make n'utilise pas forcément toutes les règles du Makefile. On cherche à mettre à jour un seul fichier, que l'on nomme but initial. Par défaut, c'est le but principal de la première règle du Makefile. On peut également choisir le but initial en passant son nom en argument sur la ligne de commande.

make met seulement ce fichier à jour, mais s'il dépend d'autres fichiers, ceux-ci seront également mis à jour, et ainsi de suite en cascade. Il est tout à fait possible que certaines règles ne soient pas incluses dans cet enchaînement, et dans ce cas elles n'ont aucun effet.

But factice

Parfois on souhaite que certaines commandes soient exécutées à coup sûr. Une technique pour y arriver est de réclamer un fichier qui n'existe pas : c'est ce qu'on appelle un but factice.

clean :
	rm -f extension.o main.o

Dans cet exemple, il n'y a pas de fichier clean. Le but est donc considéré comme non à jour, et la commande rm est forcément exécutée. Cela permet de lancer la commande :

bob@box:~$ make clean
lorsque l'on veut effacer les fichiers objets.

Malheureusement, cette technique ne marche plus si on crée un fichier clean ! Pour éviter toute confusion, on peut prévenir make que le but clean est factice en ajoutant la règle:

.PHONY : clean

Règles implicites

make connait quelques règles universelles qui permettent de gagner du temps. Par exemple, aucune règle n'est nécessaire pour lui expliquer comment passer d'un fichier .c à un fichier .o : il le fait tout seul.

S'il y a des dépendances inhabituelles, on en écrit juste assez pour qu'il comprenne :

extension.o : extension.h

Remarquez ici qu'on a «oublié» une dépendance et toute la commande, mais ça marche quand même.

Variables

Pour du texte que vous allez devoir répéter plusieurs fois, il est possible de définir des variables.

OFILES = extension.o main.o
 
exemple : $(OFILES)
	gcc -ansi -pedantic -o exemple $(OFILES) -lm

Il existe même des variables prédéfinies, telles que CC pour indiquer le compilateur à utiliser dans les règles implicites, et CFLAGS pour les options à lui passer.

Divers

On peut ajouter des commentaires : ils commencent par # et se finissent par un saut de ligne.

Les sauts de ligne marquent d'ailleurs la fin d'un élément en général (commentaire, affectation, dépendance, commande). Si vous souhaitez revenir à la ligne sans finir un élément, utilisez une contre-oblique(\) juste avant le saut de ligne.

Exemple

Voici le même exemple que plus haut, mais en exploitant tout ce que nous avons vu.
### VARIABLES ###
 
CC = gcc
CFLAGS = -Wall \
         -ansi \
         -pedantic
LIBS = -lm
EXE = exemple
OFILES = extension.o \
         main.o
 
### BUT PAR DEFAUT ###
 
but : ${EXE}
 
### REGLES ESSENTIELLES ###
 
extension.o : extension.h
 
main.o : extension.h
 
${EXE} : ${OFILES}
	$(CC) $(CFLAGS) -o ${EXE} ${OFILES} ${LIBS}
 
### REGLES OPTIONNELLES ###
 
run : but
	./${EXE}
 
clean :
	-rm -f ${OFILES} ${EXE}
 
mrproper : clean but
 
### BUTS FACTICES ###
 
.PHONY : but clean mrproper
 
### FIN ###

retour à la page d'accueil

retour au sommet