„Rerun to get cross-references right.“ LaTeX gehört zu den wenigen Satzsystemen, bei denen ein einziger Durchlauf des Compilers noch nicht das richtige Ergebnis liefert. Querverweise, Inhaltsverzeichnis und Zitate werden im ersten Durchlauf nur in Dateien geschrieben; deshalb übernimmt ein automatisierter Build mit einem Werkzeug wie latexmk die Wiederholungen, bis sich die Ausgabe nicht mehr ändert. Diese Seite beginnt bei der Frage, warum überhaupt mehrere Läufe nötig sind, und geht dann latexmk -pdf durch, den Modus -pvc, der bei jedem Speichern neu baut, die Aufräumoptionen -c und -C, die Konfigurationsdatei latexmkrc sowie die Alternativen arara, llmk und make.
Warum LaTeX mehrere Kompilierläufe braucht
Die Antwort ist einfach: LaTeX liest ein Dokument genau einmal, von vorn nach hinten. Wenn auf Seite eins das Inhaltsverzeichnis gesetzt wird, steht noch nicht fest, auf welcher Seite Abschnitt 7 landet. Also schreibt LaTeX alles, was es unterwegs erfährt – Abschnitts- und Seitennummer jeder Marke, die Verzeichniszeilen, die Zitierschlüssel –, in Hilfsdateien wie .aux, .toc, .lof und .lot und liest sie zu Beginn des nächsten Laufs wieder ein. Die Ausgabe entsteht damit immer aus dem, was der vorherige Lauf herausgefunden hat. Genau deshalb hat das erste PDF ein leeres Inhaltsverzeichnis und zeigt ?? an den Stellen der Verweise.
Darin steckt ein hübscher Kniff: LaTeX zählt nicht, wie viele Durchläufe noch fehlen. Bei \end{document} vergleicht es den soeben berechneten Wert jeder Marke mit dem Wert, den es aus der .aux-Datei des vorherigen Laufs gelesen hat, Stück für Stück; weicht auch nur einer ab, erscheint LaTeX Warning: Label(s) may have changed. Rerun to get cross-references right. Umgekehrt heißt das: Verschwindet die Warnung, hat sich die .aux-Datei nicht mehr geändert – das Dokument hat einen Fixpunkt erreicht. Ob ein Dokument fertig ist, entscheidet nicht das Aussehen der Seiten, sondern die Übereinstimmung dieser Hilfsdateien.
% 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.Eine Bibliografie verlängert den Hin- und Rückweg zusätzlich. Die von \cite angeforderten Schlüssel landen im ersten Lauf in der .aux-Datei; bibtex oder biber liest sie und erzeugt eine .bbl; der zweite Lauf bindet die .bbl ein; ein dritter korrigiert Verweise, deren Nummern sich verschoben haben. Das ist die ganze Geschichte hinter der bekannten Formel latex → bibtex → latex → latex. Ein Index schiebt zusätzlich makeindex in dieselbe Kette. Von Hand bedeutet das, jedes Mal aufs Neue zu beurteilen, wie weit zurückgegangen werden muss.
latexmk: ein Befehl, der die ganze Schleife übernimmt
Zu tippen ist eine einzige Zeile: latexmk -pdf document.tex. Danach beobachtet latexmk die Änderungen der .aux-Datei, ruft pdflatex so oft auf wie nötig, schiebt bibtex/biber und makeindex in der richtigen Reihenfolge ein und hört auf, sobald die Warnungen verschwunden sind. Das Werkzeug hat eine ungewöhnliche Herkunft: Angefangen hat es als kleines Skript namens go von David J. Musliner. Evan McLean baute daraus latexmk, und seither pflegt John Collins, Physiker an der Penn State University, das Perl-Programm – unter TeX Live 2024 antwortet latexmk -v mit „Latexmk, John Collins, 31 Jan. 2024. Version 4.83.“ Da es sowohl bei TeX Live als auch bei MiKTeX dabei ist, muss in der Regel nichts nachinstalliert werden.
$ 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-dateDas -recorder in dieser Ausgabe fügt latexmk selbst hinzu. Mit dieser Option schreibt die TeX-Engine eine .fls-Datei mit allen Dateien, die der Lauf gelesen und geschrieben hat; latexmk gleicht sie mit dem Log ab, ermittelt daraus die Abhängigkeiten und hält den Zustand jeder Datei in einer Datenbank namens .fdb_latexmk fest. Entscheidend ist das Kriterium: latexmk vergleicht Prüfsummen der Dateiinhalte, nicht Änderungszeiten. Das Handbuch nennt den Grund unmissverständlich. Eine während eines LaTeX-Laufs geschriebene Datei ist stets jünger als die zuvor eingelesene, wirkt also nach Zeitstempeln dauerhaft veraltet. Diese zirkuläre Abhängigkeit sei LaTeX eigen, heißt es dort, und latexmk sei genau dafür geschrieben worden, sie zu überwinden. Auch eine Reißleine gibt es: Hat sich das Dokument nach $max_repeat Läufen – standardmäßig fünf – nicht stabilisiert, nimmt latexmk eine Endlosschleife an und bricht ab.
-pdf, -lualatex, -xelatex: die Engine wählen
-pdf wählt pdflatex, -lualatex wählt lualatex, -xelatex wählt xelatex. Ohne Angabe verhält sich latexmk wie seine frühesten Versionen und erzeugt ein .dvi; wer ein PDF will, muss also eine dieser Optionen setzen. Ein Detail lohnt hier die Aufmerksamkeit: Selbst mit -xelatex lässt latexmk xelatex das PDF nicht direkt schreiben. Es erzeugt zunächst eine Zwischendatei .xdv, erledigt darauf alle Wiederholungsläufe und ruft erst danach einmal xdvipdfmx auf. Bei großen .png-Grafiken ist die PDF-Erzeugung langsam – so müssen die Bilder nicht bei jedem Durchlauf neu eingebettet werden. -lualatex ist die Kurzform von -pdflua -dvi- -ps-, -xelatex die von -pdfxe -dvi- -ps-. Für einen Weg über DVI, etwa das japanische Gespann upLaTeX + dvipdfmx, dient -pdfdvi.
| Option | Wirkung | Einsatz |
|---|---|---|
-pdf | erzeugt das PDF mit pdflatex | Standardfall für Dokumente in lateinischer Schrift |
-lualatex | erzeugt das PDF mit lualatex (wie -pdflua -dvi- -ps-) | OpenType-Schriften oder Erweiterungen in Lua |
-xelatex | lässt xelatex ein .xdv erzeugen und ruft am Ende xdvipdfmx auf | wenn Systemschriften direkt verwendet werden |
-pdfdvi | erzeugt zuerst ein .dvi und wandelt es in PDF um | DVI-Wege wie upLaTeX + dvipdfmx |
-pvc | überwacht die Quellen und baut bei jeder Änderung neu | beim Schreiben, um nach jedem Speichern das Ergebnis zu sehen |
-pvctimeout | beendet -pvc nach einer Phase der Untätigkeit (standardmäßig 30 Minuten) | wenn die Überwachung nicht unbeaufsichtigt weiterlaufen soll |
-c | entfernt die neu erzeugbaren Zwischendateien, behält das PDF | zum Aufräumen des Arbeitsverzeichnisses |
-C | macht -c und löscht zusätzlich .dvi, .ps und .pdf | Nachweis eines Clean Builds; Vorbereitung einer Auslieferung |
-gg | räumt wie -C auf und baut anschließend normal | Neubau von Grund auf in einem Befehl |
-f | setzt die Verarbeitung trotz Fehlern fort | wenn die gesamte Log-Ausgabe auf einmal gebraucht wird |
-silent | dämpft die Ausgabe der Engine (wie -quiet) | um CI-Logs lesbar zu halten |
-r | liest zusätzlich eine angegebene Konfigurationsdatei | wenn einmalig über einen anderen Weg gebaut wird |
Bei jedem Speichern neu bauen – latexmk -pvc
-pvc steht für „preview continuously“: latexmk bleibt mit geöffnetem Betrachter im Speicher und lässt die gesamte Schleife erneut laufen, sobald sich irgendeine Quelldatei ändert. Überwacht wird nicht nur die Haupt-.tex. Die aus der .fls gewonnene Abhängigkeitsliste wird zur Beobachtungsliste, also gehören auch mit \input/\include eingebundene Kapiteldateien, eingebettete Grafiken und die .bib-Datei dazu. Das Gefühl entspricht einem Dev-Server für ein Dokument. Ein paar Eigenheiten kommen mit: -pvc funktioniert nur mit einer einzigen Datei und verträgt sich nicht mit -p und -pv. Außerdem schaltet der Modus den Force-Modus -f ab; wer beides braucht, schreibt sie in der Reihenfolge -pvc -f. Von sich aus endet der Lauf nicht; erst -pvctimeout fügt eine Zeitsperre bei Untätigkeit hinzu, deren Dauer standardmäßig 30 Minuten beträgt (-pvctimeoutmins= ändert sie, -pvctimeout- schaltet sie wieder ab). Auch der Betrachter zählt: Das Handbuch warnt ausdrücklich davor, unter MS-Windows acroread zu verwenden, weil es die PDF-Datei sperrt und neue Versionen nicht geschrieben werden können.
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 lualatexDie Schaltfläche „beim Speichern bauen“ in einem Editor ist meist latexmk unter der Haube. LaTeX Workshop für VS Code, TeXstudio, TeXShop, AUCTeX in Emacs, Overleaf – die Namen unterscheiden sich, ausgeführt wird entweder derselbe Befehl oder eine eingebaute Umsetzung derselben Idee. Wer -pvc auf der Kommandozeile kennt, hat deshalb einen Rückzugsort: Spinnt der Editor, klärt der nackte Befehl, ob das Dokument oder die Konfiguration schuld ist. Scheitert nur der Build im Editor, während latexmk durchläuft, liegt der Verdacht auf den Editor-Einstellungen, nicht auf dem Dokument.
latexmk -c und -C: erzeugte Dateien aufräumen
Der Unterschied besteht in einem Punkt: ob das PDF erhalten bleibt. -c entfernt die neu erzeugbaren Dateien – .aux, .log, .toc, .fls, .fdb_latexmk und dergleichen –, behält aber .dvi, .ps und .pdf. -C löscht diese Ausgaben ebenfalls. Wer aufräumen und in einem Zug neu bauen will, nimmt -gg. Praktisch wichtig ist das, weil eine veraltete .aux Unfälle verdeckt. Ein paar Abschnitte umgestellt, ein \label gelöscht – und das PDF auf dem eigenen Rechner sieht weiterhin plausibel aus, weil die alten Werte noch herumliegen, während eine Mitautorin mit frisch geklontem Repository oder die CI einen kaputten Build bekommt. latexmk -C auszuführen und danach latexmk -pdf durchlaufen zu sehen, ist vor der Abgabe der Beweis, dass sich das Dokument tatsächlich allein aus seinen Quellen bauen lässt.
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 scratchDen Build in eine latexmkrc-Datei schreiben
Liegt neben dem Dokument eine Datei namens latexmkrc oder .latexmkrc, nimmt jeder, der in diesem Verzeichnis latexmk eintippt, denselben Weg. Beim Start liest latexmk der Reihe nach: die systemweite Datei, dann $HOME/.latexmkrc (oder $XDG_CONFIG_HOME/latexmk/latexmkrc), dann latexmkrc oder .latexmkrc im aktuellen Verzeichnis, dann alles, was mit -r angegeben wurde. Später Gelesenes gewinnt, die Projekteinstellungen überschreiben also persönliche Vorlieben. Der Inhalt ist Perl-Code, # leitet einen Kommentar ein, und meist genügen ein paar Zuweisungen an Variablen. Bei gemeinsamer Arbeit sorgt es für den geringsten Streit, diese Datei ins Repository zu legen und sie als Abmachung zu behandeln: „So wird dieses Dokument gebaut.“
# 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';Alternativen zu latexmk: arara, llmk, make
Die Trennlinie verläuft an einer Frage: Wer legt die Schrittfolge fest? latexmk erschließt sie aus Logs und Abhängigkeiten. arara erschließt gar nichts. Es liest im Dokument notierte Direktiven – eine Kommentarzeile wie % arara: pdflatex – und führt genau das aus, was dort steht, in der dort angegebenen Reihenfolge. Wie der CTAN-Eintrag formuliert, bestimmt arara seine Aktionen aus Metadaten im Quelltext statt aus indirekten Quellen wie einer Logdatei-Analyse. Entwickelt wird es von Island of TeX um Paulo Roberto Massa Cereda; zum Ausführen ist Java nötig. llmk (in TeX Live als light-latex-make paketiert, geschrieben von Takuto Asakura) ist noch deklarativer: Der Ablauf steht in llmk.toml oder in einem TOML-Feld der Quelle, und es läuft allein mit texlua – der Entwurf stellt gleiches Verhalten in jeder Umgebung an die erste Stelle.
% arara directives: the document itself states the workflow
% arara: pdflatex
% arara: biber
% arara: pdflatex
% arara: pdflatex
\documentclass{article}# llmk.toml -- next to the document; "source" is required in this file
source = "doc.tex"
latex = "lualatex"
bibtex = "biber"
sequence = ["latex", "bibtex", "latex", "latex"]Und schlichtes make? Ein Makefile kann LaTeX durchaus steuern, doch make entscheidet nach Änderungszeit. Da die .aux-Datei bei jedem Lauf neu geschrieben wird, liegt sie nach Zeitstempeln immer nach der eingelesenen Datei – und gilt damit dauerhaft als veraltet. Genau an diesem Punkt hält das Handbuch von latexmk fest, dass die zirkuläre Abhängigkeit LaTeX eigen ist und latexmk geschrieben wurde, um sie zu überwinden. Wer dennoch make einsetzt, fährt am besten damit, eine Kopie der .aux aufzubewahren und zu vergleichen – oder aus dem Makefile-Ziel einfach latexmk aufzurufen. Tatsächlich laufen sehr viele Projekt-Makefiles auf eine einzige Zeile hinaus: latexmk -pdf $<.
| Werkzeug | Wie die Schritte bestimmt werden | Wo die Konfiguration liegt | Voraussetzung |
|---|---|---|---|
latexmk | abgeleitet aus Log, .fls und Prüfsummen der Inhalte | latexmkrc / .latexmkrc (Perl) | Perl; bei TeX Live und MiKTeX dabei |
arara | genau so ausgeführt, wie es die Direktiven im Dokument sagen | % arara:-Kommentare im Dokument | Java |
llmk | folgt der in TOML deklarierten sequence | llmk.toml oder ein TOML-Feld in der Quelle | nur texlua |
make | nach Änderungszeiten entschieden; anfällig für den .aux-Zyklus | Makefile | make; fast überall bereits vorhanden |
Welcher Befehl beim Schreiben, Teilen und Abgeben
Die Wahl lässt sich auf drei Zeitpunkte bringen. Während des Schreibens mit -pvc beobachten und das Ergebnis bei jedem Speichern ansehen. Bevor das Dokument weitergegeben wird, einmal schlicht latexmk laufen lassen. Kurz vor der Abgabe mit latexmk -C alles löschen und neu bauen. Gerade der letzte Schritt als Gewohnheit verhindert den klassischen Unfall, kurz vor Fristende zu bemerken, dass das Dokument nur auf dem eigenen Rechner kompiliert. Und sind die Einstellungen erst in latexmkrc festgehalten und eingecheckt, nehmen CI-Server wie Mitautoren denselben Weg – die Diskussion „bei mir läuft es doch“ kommt dann gar nicht erst auf.
- Beim Schreiben →
latexmk -pdf -pvc doc.tex: baut bei jedem Speichern automatisch neu;-pvctimeoutergänzen, wenn es nicht unbeaufsichtigt weiterlaufen soll. - Engine festlegen →
$pdf_modeund Verwandte inlatexmkrcsetzen und die Datei einchecken, damit alle sie teilen. - Vor der Übergabe an Mitautoren → einmal schlicht
latexmk -pdflaufen lassen und prüfen, dass keinLaTeX Warning: Label(s) may have changed.übrig bleibt. - Kurz vor Abgabe oder Veröffentlichung → mit
latexmk -Calles löschen, dann clean bauen;latexmk -gg -pdf doc.texerledigt beides auf einmal. - Build auf Server oder in CI → siehe die CI-Seite;
-silenthält die Logs lesbar.