Compilations automatisées

« Rerun to get cross-references right. » LaTeX fait partie des rares systèmes de composition où un seul passage du compilateur ne suffit pas à obtenir le bon résultat. Les références croisées, la table des matières et les citations sont seulement écrites dans des fichiers lors du premier passage ; c'est pourquoi un outil de build automatisé comme latexmk effectue les allers-retours à votre place jusqu'à ce que la sortie se stabilise. Cette page part de la raison pour laquelle plusieurs compilations sont nécessaires, puis parcourt latexmk -pdf, le mode -pvc qui reconstruit à chaque enregistrement, les nettoyages -c et -C, le fichier de configuration latexmkrc, ainsi que les solutions de rechange : arara, llmk et make.

Pourquoi LaTeX exige plusieurs compilations

La réponse est simple : LaTeX ne lit le document qu'une seule fois, du début à la fin. Au moment où il compose la table des matières en page un, il ignore encore sur quelle page tombera la section 7. Il consigne donc ce qu'il apprend en chemin — numéro de section et de page de chaque étiquette, lignes du sommaire, clés de citation — dans des fichiers auxiliaires comme .aux, .toc, .lof et .lot, puis les relit au début du passage suivant. La sortie est ainsi toujours composée à partir de ce qu'a découvert le passage précédent. C'est précisément pourquoi le premier PDF affiche une table des matières vide et des ?? à la place des renvois.

Un mécanisme astucieux se cache ici : LaTeX ne compte pas les passages restants. À \end{document}, il compare la valeur qu'il vient de calculer pour chaque étiquette à celle qu'il a lue dans le .aux du passage précédent, une par une ; si une seule diffère, il affiche LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right. Autrement dit, la disparition de cet avertissement signale que le fichier .aux a cessé de changer, c'est-à-dire que le document a atteint un point fixe. Ce n'est pas l'aspect des pages qui décide qu'un document est terminé, mais l'accord de ces fichiers auxiliaires.

text
% doc.aux -- what one run leaves behind for the next one to read
\@writefile{toc}{\contentsline {section}{\numberline {1}One}{1}{}}
\newlabel{sec:one}{{1}{1}{}{}{}}

