Comment les Makefiles automatisent la compilation GCC et vous font gagner du temps

7

Taper de longues commandes « gcc » à plusieurs reprises est pénible. La situation empire lorsque vous ajoutez des bibliothèques ou modifiez constamment le code. Makefiles corrige ce problème. Ils automatisent le processus de construction afin que vous arrêtiez de taper les mêmes commandes encore et encore.

Voici un exemple simple de Makefile. Il remplace une séquence de compilation manuelle.

Enregistrez-le dans un fichier nommé makefile. Exécutez make pour construire l’exécutable. Il existe une règle stricte. Vous devez utiliser un caractère de tabulation avant chaque ligne gcc. Huit espaces échoueront. L’outil de construction le rejettera. Toutes les autres lignes doivent commencer par la marge gauche.

Comprendre les dépendances

Un Makefile comporte deux types de lignes. Les lignes alignées à gauche sont des lignes de dépendance. Ils définissent les relations entre les fichiers. Les lignes à onglets sont des commandes exécutables. Il peut s’agir de n’importe quelle commande UNIX valide.

Prenez cette ligne :
main.o : main.c util.h

Cela dit que « main.o » dépend de « main.c » et « util.h ». Si l’un des fichiers source change, la commande située en dessous s’exécute. Il recrée « main.o ».

La première ligne du fichier est spéciale. Il définit l’objectif final. Dans ce cas, il s’agit de l’exécutable « principal ». Il répertorie « main.o » et « util.o » comme dépendances. Si ces fichiers objets sont plus récents que la source, Make les reconstruit. Ensuite, il les relie dans le binaire final.

Cette commande s’exécute uniquement si les dépendances changent. Si rien n’a changé, Make ne fait rien. C’est le principal avantage. Cela évite le travail déjà effectué.

Pourquoi c’est important pour votre flux de travail

Les grands programmes disposent de nombreuses bibliothèques et fichiers sources. Le suivi des fichiers modifiés manuellement est sujet aux erreurs. Un Makefile gère cela automatiquement. Il recompile uniquement ce qui est nécessaire. Vous modifiez un fichier d’en-tête. Make reconstruit chaque fichier source qui l’inclut. Vous modifiez une fonction utilitaire. Make reconstruit uniquement ce fichier objet et relie l’exécutable.

Vous n’avez pas besoin d’être sur un système UNIX pour utiliser cette logique. La plupart des compilateurs et IDE modernes incluent des fonctionnalités similaires. Vérifiez la documentation de votre compilateur. Recherchez des outils d’automatisation de build. Ils fonctionnent de la même manière sous le capot.

Cela nous ramène à des en-têtes comme « stdio.h ». Vous les avez inclus dans des exemples précédents sans expliquer pourquoi. Ce sont des bibliothèques standards. Quelqu’un les a écrits il y a des années. Ils les ont mis à disposition pour vous éviter de réinventer les fonctions de base. Les Makefiles et les bibliothèques standards s’inscrivent dans la même philosophie. Ils vous permettent de vous concentrer sur la logique plutôt que sur le passe-partout.

L’outil est aussi bon que ses règles. Si vos dépendances sont erronées, Make ne parviendra pas à reconstruire ce qu’il devrait. Ou pire, cela créera du code obsolète. Vérifiez vos caractères de tabulation. Vérifiez vos noms de fichiers. Obtenez la bonne syntaxe et le compilateur fait le gros du travail.

Vous vous demandez peut-être si la compilation manuelle est toujours plus rapide. Pour un seul fichier, peut-être. Mais dès que vous touchez un en-tête dans un projet multi-fichiers, la méthode manuelle perd. Vous commencez à copier les commandes. Vous commencez à faire des fautes de frappe. Vous commencez à vous demander pourquoi « main.o » n’a pas été mis à jour.

Le véritable gain est le passage de la saisie de commandes à la définition de règles. Vous définissez l’État. L’outil applique les transitions. C’est un petit changement d’habitude. Cela s’avère payant dans chaque construction ultérieure.