Systèmes d’Exploitation I
Travaux Pratiques 0
ÉTUDE PRÉLIMINAIRE
La compilation avec Make
Amine DHRAIEF
make
● make est un logiciel qui construit automatiquement des fichiers, souvent
exécutables, ou des bibliothèques à partir d'éléments de base tels que
du code source.
● Il utilise des fichiers appelés makefile (Makefile) qui spécifient comment
construire les fichiers cibles.
● À la différence d'un simple script shell, make exécute les commandes
seulement si elles sont nécessaires.
– Le but est d'arriver à un résultat (logiciel compilé ou installé, documentation créée, etc.)
sans nécessairement refaire toutes les étapes.
● make est particulièrement utilisé sur les plateformes UNIX.
18/01/18
2
make
● make sert principalement à faciliter la compilation et l'édition
de liens puisque dans ce processus le résultat final dépend
d'opérations précédentes.
● Pour ce faire, make utilise un fichier de configuration appelé
makefile qui porte souvent le nom de Makefile. Ce dernier
décrit des cibles (qui sont souvent des fichiers, mais pas
toujours), de quelles autres cibles elles dépendent, et par
quelles actions (des commandes) y parvenir.
● make cherche dans le répertoire courant le makefile à utiliser.
18/01/18
3
make
● Un Makefile est un fichier constitué de plusieurs règles de la forme :
cible: dependance
[tab] commandes
● Chaque commande est précédée d'une tabulation.
● Lors de l'utilisation d'un tel fichier via la commande make la première règle
rencontrée, ou la règle dont le nom est spécifié, est évaluée. L'évaluation
d'une règle se fait en plusieurs étapes :
Publicité
– Les dépendances sont analysées, si une dépendance est la cible d'une autre règle du
Makefile, cette règle est à son tour évaluée.
– Lorsque l'ensemble des dépendances est analysé et si la cible ne correspond pas à un
fichier existant ou si un fichier dépendance est plus récent que la régle, les différentes
commandes sont exécutées.
18/01/18
4
Exemple
● hello.c
#include <stdio.h>
#include <stdlib.h>
void Hello(void)
printf("Hello World\n");
{
}
18/01/18
5
Exemple
● hello.h
void Hello(void);
18/01/18
6
Exemple
● main.c
#include <stdio.h>
#include <stdlib.h>
#include "hello.h"
int main(void)
{
}
Hello();
return EXIT_SUCCESS;
18/01/18
7
Exemple
● Makefile
hello: hello.o main.o
gcc -o hello hello.o main.o
Publicité
hello.o: hello.c
gcc -o hello.o -c hello.c -W -Wall -ansi
-pedantic
main.o: main.c hello.h
gcc -o main.o -c main.c -W -Wall -ansi -pedantic
8
18/01/18
Exemple
● Nous cherchons à créer le fichier exécutable hello, la première
dépendance (hello.o) est la cible d'une des règles de notre Makefile, nous
évaluons donc cette règle. Comme aucune dépendance de hello.o n'est
une règle, aucune autre règle n'est à évaluer pour compléter celle-ci.
● Deux cas se présentent ici : soit le fichier hello.c est plus récent que le
fichier hello.o, la commande est alors exécutée et hello.o est construit,
soit hello.o est plus récent que hello.c est la commande n'est pas
exécutée. L’évaluation de la règle hello.o est terminée.
● Les autres dépendances de hello sont examinées de la même manière
puis, si nécessaire, la commande de la règle hello est exécutée et hello
est construit.
18/01/18
9
Exemple
● Plusieurs cas ne sont pas gérés dans l'exemple précédent :
– Un tel Makefile ne permet pas de générer plusieurs exécutables distincts.
– Les fichiers intermédiaires restent sur le disque dur même lors de la mise en production.
– Il n'est pas possible de forcer la regénération intégrale du projet
● Ces différents cas conduisent à l'écriture de règles complémentaires :
– all : généralement la première du fichier, elle regroupe dans ces dépendances
l'ensemble des exécutables à produire.
– clean : elle permet de supprimer tout les fichiers intermédiaires.
– mrproper : elle supprime tout ce qui peut être régénéré et permet une reconstruction
complète du projet.
● En ajoutant ces règles complémentaires, notre Makefile devient donc :
18/01/18
10
Makefile
all: hello
Exemple
Publicité
hello: hello.o main.o
gcc -o hello hello.o main.o
hello.o: hello.c
gcc -o hello.o -c hello.c -W -Wall -ansi -pedantic
main.o: main.c hello.h
gcc -o main.o -c main.c -W -Wall -ansi -pedantic
clean: rm -rf *.o
mrproper: clean
rm -rf hello
18/01/18
11
Exemple
● Il est possible de définir des variables dans un Makefile, ce qui rend les
évolutions bien plus simples et plus rapides, en effet plus besoin de
changer l'ensemble des règles si le compilateur change, seule la variable
correspondante est à modifier.
● Une variable se déclare sous la forme NOM=VALEUR et se voir utiliser via
$(NOM).
– Nous allons donc définir quatre variables dans notre Makefile :
● Une désignant le compilateur utilisée nommée CC (une telle variable est
typiquement nommé CC pour un compilateur C, CXX pour un compilateur
C++).
– CFLAGS regroupant les options de compilation (Généralement cette variable est
nommées CFLAGS pour une compilation en C, CXXFLAGS pour le C++).
– LDFLAGS regroupant les options de l'édition de liens.
– EXEC contenant le nom des exécutables à générer.
18/01/18
12
Exemple
CC=gcc
CFLAGS=-W -Wall -ansi -pedantic
LDFLAGS=
EXEC=hello
all: $(EXEC)
hello: hello.o main.o
$(CC) -o hello hello.o main.o $(LDFLAGS)
hello.o: hello.c
$(CC) -o hello.o -c hello.c $(CFLAGS)
Publicité
main.o: main.c hello.h
$(CC) -o main.o -c main.c $(CFLAGS)
clean:
rm -rf *.o
mrproper: clean
18/01/18
rm -rf $(EXEC)
13
Exemple
● -W -Wall : Valider les avertissements (warnings)
décrits en arguments. Il en existe une multitude.
mais l'option la plus couramment utilisée est
-Wall , pour activer tous les avertissements.
● -pedantic : Le compilateur fournit des
avertissements encore plus rigoureux qu'avec
-Wall, principalement orientés sur la portabilité du
code
● -ansi : Compatible avec la norme C Ansi
18/01/18
14
Exemple
● Pour compiler le projet
– $make
● Pour supprimer tout les fichiers intermédiaires.
– $make clean
● Pour supprimer tout ce qui peut être régénéré et
permet une reconstruction complète du projet.
– $make mrproper
18/01/18
15
The END
18/01/18
16