Premiers pas avec le makefile
Makefile de base
Envisagez d’écrire un “hello world!” programme en c. Disons que notre code source est dans un fichier appelé source.c, maintenant pour exécuter notre programme, nous devons le compiler, généralement sous Linux (en utilisant gcc), nous aurions besoin de taper $> gcc source.c -o output
où sortie est le nom de l’exécutable à générer. Pour un programme de base, cela fonctionne bien, mais à mesure que les programmes deviennent plus complexes, notre commande de compilation peut également devenir plus complexe. C’est là qu’un Makefile entre en jeu, les makefiles nous permettent d’écrire un ensemble assez complexe de règles sur la façon de compiler un programme, puis de le compiler simplement en tapant make sur la ligne de commande. Par exemple, voici un exemple possible de Makefile pour l’exemple hello wold ci-dessus.
Makefile de base
Faisons un Makefile de base et sauvegardons-le sur notre système dans le même répertoire que notre code source nommé Makefile. Notez que ce fichier doit être nommé Makefile, cependant le M majuscule est facultatif. Ceci dit il est relativement classique d’utiliser un capitol M.
output: source.c
gcc source.c -o output
Notez qu’il y a exactement un onglet avant la commande gcc sur la deuxième ligne (c’est important dans les makefiles). Une fois ce Makefile écrit chaque fois que l’utilisateur tape make (dans le même répertoire que le Makefile) make vérifiera si source.c a été modifié (vérifie l’horodatage) s’il a été modifié plus récemment que la sortie il s’exécutera la règle de compilation sur la ligne suivante.
Variables dans les Makefiles
Selon le projet, vous souhaiterez peut-être introduire certaines variables dans votre fichier make. Voici un exemple de Makefile avec des variables présentes.
CFLAGS = -g -Wall
output: source.c
gcc $< $(CFLAGS) -o $@
Explorons maintenant ce qui s’est passé ici. Dans la première ligne, nous avons déclaré une variable nommée CFLAGS qui contient plusieurs drapeaux communs que vous pouvez souhaiter passer au compilateur, notez que vous pouvez stocker autant de drapeaux que vous le souhaitez dans cette variable. Ensuite, nous avons la même ligne qu’avant indiquant à make de vérifier source.c pour voir s’il a été modifié plus récemment que output, si c’est le cas, il exécute la règle de compilation. Notre règle de compilation est essentiellement la même qu’avant mais elle a été raccourcie en utilisant des variables, la variable $<
est intégrée à make (appelée variable automatique voir https://www.gnu.org/software/make /manual/html_node/Automatic-Variables.html) et il représente toujours la source donc dans ce cas source.c. $(CFLAGS)
est notre variable que nous avons définie auparavant, mais notez que nous avons dû mettre la variable entre parenthèses avec un $ devant comme ceci$(someVariable)
. C’est la syntaxe pour dire à Make d’étendre la variable à ce que vous avez tapé auparavant. Enfin, nous avons le symbole $@, encore une fois, il s’agit d’une variable intégrée à make, et il représente simplement la cible de l’étape de compilation, donc dans ce cas, il représente output.
Nettoyer
Make clean est un autre concept utile pour en savoir plus sur les fichiers make. Permet de modifier le * Makefile * d’en haut
CFLAGS = -g -Wall
TARGETS = output
output: source.c
gcc $< $(CFLAGS) -o $@
clean:
rm $(TARGETS)
Comme vous pouvez le voir, nous avons simplement ajouté une règle supplémentaire à notre Makefile, et une variable supplémentaire qui contient toutes nos cibles. C’est une règle assez courante dans les makefiles car elle vous permet de supprimer rapidement tous les binaires que vous avez produits simplement en tapant $> make clean
. En tapant make clean, vous dites au programme make d’exécuter la règle de nettoyage, puis make exécutera la commande rm pour supprimer toutes vos cibles.
J’espère que ce bref aperçu de l’utilisation de make vous aidera à accélérer votre flux de travail, * Makefiles * peut devenir très complexe, mais avec ces idées, vous devriez pouvoir commencer à utiliser make et avoir une meilleure compréhension de ce qui se passe chez les autres programmeurs * Makefiles*. Pour plus d’informations sur l’utilisation de make, une excellente ressource est https://www.gnu.org/software/make/manual/.
Définir des règles
Démarrage rapide
Une règle décrit quand et comment certains fichiers (les cibles de la règle) sont créés. Il peut également servir à mettre à jour un fichier cible si l’un des fichiers nécessaires à sa création (prérequis de la cible) est plus récent que la cible.
Les règles suivent la syntaxe ci-dessous : (Notez que les commandes suivant une règle sont mises en retrait par une tabulation)
targets: prerequisites
<commands>
où targets et prerequisites sont des noms de fichiers ou des noms réservés spéciaux et les commandes (le cas échéant) sont exécutées par un shell pour construire/reconstruire des targets qui sont obsolètes.
Pour exécuter une règle, il suffit d’exécuter la commande make
dans le terminal à partir du même répertoire où réside le Makefile. L’exécution de make
sans spécifier la cible exécutera la première règle définie dans le Makefile. Par convention, la première règle du Makefile est souvent appelée all ou default, répertoriant généralement toutes les cibles de construction valides comme prérequis.
make
n’exécute la règle que si la cible est obsolète, ce qui signifie qu’elle n’existe pas ou que son heure de modification est antérieure à l’un de ses prérequis. Si la liste des prérequis est vide, la règle ne sera exécutée que lorsqu’elle sera invoquée pour la première fois pour créer les cibles. Cependant, lorsque la règle ne crée pas de fichier et que la cible est une variable factice, la règle sera toujours exécutée.
Règles de modèle
Les règles de modèle sont utilisées pour spécifier plusieurs cibles et construire des noms de prérequis à partir de noms de cible. Elles sont plus générales et plus puissantes que les règles ordinaires car chaque cible peut avoir ses propres prérequis. Dans les règles de modèle, une relation entre une cible et un prérequis est établie sur la base de préfixes comprenant des noms de chemin et des suffixes, ou les deux.
Imaginez que nous voulions construire les cibles foo.o
et bar.o
, en compilant les scripts C, foo.c
et bar.c
, respectivement. Cela pourrait être fait en utilisant les règles ordinaires ci-dessous :
foo.o: foo.c
cc -c $< -o $@
bar.o: bar.c
cc -c $< -o $@
où variable automatique $<
est le nom du premier prérequis et $@
le nom de la cible (Une liste complète des variables automatiques peut être trouvée [ici](https://www.gnu.org/ software/make/manual/html_node/Automatic-Variables.html#Automatic-Variables)).
Cependant, comme les cibles partagent le même suffixe, les deux règles ci-dessus peuvent désormais être remplacées par la règle de modèle suivante :
%.o: %.c
cc -c $< -o $@
Règles implicites
Des règles implicites indiquent à make
comment utiliser les méthodes habituelles pour construire certains types de fichiers cibles, qui sont très souvent utilisés. make
utilise le nom du fichier cible pour déterminer quelle règle implicite invoquer.
L’exemple de règle de modèle que nous avons vu dans la [section précédente] (#pr), n’a pas réellement besoin d’être déclaré dans un Makefile car make
a une règle implicite pour la compilation C. Ainsi, dans la règle suivante, les prérequis foo.o
et bar.o
seront construits en utilisant la règle implicite pour la compilation C, avant de construire foo
.
foo : foo.o bar.o
cc -o foo foo.o bar.o $(CFLAGS) $(LDFLAGS)
Un catalogue de règles implicites et des variables qu’elles utilisent peut être trouvé [ici][posix-implicit].
[posix-implicite] : http://pubs.opengroup.org/onlinepubs/9699919799/utilities/make.html#tag_20_76_13_09 [//] : # (À FAIRE : règles du double-virgule)
règle générique pour compresser un fichier
si un répertoire contient 2 fichiers :
$ ls
makefile
example.txt
et makefile
contiennent le texte suivant
%.gz: %
gzip $<
alors vous pouvez obtenir example.txt.gz
en tapant dans le shell
$ make -f makefile example.txt.gz
le makefile consiste en une seule règle qui indique à make comment créer un fichier dont le nom se termine par .gz s’il existe un fichier portant le même nom mais avec le suffixe .gz.
makefile Bonjour le monde
C:\makefile :
helloWorld :
[TAB]echo hello world
résultats de l’exécution :
C:\>make
echo hello world
hello world
Remarque : [TAB] doit être remplacé par un véritable onglet, stackoverflow remplace les tabulations par des espaces et les espaces ne sont pas utilisés de la même manière que les tabulations dans un makefile.