% doc.log -- the first run, before the .aux settles
LaTeX Warning: Reference `sec:two' on page 1 undefined on input line 5.
LaTeX Warning: There were undefined references.
LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right.

Ajouter une bibliographie allonge encore l'aller-retour. Les clés demandées par \cite sont consignées dans le .aux au premier passage ; bibtex ou biber lit ce fichier et produit un .bbl ; le deuxième passage intègre le .bbl ; un troisième corrige les renvois dont les numéros ont bougé. Voilà toute l'histoire derrière la formule bien connue latex → bibtex → latex → latex. Un index insère en plus makeindex dans la même chaîne. Tant que l'on procède à la main, il faut réévaluer chaque fois jusqu'où revenir en arrière.

latexmk : une seule commande pour toute la boucle

Une seule ligne à taper : latexmk -pdf document.tex. Ensuite, latexmk surveille les changements du fichier .aux, lance pdflatex autant de fois qu'il le faut, appelle bibtex/biber et makeindex dans le bon ordre en cours de route et s'arrête dès que les avertissements ont disparu. L'outil a une généalogie singulière : il est né d'un petit script nommé go, écrit par David J. Musliner. Evan McLean l'a transformé en latexmk, et depuis John Collins, physicien à Penn State University, en assure la maintenance en Perl — sous TeX Live 2024, latexmk -v répond « Latexmk, John Collins, 31 Jan. 2024. Version 4.83. ». Il est livré avec TeX Live comme avec MiKTeX : il n'y a normalement rien à installer.

terminal
$ latexmk -pdf doc.tex
Latexmk: applying rule 'pdflatex'...
Run number 1 of rule 'pdflatex'
Running 'pdflatex  -recorder  "doc.tex"'
Latexmk: References changed.
Latexmk: applying rule 'pdflatex'...
Run number 2 of rule 'pdflatex'
Running 'pdflatex  -recorder  "doc.tex"'
Latexmk: All targets (doc.pdf) are up-to-date

Le -recorder visible dans cette sortie est ajouté par latexmk lui-même. Avec cette option, le moteur TeX écrit un fichier .fls énumérant tous les fichiers lus et écrits pendant l'exécution ; latexmk le recoupe avec le journal pour établir les dépendances et conserve l'état de chaque fichier dans une base nommée .fdb_latexmk. L'essentiel tient au critère : latexmk compare des sommes de contrôle du contenu, et non des dates de modification. Son manuel en donne clairement la raison. Un fichier écrit pendant une exécution de LaTeX est toujours postérieur à celui qui a été lu juste avant, si bien qu'aux seules dates il paraît perpétuellement périmé. Cette dépendance circulaire, note le manuel, est propre à LaTeX, et latexmk a été programmé pour la surmonter. Il existe aussi un garde-fou : si le document ne s'est pas stabilisé après $max_repeat exécutions — cinq par défaut — latexmk conclut à une boucle infinie et s'arrête.

-pdf, -lualatex, -xelatex : choisir le moteur

-pdf choisit pdflatex, -lualatex choisit lualatex et -xelatex choisit xelatex. Sans option, latexmk continue de faire ce que faisaient ses toutes premières versions et produit un .dvi : dès qu'un PDF est attendu, l'une de ces options est donc indispensable. Un détail mérite d'être connu : même avec -xelatex, latexmk ne laisse pas xelatex écrire le PDF directement. Il fabrique d'abord un fichier intermédiaire .xdv, y effectue toutes les relances, puis appelle une seule fois xdvipdfmx à la fin. Avec de gros graphiques .png, l'étape PDF est lente ; on évite ainsi de réincorporer les images à chaque passage. -lualatex abrège -pdflua -dvi- -ps- et -xelatex abrège -pdfxe -dvi- -ps-. Pour une route passant par le DVI, comme le couple japonais upLaTeX + dvipdfmx, on choisit -pdfdvi.

OptionEffetQuand l'utiliser
-pdfproduit le PDF avec pdflatexcas standard des documents en alphabet latin
-lualatexproduit le PDF avec lualatex (équivaut à -pdflua -dvi- -ps-)polices OpenType ou extensions écrites en Lua
-xelatexfait produire un .xdv par xelatex, puis appelle xdvipdfmxlorsque les polices du système sont utilisées telles quelles
-pdfdvifabrique d'abord un .dvi puis le convertit en PDFroutes passant par le DVI comme upLaTeX + dvipdfmx
-pvcsurveille les sources et reconstruit à chaque changementpendant la rédaction, pour voir le résultat à chaque enregistrement
-pvctimeoutmet fin à -pvc après une période d'inactivité (30 minutes par défaut)pour ne pas laisser le processus tourner sans personne devant
-csupprime les fichiers intermédiaires régénérables, garde le PDFpour ranger un répertoire de travail
-Cfait -c et supprime en plus les .dvi, .ps et .pdfprouver une compilation propre ; préparer une diffusion
-ggnettoie comme -C puis effectue une compilation normalereconstruction complète en une seule commande
-fpoursuit le traitement malgré les erreurspour obtenir toute la sortie du journal d'un coup
-silentréduit la sortie du moteur (identique à -quiet)pour garder des journaux de CI lisibles
-rlit en plus un fichier de configuration désignépour compiler ponctuellement par une autre route

Reconstruire à chaque enregistrement — latexmk -pvc

-pvc signifie « preview continuously » : latexmk reste résident, un visualiseur ouvert, et relance toute la boucle dès qu'un fichier source change. Il ne surveille pas seulement le .tex principal. La liste de dépendances construite à partir du .fls devient la liste de surveillance : les fichiers de chapitre inclus par \input/\include, les images incorporées et le fichier .bib en font partie. La sensation est celle d'un serveur de développement pour un document. Quelques particularités l'accompagnent : -pvc ne fonctionne qu'avec un seul fichier et est incompatible avec -p et -pv. Ce mode désactive aussi le mode forcé -f ; pour vraiment combiner les deux, il faut les écrire dans l'ordre -pvc -f. De lui-même, il ne s'arrête jamais ; c'est -pvctimeout qui ajoute un délai d'inactivité, fixé par défaut à 30 minutes (-pvctimeoutmins= le modifie, -pvctimeout- le supprime de nouveau). Le visualiseur compte également : le manuel avertit explicitement qu'acroread sous MS-Windows verrouille le fichier PDF et empêche l'écriture de nouvelles versions ; c'est donc un mauvais choix en aperçu continu.

terminal
latexmk -pdf -pvc doc.tex                 # watch the sources, rebuild on every save
latexmk -pdf -pvc -pvctimeout doc.tex     # same, but give up after 30 idle minutes
latexmk -lualatex -pvc doc.tex            # the same loop, driven by lualatex

Le bouton « compiler à l'enregistrement » d'un éditeur, c'est en général latexmk en dessous. LaTeX Workshop pour VS Code, TeXstudio, TeXShop, AUCTeX sous Emacs, Overleaf : les noms diffèrent, mais ce qui s'exécute est soit la même commande, soit une implémentation interne de la même idée. Connaître -pvc en ligne de commande offre donc un repli : quand l'éditeur se comporte mal, la commande nue permet de dire si le fautif est le document ou la configuration. Si seule la compilation de l'éditeur échoue alors que latexmk passe, le suspect est le réglage de l'éditeur, pas le document.

latexmk -c et -C : nettoyer les fichiers générés

La différence tient en un point : le PDF est-il conservé ou non. -c supprime les fichiers régénérables — .aux, .log, .toc, .fls, .fdb_latexmk et consorts — mais garde les .dvi, .ps et .pdf. -C supprime aussi ces sorties. Pour nettoyer puis reconstruire en une seule opération, il existe -gg. L'enjeu est concret : un .aux périmé masque les accidents. Réordonnez quelques sections, supprimez un \label, et le PDF de votre machine continue d'avoir l'air correct parce que les anciennes valeurs traînent encore — tandis qu'un coauteur qui vient de cloner le dépôt, ou la CI, obtient une compilation cassée. Lancer latexmk -C puis voir latexmk -pdf aboutir avant de rendre, c'est la preuve que le document se construit réellement à partir de ses seules sources.

terminal
latexmk -c                  # remove aux, log, toc, fls, fdb_latexmk ... keep the PDF
latexmk -C                  # remove all of that plus the dvi / ps / pdf output
latexmk -gg -pdf doc.tex    # clean first, then build again from scratch

Inscrire le build dans un fichier latexmkrc

Placer à côté du document un fichier nommé latexmkrc ou .latexmkrc suffit pour que quiconque tape latexmk dans ce répertoire emprunte le même chemin. Au démarrage, latexmk lit dans l'ordre : le fichier système, puis le $HOME/.latexmkrc de l'utilisateur (ou $XDG_CONFIG_HOME/latexmk/latexmkrc), puis latexmkrc ou .latexmkrc du répertoire courant, puis ce qui a été indiqué par -r. Les fichiers lus en dernier l'emportent : les réglages du projet écrasent donc les préférences individuelles. Le contenu est du Perl, # introduit un commentaire, et quelques affectations de variables suffisent le plus souvent. En travail collaboratif, verser ce fichier au dépôt et en faire la convention — « ce document se construit ainsi » — est ce qui évite le plus de discussions.

perl
# latexmkrc -- lives next to the document and is committed with it

$pdf_mode = 4;           # 4 = build the PDF with lualatex
$max_repeat = 7;         # allow a couple of extra passes on a long document

# Alternative route: upLaTeX -> DVI -> dvipdfmx
# $latex    = 'uplatex -interaction=nonstopmode -halt-on-error %O %S';
# $dvipdf   = 'dvipdfmx %O -o %D %S';
# $pdf_mode = 3;         # 3 = make the PDF from the DVI file

# Extra extensions that -c and -C should remove as well.
$clean_ext = 'synctex.gz run.xml bcf';

Les alternatives à latexmk : arara, llmk, make

La ligne de partage tient à une seule question : qui décide de l'enchaînement des étapes. latexmk le déduit des journaux et des dépendances. arara, lui, ne déduit rien. Il lit des directives écrites dans le document — une ligne de commentaire telle que % arara: pdflatex — et exécute exactement ce qui est écrit, dans l'ordre où c'est écrit. Comme le formule sa notice CTAN, arara détermine ses actions à partir de métadonnées présentes dans le code source, et non de ressources indirectes comme l'analyse du fichier journal. Il est développé par Island of TeX autour de Paulo Roberto Massa Cereda et nécessite Java. llmk (empaqueté dans TeX Live sous le nom light-latex-make, écrit par Takuto Asakura) va plus loin dans le déclaratif : le déroulé s'écrit dans llmk.toml ou dans un champ TOML de la source, et le programme ne demande que texlua — la conception privilégie un comportement identique dans tous les environnements.

latex
% arara directives: the document itself states the workflow
% arara: pdflatex
% arara: biber
% arara: pdflatex
% arara: pdflatex
\documentclass{article}
toml
# llmk.toml -- next to the document; "source" is required in this file
source = "doc.tex"
latex = "lualatex"
bibtex = "biber"
sequence = ["latex", "bibtex", "latex", "latex"]

Et make tout simple ? Un Makefile peut bien sûr piloter LaTeX, mais make tranche d'après la date de modification. Comme le fichier .aux est réécrit à chaque exécution, les dates le placent toujours après celui qui a été lu — et donc perpétuellement périmé. C'est exactement sur ce point que le manuel de latexmk affirme que cette dépendance circulaire est propre à LaTeX et que latexmk a été écrit pour la surmonter. Si l'on tient malgré tout à make, les solutions praticables consistent à conserver une copie du .aux pour la comparer, ou tout simplement à appeler latexmk depuis la cible du Makefile. Dans les faits, quantité de Makefiles de projets se résument à une ligne : latexmk -pdf $<.

OutilComment les étapes sont décidéesOù se trouve la configurationPrérequis
latexmkdéduites du journal, du .fls et des sommes de contrôlelatexmkrc / .latexmkrc (Perl)Perl ; livré avec TeX Live et MiKTeX
araraexécutées exactement comme l'indiquent les directives du documentcommentaires % arara: dans le documentJava
llmksuit la sequence déclarée en TOMLllmk.toml ou un champ TOML dans la sourcetexlua seulement
makedécidées par les dates de modification ; faibles face au cycle du .auxMakefilemake ; déjà présent presque partout

Quelle commande pendant la rédaction, le partage et la remise

Le choix se ramène à trois moments. Pendant la rédaction, surveiller avec -pvc et regarder le résultat à chaque enregistrement. Avant de transmettre le document, lancer une fois latexmk nu. Juste avant la remise, tout effacer avec latexmk -C et reconstruire. C'est surtout cette dernière étape, prise comme habitude, qui évite l'accident classique : découvrir à la date limite que le document ne compile que sur sa propre machine. Et dès lors que les réglages sont figés dans latexmkrc et versés au dépôt, le serveur de CI et chaque coauteur suivent le même chemin ; la discussion « chez moi, ça marche » ne se pose plus.

  • Pendant la rédactionlatexmk -pdf -pvc doc.tex : reconstruction automatique à chaque enregistrement ; ajouter -pvctimeout pour qu'il ne tourne pas indéfiniment sans personne.
  • Figer le moteur → définir $pdf_mode et consorts dans latexmkrc, et verser le fichier au dépôt pour que tous le partagent.
  • Avant de transmettre à un coauteur → lancer une fois latexmk -pdf nu et vérifier qu'aucun LaTeX Warning: Label(s) may have changed. ne subsiste.
  • Juste avant la remise ou la diffusionlatexmk -C pour tout effacer, puis une compilation propre ; latexmk -gg -pdf doc.tex fait les deux d'un coup.
  • Build sur un serveur ou en CI → voir la page CI ; -silent garde les journaux lisibles.