4. Make

4.1. Qu'est-ce que make?

Lorsque vous travaillez sur un programme simple avec seulement un ou deux fichiers de source, taper:

% cc fichier1.c fichier2.c
n'est pas trop gênant, mais cela devient rapidement très fastidieux lorsqu'il y a plusieurs fichiers - et cela peut aussi mettre du temps à compiler.

Un façon d'éviter ces problèmes est d'utiliser des fichiers objets et de ne recompiler que les fichiers de source dont le contenu a changé. Nous pourrions alors avoir quelque chose du style:

% cc fichier1.o fichier2.ofile37.c
si nous avons modifé fichier37.c, et celui-là uniquement, depuis notre compilation précédente. Cela peut sérieusement accélérer la compilation, mais ne résout pas le problème de saisie à répétition de la commande.

Nous pourrions aussi écrire une procédure pour résoudre ce dernier problème, mais ne ne pourrions alors que lui faire tout recompiler, ce qui serait très peu efficace sur un gros projet.

Que ce passe-t-il si nous avons des centaines de fichiers de sources? Si nous travaillons en équipe et que d'autres oublient de nous prévenir des modifications qu'ils ont apportées à un des fichiers que nous utilisons?

Peut-être pourrions-nous rassembler les deux solutions et écrire quelque chose qui ressemble à une procédure et comporte une sorte de règle magique qui dise quand tel fichier de source doit être compilé. Nous n'aurions plus besoin que d'un programme qui comprennent ces règles, parce que c'est un peu trop compliqué pour une procédure.

Ce programme s'appelle make. Il lit un fichier, qu'on appelle un makefile, qui lui dit quelles sont les dépendances entre les différents fichiers, et en déduit lesquels ont besoin ou non d'être recompilés. Par exemple, une règle peut signifier quelque chose comme “si fromboz.o est plus ancien que fromboz.c, cela veut dire que fromboz.c doit avoir été modifié, il faut donc le recompiler”. Le fichier “makefile” inclut aussi des règles qui lui disent comment recompiler, ce qui en fait un outil encore plus puissant.

Ces fichiers “makefiles” sont habituellement rangés dans le même répertoire que les sources auxquels ils s'appliquent, et peuvent être appelés makefile, Makefile ou MAKEFILE. La plupart des programmeurs utilisent le nom Makefile, ce qui fait qu'ils se trouvent alors vers le début de la liste des fichiers et sont ainsi facilement repérables [1].

4.2. Exemple d'utilisation de make

Voici un fichier Makefile élémentaire :


foo: foo.c
      cc -o foo foo.c
       
Il contient deux lignes, une pour la dépendance et une pour la génération.

