Introduction à make avec (Xe)LaTeX

, par Maïeul

Le programme make est un outil utilisé par les développeurs. On peut également s’en servir lorsqu’on fait du (Xe)LaTeX, pour automatiser les compilations.

En effet, il est assez courant de devoir faire plusieurs compilations successives, avec différents compilateurs ((Xe)LaTeX, SplitIndex, Biber etc.). Ces compilations doivent s’effectuer dans un certain ordre, parfois se répéter (par exemple en cas de variation des ruptures de pages, pour avoir une table des matières toujours à jour) etc.

Le risque est grand d’en oublier. C’est pourquoi utiliser make pour automatiser cela est une bonne idée. Voici un petit tutoriel à ma sauce. Il vient compléter celui qui m’a appris à me servir de make ainsi qu’un autre plus généraliste.

Que les puristes me pardonnent : il y a ici quelques approximations, pour les besoins de la cause.

On consultera désormais l’article sur LaTeXmk, qui est plus efficace.

Principe

Make est un logiciel qui sert à transformer un ou plusieurs fichiers en un fichier final. Pour ce faire, il va se servir d’un fichier makefile qui indique le fichier final souhaité, les fichiers sources initiaux et l’ensemble des étapes nécessaire à la production du fichier final.

Make est installé par défaut sur la plupart des distributions Linux. Sur Mac, il faut installer les outils dévellopeurs. En revanche son installation est complexe sur Windows.

Premier pas

Soit le dossier contenant les fichiers :

  • principal.tex
  • principal.bib

Je souhaite obtenir le fichier principal.pdf en exécutant successivement :

  • xelatex principal.tex
  • biber principal
  • xelatex principal.tex.
  • xelatex principal.tex pour avoir un sommaire correspondant à la mise en page finale.

Je vais écrire les lignes suivantes dans un fichier makefile [1].

La première ligne indique que le fichier principal.pdf « dépend » de principal.tex et de principal.bib. Les lignes suivantes, qui doivent commencer par des tabulations, indique les commandes à exécuter pour produire le fichier. J’ai créé ainsi une règle de fabrication, nommée principal.pdf.

Lorsque dans mon terminal je tape (en étant situé dans le répertoire en question) : make principal.pdf, je vois les différentes compilation se succéder. À la fin je peux ouvrir mon fichier principal.pdf.
Si je retape make principal.pdf, j’obtiens :
make : `principal.pdf’ is up to date.

En effet, makefile voit que les fichiers principal.tex et principal.bib ont été modifiés plus anciennement que le fichier principal.pdf. Il en conclut que le fichier principal.pdf est à jour.

En revanche, si je m’amuse à modifier l’un de ces fichier, taper make principal.pdf me recommencerait le processus de compilation.

Généralisons

Supposons qu’à côté de mes deux fichiers, j’ai également les fichiers annexe.bib et annexe.tex et qu’à partir de cela, je souhaite obtenir un fichier annexe.pdf.

Je pourrais m’amuser à créer une règle pour annexe.pdf. Mais je pourrais très bien fabriquer un règle générique pour les fichiers .pdf

Dans la description de la règle, le %.pdf signifie « n’importe quel fichier finissant par .pdf ». Pour la suite % signifie « la partie variante du nom du fichier », autrement dit « ce qui se trouve avant le .pdf ».

Dans le contenu de la règle, le $* signifie « la partie variante du nom du fichier de destination ».

Autrement dit, j’ai produit ici l’équivalent de

Mais cela pourrait s’étendre à fichier titi.pdf dépendant de titi.tex et titi.bib.

Évidemment mes fichiers cibles peuvent aussi dépendre de fichiers situés dans d’autres dossiers. Chez moi, par exemple, ce sont les fichiers situés dans les dossiers contenu et inclure. On peut indiquer la dépendance aux dossiers en indiquant la dépendance aux fichiers qu’ils contiennent.

Une règle par défaut

Pour le moment, je suis obligé, si je veux produire les fichiers principal.pdf et annexe.pdf, de faire successivement make principal.pdf et make annexe.pdf.

On pourrait vouloir produire ces deux fichiers d’un coup. Pour ce faire je vais créer une règle spéciale nommée all, que je vais placer en tout premier. Comme cette règle doit produire ces deux fichiers, je vais lui indique qu’elle nécessite les fichiers principal.pdf et annexe.pdf. Le programme make ira chercher les règles correspondante à la production de ces fichiers.

Ma règle s’écrit dont simplement :

Seulement voilà : imaginons que pour une raison quelconque, j’ai un fichier all dans mon dossier. Dans ce cas make je risque d’avoir des conflits. Pour éviter cela, je vais indiquer une règle spéciale : .PHONY. Cette règle indique simplement que les fichiers dont elle « dépend » n’existent pas, mais qu’il s’agit en réalité de nom de règle.

J’écris donc :

Si je tape make all, le programme va bien me produire mes deux fichiers principal.pdf et annexe.pdf.

Si je met cette règle en premier, elle sera exécutée si aucune règle n’est appelée, en frappant simplement make.

Nettoyage

La compilation produit tout le temps des fichiers annexes. Il peut être utile d’avoir une règle pour les supprimer automatiquement. La plupart du temps cette règle est appelée clean. Comme c’est une règle spéciale, il faut que je l’ajoute à la règle .PHONY

Voici un exemple de règle clean

La commande rm est une commande terminal qui efface les fichiers listés. L’option -f permet de ne pas avoir de message d’erreur si on demande l’effacement de fichiers qui n’existent pas. Ici nous demandons l’effacement des fichiers se finissant [2] par .aux, .bcf, .log, .xml, .toc, .bbl, .blg, ainsi que les fichiers .aux se situant dans des dossiers.

Affichage de message finaux

Reprenons notre règle %.tex. On aimerait avoir un message, à la toute fin des compilations, nous indiquant s’il y a des références bibliographiques inconnues.

Pour ce faire nous allons lire dans le fichier .log final, pour rechercher les ligne contenant Citation xxx undefined. Nous allons pour cela utiliser un programme, généralement livré en standard sous MacOs X et Linux, appelé grep. Ce programme permet de rechercher dans des fichiers du texte, en utilisant des outils de joker, qu’on appelle « expression régulière ».

Allons y, cela nous donne

Ligne 7, nous affichons, grâce à la commande Terminal toto le message « Citations indéfinies : ». Le @ sert à indiquer à make de ne pas afficher cette ligne [3].

Ligne 8, nous exécutons la commande grep. L’option -i permet de ne pas tenir compte de la casse. Nous recherchons dans le fichier .log tout les lignes contenant Citation suivi d’une série de n’importe quel caractère [4] suivi de undefined et nous les affichons. À défaut, nous affichons « Aucune ».

Évidemment on pourrait étendre cela aux tests des étiquettes de référence croisés : pour vérifier par exemple les étiquettes en double, ou celles inexistantes.

Cela donnerait

Le fichier makefile final

Au final, tout cela donne

Notes

[1Attention, il n’y a pas d’extension  !

[2Le caractère * est un joker signifiant «  chaîne de taille indéfinie contenant n’importe quel caractère  », je renvoi à n’importe quelle introduction au terminal.

[3Pour mieux comprendre, vous pouvez essayer sans le @.