Principe de base
La syntaxe de base du makefile consiste à définir:
- une cible
- des dépendances (optionnelles)
- les commandes à exxécuter pour réaliser la cible
cible: dependance1 dependance2 ...
commande1
commande2
- La cible peut être soit un fichier à produire ou une cible virtuelle.
- Les dépendances peuvent être des fichiers ou d’autres cibles
Avant de construire une cible, make va vérifier si les dépendances sont à jour et les reconstruire si nécessaire.
Une fois la chaine des dépendances parcourue, le dernier élement est généralement un fichier, make va alors reconstruire la cible associée uniquement si le fichier a été modifié puis remonter la chaine de dépendance afin de générer la cible désirée.
Cibles usuelles
- make all
- généralement la première cible du makefile (exécuté lorsque make est appelé sans argument)
- génère l’ensemble du projet
- make test
- compile et exécute les tests
- make install
- installe le logiciel sur l’hôte
- make clean
- Supprime les fichiers générés
Phony
La directive phony permet de lister toutes les cibles qui ne correspondent pas à des fichiers, mais sont des cibles virtuelles (ex: all, clean, etc.)
.PHONY: all clean install
Macros
CC=gcc # déclaration
$(CC) # utilisation
Les opérandes dispos sont les suivantes:
| Opérande | Signification |
|---|---|
| = | Affectation simple |
| ?= | Définition de la macro seulement si pas encore définie |
| += | Concaténation |
Variables internes
| Variable | Signification |
|---|---|
| $@ | Nom de la cible |
| $? | Toutes les dépendances plus récentes que la cible |
| $< | Première dépendance |
| $^ | Toutes les dépendances |
| $* | Le nom du fichier sans l’extension |
Règle générique
Il est possible de définir des règles génériques pour une extension donnée
%.o: %.c
$(CC) -o $@ -c $< $(CFLAGS)
Chaque fichier .o sera donc dépendant du fichier .c associé (même nom de fichier) et sera construit selon la commande décrite. On utilise les variables internes afin de récupérer la cible et la dépendance de manière automatique.
Fonctions
Wildcard
SRC=$(wildcard *.c)
La variable SRC contient la liste de tous les fichiers *.c
Création de la liste des fichiers objet
OBJ=$(SRC:.c=.o)
La variable OBJ contient la liste de tous les fichiers .o construite à partir de la liste des fichiers .c
Substitution
La commande patsubst permet de remplacer un pattern dans une chaine (ex une liste de fichier) par une chaine de notre choix.
OBJ=$(patsubst %.c, build/%.o, $(SRC))
La commande ci-dessus remplace chaque fichier .c présent dans la liste SRC par la chaine build/<nom_fichier>.o
Exemple
- Si
SRC=file1.c file2.c - Alors
OBJ=build/file1.o build/file2.o
Chemin absolu
La commande abspath renvoie le chemin abslolu d’un fichier ou d’un dossier.
file_abs=$(abspath <file>)
Sous-makefile
On veut parfois avoir plusieurs makefile qui puissent être appelés par un fichier makefile maitre.
Le makefile maitre peut déclarer des macros qui seront également définies dans les makefile enfants. Pour cela, il faut les déclarer avec le mot clé export
export CC=gcc
Ensuite, le makefile enfant est appelé grâce à la variable $(MAKE). 2 possibilités pour indiquer le makefile enfant:
# Option 1
cd <subdir> && $(MAKE)
# Option 2
$(MAKE) -C <subdir>
📝 Le Makefile enfant est appelé avec les mêmes options que le makefile parent si aucune option n’est indiquée explicitement dans l’invocation par le makefile parent.
On peut également passer des variables/macros au makefile enfant depuis le makefile parent, directement depuis la commande
$(MAKE) -C <subdir> MYVAR=<value>
Dans ce cas particulier, on pourra déclarer la variable en utilisant l’opérande ?=: Si la variable est définie par le makefile parent, celle-ci n’est pas rédéfinie. Mais si la variable n’est pas positionnée par le makefile parent, celle-ci possède une valeur par défaut.
Fichier type
CC=gcc
CFLAGS=-W -Wall -ansi
SRC_DIR=src
BUILD_DIR=build
SRC=$(wildcard $(SRC_DIR)/*.c)
OBJ=$(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.o, $(SRC))
.PHONY: all clean
all: myExecutable
myExecutable: $(OBJ)
$(CC) -o $(BUILD_DIR)/$@ $^
%.o: %.c
mkdir -p $(BUILD_DIR)
$(CC) -o $@ -c $< $(CFLAGS)
clean:
rm -rf $(BUILD_DIR)