La ligne décrivant la dépendance contient le nom du programme (qu'on appelle la cible), suivi de “deux points”, puis d'un blanc et du nom du fichier source. Quand make lit cette ligne, il regarde si foo existe; s'il existe, il compare la date de dernière modification de foo à celle de dernière modification de foo.c. Si foo n'existe pas, ou s'il est antérieur à foo.c, il regarde alors la ligne de génération pour savoir ce qu'il faut faire. En d'autres termes, c'est la règle à appliquer pour savoir si foo.c doit être recompilé.

La ligne de génération commence par une tabulation (appuyez sur la touche Tab) suivie de la commande que vous taperiez pour compiler foo si vous le faisiez sur la ligne de commande. Si foo n'est pas à jour ou s'il n'existe pas, make exécute alors cette commande pour le créer. En d'autres termes, c'est la règle qui dit à make comment recompiler foo.c.

Ainsi, quand vous tapez make, il fera en sorte que foo soit en phase avec les dernières modifications que vous avez apportées à foo.c. Ce principe s'étend aux Makefiles avec des centaines de cibles - de fait, sur FreeBSD, il est possible de compiler tout le système d'exploitation en tapant simplement make world dans le répertoire adéquat!

Une autre particularité de Makefiles est que les cibles ne sont pas nécessairement des programmes. Nous pourrions par exemple avoir le Makefile suivant:


foo: foo.c
      cc -o foo foo.c

install:
      cp foo /home/me
       


Nous pouvons dire à make quelle cible nous voulons atteindre en tapant:

% make cible
make examinera alors cette cible et ignorera toutes les autres. Par exemple, si, avec le Makefile précédent, nous tapons make foo, make ignorera la cible install.

Si nous tapons simplement make tout court, il examinera toujours la première cible et s'arrêtera ensuite sans s'occuper des autres. Si nous avions tapé make dans ce cas, il serait simplement allé à la cible foo, aurait recompilé foo si nécessaire, et se serait arrêté sans passer à la cible install.

Remarquez que la cible install ne dépend en fait de rien du tout! Cela signifie que la commande sur la ligne suivante est toujours exécutée si nous essayons de reconstruire cette cible en tapant make install. Dans ce cas, il copiera foo dans le répertoire de l'utilisateur. C'est souvent utilisé par les Makefiles de logiciels, de sorte que l'application soit installée dans le bon répertoire, une fois correctement compilée.

C'est un point un peu délicat à expliquer. Si vous ne comprenez pas exactement comment make fonctionne, la meilleure chose à faire est d'écrire un programme simple comme le classique “Bonjour, le monde!”, un fichier Makefile et de faire des essais. Compilez ensuite en utilisant plus d'un fichier source, ou en ayant un fichier source qui inclut un fichier d'en-tête. La commande touch vous sera très utile - elle modifie la date d'un fichier sans que vous ayez à l'éditer.

4.3. Makefiles FreeBSD

L'écriture de Makefiles peut être assez compliquée. Heureusement, les systèmes basés sur BSD, comme FreeBSD, en fournissent de très puissants, intégrés au système. Le catalogue des logiciels portés de FreeBSD en est un excellent exemple. Voici l'essentiel d'un de leurs Makefiles typiques:


MASTER_SITES=   ftp://freefall.cdrom.com/pub/FreeBSD/LOCAL_PORTS/
DISTFILES=      scheme-microcode+dist-7.3-freebsd.tgz

.include <bsd.port.mk>
       


Si nous allons maintenant dans le répertoire associé à ce logiciel et tapons make, voici ce qui se passe:

  1. Il regarde si le code source de ce logiciel est déjà présent sur le système.

  2. S'il n'y est pas, une connexion FTP à l'URL indiquée par MASTER_SITES est établie pour télécharger le source.

  3. La somme de contrôle est calculée sur le source et comparée à celle calculée sur une version connue et validée. Cela pour s'assurer que le source n'a pas été corrompu pendant le transfert.

  4. Les modifications nécessaires pour que le code fonctionne sous FreeBSD sont appliquées - c'est ce que l'on appelle patcher.

  5. Les opérations particulières de configuration du source sont effectuées. (De nombreuses distributions de programmes Unix essayent de déterminer sur quel système elles sont compilées et de quelles fonctionnalités Unix optionnelles il dispose - c'est à ce stade du scénario d'installation de logiciels sous FreeBSD que leur sont fournies ces informations).

  6. Le code source du programme est compilé. De fait, on passe dans le répertoire où le code a été décompacté et make y est exécuté - le Makefile du programme lui-même contient les informations nécessaires à sa compilation.

  7. Nous disposons maintenant d'une version compilée du programme. Si nous le voulons, nous pouvons maintenant la tester; si nous avons confiance dans le programme, nous pouvons taper make install. Cela recopiera le programme et tous les fichiers d'environnement dont il a besoin à l'endroit adéquat; une entrée sera aussi créée dans une base de données des logiciels, de façon à ce qu'il puisse être désinstallé par la suite, si nous changeons d'avis.

Je pense que vous serez maintenant d'accord pour trouver que c'est assez impressionnant pour une simple procédure de quatre lignes!

Le secret se trouve à la dernière ligne, qui dit à make d'aller voir ce qu'il y a dans le Makefile appelé bsd.port.mk. Il est facile de rater cette ligne, mais c'est pourtant de là que vient toute la mécanique subtile. Quelqu'un a écrit un Makefile qui dit à make de faire tout ce qui a été décrit ci-dessus (plus deux ou trois autres choses dont je n'ai pas parlé, dont le traitement des erreurs qui pourraient se produire) et tout le monde peut l'utiliser en mettant simplement cette unique ligne dans son propre Makefile!

Si vous voulez jeter un oeil à ces Makefiles systèmes, ils sont dans le répertoire /usr/share/mk, mais il vaut mieux attendre d'avoir un peu d'expérience des Makefiles, parce qu'ils sont très compliqués (et si vous les regardez, ayez sous la main une bonne dose de café serré!).

4.4. Utilisation plus poussée de make

make est un outil très puissant, et peut faire beaucoup plus que l'exemple élémentaire que nous avons donné. Il y a malheureusement plusieurs versions de make, et elles sont très différentes. La meilleure façon de savoir ce qu'elles peuvent faire est certainement de lire la documentation - espérons que cette introduction vous aura fourni les bases pour le faire.

La version de make fournie avec FreeBSD est Berkeley make; elle s'accompagne d'un guide dans /usr/share/doc/psd/12.make. Pour le visualiser, tapez:

% zmore paper.ascii.gz
dans ce répertoire.

Il y a des nombreux logiciels du catalogue des logiciels portés qui utilisent GNU make, qui est très bien documenté dans les pages “info”. Si vous avez installé un de ces logiciels, GNU make sera automatiquement installé sont le nom gmake. Il est aussi disponible sous forme de logiciel porté ou précompilé autonome.

Pour visualiser les pages “info” de GNU make, il vous faut éditer le fichier dir du répertoire /usr/local/info et y ajouter une ligne pour ce programme. C'est une ligne du genre:


 * Make: (make).                 L'utilitaire GNU Make.
     
Une fois que c'est fait, vous pouvez taper info puis sélectionner make dans le menu (ou sous Emacs, taper C-h i).

Notes

[1]

Ils n'utilisent pas la variante MAKEFILE parce que les noms en majuscules servent souvent à désigner les fichiers de documentation comme README.

Ce document, ainsi que d'autres peut être téléchargé sur ftp.FreeBSD.org/pub/FreeBSD/doc/.

Pour toutes questions à propos de FreeBSD, lisez la documentation avant de contacter <questions@FreeBSD.org>.
Pour les questions sur cette documentation, contactez <doc@FreeBSD.org>.