6 Compilation séparée et utilisation de l'utilitaire make
La commande make permet de déterminer automatiquement quelles
parties d'un programme sont à recompiler et génère les commandes pour
ce faire. Il est très utile pour la compilation séparée, où un
programme est constitué de plusieurs fichiers sources.
Exercice 21
Séparez votre programme en deux fichiers sources
fbib.c et fact.c. Le premier ne contient
que les définitions des fonctions
factorielle_iterative(),
factorielle_recursive() et factorielle(). Le
second ne contient que la fonction main(). Créez un
fichier fbib.h contenant la déclaration de la
fonction factorielle :
extern unsigned int factorielle(unsigned int);
et incluez ce fichier dans fact.c :
#include <stdio.h>
#include "fbib.h"
...
Remarquez l'utilisation des doubles quotes pour indiquer au
compilateur de chercher le fichier d'entêtes fbib.h dans
le répertoire courant en premier. Sans utiliser make,
pour compiler le programme, il faut exécuter les commandes
suivantes:
% gcc -c -Wall -Werror -ansi -pedantic fbib.c
% gcc -c -Wall -Werror -ansi -pedantic fact.c
% gcc -Wall -Werror -ansi -pedantic -o fact fact.o fbib.o
L'option -c de gcc permet de spécifier au
compilateur de ne pas faire l'édition de liens, et de ne générer
que les fichiers objets .o.
Exercice 22
Créez un fichier Makefile (ou makefile) avec le
contenu suivant :
CC = gcc
CFLAGS = -Wall -Werror -ansi -pedantic
CFLAGS += -g
fact: fact.o fbib.o
$(CC) $(CFLAGS) -o fact fact.o fbib.o
fact.o: fact.c
$(CC) -c $(CFLAGS) fact.c
fbib.o: fbib.c
$(CC) -c $(CFLAGS) fbib.c
Les lignes correspondantes aux commandes à exécuter commencent par
une tabulation
(et non une série d'espaces...). Lancez la
compilation par la commande make (ou make
fact si la première règle de dépendance ne concerne pas
fact). Les trois compilations sont automatiquement
exécutées. En modifiant la date du fichier fbib.c,
et en recompilant,
% touch fbib.c
% make
seule la compilation de fbib.c et l'édition de
liens sont exécutées, le fichier fact.c étant resté
inchangé.
Exercice 23
En fait, make connaît déjà un ensemble de règles de
dépendance par défaut, et seule la première dépendance suffit.
L'option -p de make liste la base de données
(variables et règles de dépendance) utilisée. Pour vous en
convaincre, essayez de supprimer les 4 dernières lignes de
Makefile.
Dans un Makefile, on place aussi une entrée clean
pour faire le ménage des fichiers intermédiaire et une entrée
realclean qui ne conserve que le strict nécessaire. Ces
entrées ne correspondent pas à des fichiers à construire, on le
précise à make par la directive .PHONY :
CC = gcc
CFLAGS = -Wall -Werror -ansi -pedantic
CFLAGS += -g
fact: fact.o fbib.o
$(CC) $(CFLAGS) -o fact fact.o fbib.o
.PHONY: clean realclean
clean:
$(RM) factorielle.o main.o
realclean : clean
$(RM) factorielle
Partisan du moindre effort (et de la moindre erreur), on peut
rassembler l'ensemble des fichiers .o dans une variable
OBJ et utiliser la variable automatique $@
:
CC = gcc
CFLAGS = -Wall -Werror -ansi -pedantic
CFLAGS += -g
OBJ = fbib.o fact.o
fact: $(OBJ)
$(CC) $(CFLAGS) -o $@ $(OBJ)
.PHONY: clean realclean
clean:
$(RM) $(OBJ)
realclean : clean
$(RM) fact
On termine alors une séance de TP par :
% make realclean
rm -f fbib.o fact.o
rm -f fact