Makefiles


Sommaire

Comment créer et utilise un makefile ?

C’est quoi un makefile ?

Make sert a gérer les exécutable et la compilation de programmes, make est très efficace pour les gros projets car il permet de recompiler uniquement ce qui a été modifié.

Make sert aussi a plusieurs petites choses comme par exemple archivé des fichiers ect…

Comment créer un make ?

Pour créer un make dans un premier temps je dois crée un fichier nommé : Makefile

Voici de quoi se constitue un fichier Makefile :

<cible> : <dependances>
	<commande>

Un Makefile peut se constituer de variable (fortement conseillé), les variables ont des noms d’usage, pas obligatoire mais souvent utilisé, elles permettent de gagner énormément de temps.

# CC / CXX -> CXX = C++ -> Pour la compilation
# CFLAGS / CXXFLAGS -> Flags de compilation
# LDFLAGS -> Edition de links
# SRC -> endroit ou se trouvent les fichiers .c
# OBJ -> permet de cibler les fichiers .o
# EXEC -> nom de l'executable
# Variables spéciales
$@ -> nom de la cible
$< -> nom premiere dependance
$^ -> liste dependances
$? -> liste dependances plus recente que la cible
$* -> nom fichier sans son extension

# Declaration de variable :
CC = gcc
EXEC = prog
CFLAGS = -Wall -Wextra -Werror
SRC = $(wildcard *.c) -> Je lui dit de prendre tout les fichiers .c
OBJ = $(SRC:.c=.o) -> Je lui dit comme SRC mais a la place de .c -> .o

# Pour appelé une variable il suffit de faire ceci :
$(CC)

La technique OBJ = $(SRC:.c=.o) ne dépend pas de l’existence préalable des fichiers .o. Elle se base uniquement sur la liste des .c connus, construisant automatiquement les noms .o correspondants. Ainsi make sait qu’il doit créer main.o à partir de main.c, même si le fichier objet n’existe pas encore.

Il est possible de crée des conditions qui ont la syntaxe suivante :

WINDOWS = yes
ifeq ($(WINDOWS), yes) # Si la variable windows est = a yes (ifeq = if equal)
	$(EXEC) = prog.exe
else
	$(EXEC) = prog
endif

Comment mettre en forme un make ?

L’utilisation des variables spécial est très utiles quand on gère un projet avec plusieurs fichiers.

Avant toutes choses, make est tres sensible, il faut donc crée des cibles avec soins et logique.

Afin d’avoir un exemple concret de l’utilité des variables, je vais créer 2 exemples un sans variable et un avec des variables.

Makefile sans variables

Dans l’exemple si-dessous je crée la cible all et la cible qui compile mon projet.

Fichiers : main.c | test.c

all : prog

prog :
	cc -Wall -Wextra -Werror *.c

.PHONY : all

Ici le make vas compiler et me donner un binaire nommé a.out je peux exécuter mon programme correctement car j’ai un fichier main.c qui contient la fonction main.

Mais concrètement qu’est ce que je lui ai dit ? Ce make on peux le décomposer en 3 parties :

  1. all : Je crée la cible all, pour l’utilisé je fait make all
  2. all : prog : Pour crée la cible all je dépend de prog donc sans prog je ne pourrais pas fait make all. Une erreur plus ou moins similaire s’affichera : make: *** Aucune règle pour fabriquer la cible « prog », nécessaire pour « all ». Arrêt.
  3. prog : Je crée donc la cible prog dont all est dépendant.

Cependant ce Makefile n’utilise pas le potentiel de cet outil. Vu que je n’ai pas compilé avec les objets je ne bénéficie pas de la recompilation sélective c’est a dire que chaque modification d’un fichier .c vas forcer la recompilation de tout le projet.

Pour ce faire je dois faire de cette manière :

all : prog

prog : %.o
	cc -Wall -Wextra -Werror *.o -o prog
%.o : %.c
	cc -Wall -Wextra -Werror -c %.c -o %.o

Makefile composé de variables

Dans l’exemple si-dessous je veux crée un exécutable qui prend en compte plusieurs fichiers qui seront pour cette exemple : test1.c | test2.c | test3.c | main.c

Les fichiers sont dans le dossier srcs

Pour commencer, je déclare mes variables qui seront utiles pour mes cibles.

CC = cc
CFLAGS = -Wall -Wextra -Werror
SRC = $(wildcard srcs/*.c)
EXEC = prog

Ensuite je vais crée mes cibles avec les variables

CC = cc
CFLAGS = -Wall -Wextra -Werror
SRC = $(wildcard srcs/*.c)
EXEC = prog

all : $(EXEC)

$(EXEC) : $(SRC)
	$(CC) $(CFLAGS) $(SRC) -o $(EXEC)

Cas d’erreur et comment les gérer

Vous serez surement amener a crée une librairie avec diverses fonctions, pour gagner du temps a la compilation, vous décidez de faire un make.

Naïvement, vous allez faire quelques commandes qui s’apparente a celle-ci :

cc -Wall -Wextra -Werror -c *.c
ar rcs libexemple.a *.o

cc -Wall -Wextra -Werror main.c -L. -lexemple

Il est possible de crée des commandes (cible) pour organiser ces fichiers par exemple clean ect

clean : # Je ne met pas de dependance car je n'en ai pas besoin pour cela
	rm -rf *.o

Pour éviter que make confond cible et fichier (Exemple : fichier clean et cible clean) il faut ajouter .PHONY afin d’éviter toute confusions et de lancer la cible sans que make la considère comme “a jour”.

.PHONY : all clean

Sources : Makefile tutorial

Partager :

Articles similaires

Les listes chainées

Les listes chainées

Les listes a la base n’existe pas en C, elles sont le résultat d’une manipulation de pointers et de structures.

Lire la suite