S. Domas Système d’Exploitation Make et la construction d’exécutables 1ère annéeIUT Belfort-Montbéliard
2 Définitions (1) S. Domas La compilation permet de transformer un fichier texte écrit dans un langage donné et de le transformer en fichier objet (.o ou.obj). Un fichier objet est structuré en plusieurs sections contenant entre autre du code executable (en assembleur), les données statiques et constantes. La commande objdump permet de lire le contenu d’un fichier objet. Par exemple : objdump -d fich_obj : donne le code assembleur. objdump -t fich_obj : donne la liste des symboles. objdump est très souvent utilisé pour retrouver un symbole, par exemple un nom de fonction.
3 Définitions (2) S. Domas Une bibliothèque est un concaténation simple de fichiers objet. Une bibliothèque n’est donc ni un exécutable, ni un fichier « include » (.h ) Une bibliothèque contient le code de fonctions. Un exécutable qui fait appel à ces fonctions doit utiliser la bibliothèque lors de l’édition de liens. Une bibliothèque peut être statique (.a ) ou dynamique (.so ). Dans le premier cas, le code de la bibliothèque est inclus dans l’exécutable. Dans le second cas, le code est chargé lors du lancement de l’exécutable.
4 Définitions (3) S. Domas L’édition de liens permet de combiner plusieurs fichiers objet en un fichier exécutable. gcc main.o menu.o mabibli.a –lm –o prog Le contenu d’un fichier exécutable pour Linux peut être listé avec readelf. En fonction des options choisie, l’utilitaire gcc permet d’appeler soit le compilateur, soit l’éditeur de lien (« linker »). Au sens strict, gcc n’est donc pas un compilateur mais désigne un ensemble de programmes contenant un compilateur et un éditeur de liens.
5 Définitions (4) S. Domas Make est un programme qui permet de lancer des commandes shell en fonctions de dépendances d'existence et de date entre des fichiers. Typiquement, make est utilisé pour compiler des sources dans un ordre précis et uniquement si les sources ont été modifiées depuis la dernière production de l'exécutable. Pour vérifier les dépendances de date, make utilise la date de dernière mise à jour des fichiers.
6 Structure (1) S. Domas Le fichier d'instruction contient un ou plusieurs blocs de la forme : cible : dependances commande 1 commande 2 … commande n Cela correspond à : si la cible est plus vieille que les fichiers donnés en dépendance, alors lancer chaque ligne commande x dans un shell différent.
7 Structure (2) S. Domas Le caractère tabulation est obligatoire devant la commande. La cible est généralement un fichier et la ou les commandes permettent de construire ce fichier. Par exemple, les dépendances peuvent être des fichiers objets (.o) et la cible un exécutable construit en faisant l’édition de lien des.o
8 Invocation de make S. Domas Dans tous les cas, les instructions que va recevoir make sont stockées dans un fichier texte. Si l'utilisateur tape (options entre []): make [-f fich_make] [nom_cible] make cherche dans le répertoire courant un fichier Makefile ou makefile et essaie de constuire la cible nom_cible En l’abscence de cible indiquée, make construit la première rencontrée. Avec –f, make va chercher ses instructions dans le fichier fich_make.
9 Exemple simple S. Domas On veut compiler main.c et fct.c pour en faire un exécutable nommé main. Ces deux fichiers incluent un fichier defs.h. fct.c contient des appels à sqrt() dont le code est dans libm.a. main : main.o fct.o gcc -o main main.o fct.o -lm main.o : main.c defs.h gcc -c main.c fct.o : fct.c defs.h gcc -c fct.c
10 Cible et dépendances S. Domas Attention ! Dans tous les cas, make cherche les fichiers cibles et dépendances à partir du répertoire où a été lancé make. Si une dépendance n'est pas dans le répertoire courant, il faut alors donner son chemin d'accès relatif. Dans l'exemple, si defs.h se trouve dans le sous répertoire include, alors il faut changer le makefile avec ces lignes : main.o : main.c include/defs.h fct.o : fct.c include/defs.h
11 Variables S. Domas make permet de manipuler ses propres variables. une variable se définit avec : nom_var = val1 val2 val3... (récursif) ou nom_var := val1 val2 val3... (non récursif) Par exemple : lstsrc = a.c lstsrc = b.c lstobj := a.o b.o lstobj := c.o Une variable s'utilise avec : $(nom_var) } lstsrc contient a.c b.c } lstobj contient c.o
12 Variables prédéfinies S. Domas : le nom de la cible. $< : le nom de la première dépendance. $^ : le nom de toutes les dépendances (séparées par des espaces. $? : le nom de toutes les dépendances plus récentes que la cible (séparées par des espaces).
13 Expansion de variable S. Domas Avant de passer la commande au shell, make fait sa propre expansion de variable, selon le même principe qu’en shell. Par exemple, si : SRCDIR = src SRC = a.c b.c alors $(SRCDIR)/$(SRC) vaut src/a.c b.c L’expansion peut faire du chercher/remplacer. Par exemple, si : OBJDIR = obj LSTOBJ = $(SRC:%.c=$(OBJDIR)/%.o) alors LSTOBJ contient obj/a.o obj/b.o
14 Exemple simple (2) S. Domas On peut réécrire l'exemple précédent en utilisant les variables : OBJ := main.o OBJ = fct.o (equivalent à OBJ := $(OBJ) fct.o ) INCL := defs.h LIBS = -lm main : $(OBJ) gcc -o $^ $(LIBS) main.o : main.c $(INCL) gcc -c $< fct.o : fct.c $(INCL) gcc -c $<
15 Règles implicites S. Domas make connaît un certain nombre de règles pour compiler des sources. Il sait par exemple comment transformer un fichier.c en.o. Pour cela, il utilise la commande : $(CC) -c $(CFLAGS) $< Ces règles sont appelées implicites par opposition aux règles explicites que l'on a utilisé dans l'exemple. Pour utiliser une règle implicite sur un fichier, il suffit de ne pas faire de règle explicite, (= ne pas indiquer comment construire le fichier à partir des dépendances).
16 Exemple simple (3) S. Domas On peut réécrire l'exemple précédent en utilisant les règles implicites : OBJ := main.o fct.o LIBS = -lm main : $(OBJ) gcc -o $^ $(LIBS) Attention ! Le fait de ne pas mettre le.h en dépendance implique que make ne recompilera pas les sources si defs.h a changé.
17 Création de règle implicite S. Domas Il est parfois utile de définir une nouvelle règle implicite. Par exemple, le répertoire courant étant projet, on veut produire des fichiers objets à partir de sources se trouvant dans le sous-répertoire src. SRCDIR = src # definition d’une nouvelle règle : %.o : $(SRCDIR)/%.c gcc –c $< Quand make doit produire un.o, il utilise cette nouvelle règle et va automatiquement chercher le.c correspondant dans src.
18 Cible abstraite S. Domas Une cible ne correspond parfois à aucun fichier. Elle est donc abstraite. Comme il n'existe aucune possibilité de vérifier sa date, la commande est forcément appliquée. Exemple : OBJ = main.o fct.o clean : $(OBJ) rm $(OBJ) S'il n'y a pas de fichier clean dans le répertoire, le rm est effectué à chaque lancement de make clean.