Die Programme, die Register und Literaturverzeichnisse erzeugen – makeindex, xindy, bibtex, biber –, sind keine LaTeX-Makros, sondern eigenständige ausführbare Dateien. Jedes entscheidet daher selbst, wie Argumente geschrieben werden, welchen Exit-Code es liefert und wohin sein Log geht. Und hier steht die Tatsache, die Continuous Integration stillschweigend kaputt macht: makeindex liefert Exit-Code 0, auch wenn es Einträge verworfen hat, und bibtex liefert 0, auch wenn es warnt, dass ein zitiertes Werk fehlt. Der Fehler steht nicht im Build-Status, sondern in den Dateien .ilg und .blg. Diese Seite betrachtet alle vier von der Kommandoseite her, nicht von der LaTeX-Seite; das Schreiben von Registereinträgen und der Entwurf einer Literaturdatenbank stehen anderswo.
bibtex doc gegen makeindex doc.idx – welches nimmt die Endung
Hier gibt es nichts herzuleiten, das lernt man einfach: Die Literaturprogramme nehmen keine Endung, die Registerprogramme schon. bibtex und biber erhalten den Jobnamen des Dokuments und öffnen .aux beziehungsweise .bcf selbst. Wer das verwechselt, bekommt eine erstaunlich wenig hilfreiche Meldung: bibtex doc.tex antwortet I couldn t open file name doc.tex.aux und endet mit 1, biber doc.tex antwortet ERROR - Cannot find 'doc.tex.bcf'! Beide haben lediglich eine Endung an den übergebenen Namen gehängt; dass das .tex der Fehler war, sagt keines von beiden. makeindex, upmendex und texindy nehmen dagegen die Eingabedatei selbst, man schreibt also doc.idx. Mit -o ändert man den Ausgabenamen, mit -s benennt man einen Stil.
bibtex doc # job name, no extension -> reads doc.aux, writes doc.bbl
biber doc # job name, no extension -> reads doc.bcf, writes doc.bbl
makeindex doc.idx # the file itself -> writes doc.ind and doc.ilg
upmendex -o doc.ind doc.idx
texindy -C utf8 -L german-din -o doc.ind doc.idxDie Exit-Codes und wo CI ein Scheitern übersieht
Die folgende Tabelle hält Werte fest, die auf diesem Rechner unter TeX Live 2024 tatsächlich beobachtet wurden. Sie zeigt: Die Grenze zwischen Warnung und Fehlschlag zieht jedes Programm anders. bibtex liefert 2 nur, wenn es Fehlermeldungen ausgegeben hat; ein in der .bib fehlender Zitatschlüssel gilt als Warnung, der Status bleibt also 0. makeindex liefert 1, wenn die Eingabedatei fehlt, bleibt aber bei 0, gleich wie viele Einträge es darin verwirft. Wer also nur auf den Status von latexmk oder des CI-Jobs schaut, bekommt ein grünes Häkchen auf einem Build, in dem Registereinträge verschwunden und eine Literaturangabe leer geblieben sind. Bei Registern und Literaturverzeichnissen besteht die richtige Verteidigung darin, .ilg und .blg zu prüfen statt den Exit-Code.
| Situation | Exit-Code und Log (auf TeX Live 2024 gemessen) |
|---|---|
makeindex (entries rejected) | 0. Verworfene Einträge stehen nur in der .ilg; mit -q verschwinden sie auch vom Bildschirm |
makeindex (no input file) | 1, mit Input index file nosuch.idx not found. und einer einzeiligen Aufrufhilfe |
upmendex (no input file) | 255, mit Nothing written in output file. und 1 errors, written in doc.ilg. |
bibtex (warnings only) | 0. Warning--I didn t find a database entry for "key" gilt nicht als Fehlschlag |
bibtex (error messages) | 2, bei einem Syntaxfehler in der .bib oder bei I found no database files |
biber | 0 bei bloßen Warnungen, 2, sobald ERROR - erscheint; die Bilanz steht am Ende als INFO - WARNINGS: 1 |
Die .ilg von makeindex lesen – hier stecken die verworfenen Einträge
Jeder Lauf von makeindex schreibt sowohl eine .ind – das Register, das gesetzt wird – als auch eine .ilg, ein Protokoll der Arbeit. Ein gesunder Lauf ist knapp: Scanning input file doc.idx....done (6 entries accepted, 0 rejected)., dann Sorting entries....done (19 comparisons)., dann Generating output file doc.ind....done (20 lines written, 0 warnings). Es ist kaum übertrieben zu sagen, dass nur die Zahlen in Klammern lesenswert sind. Gibt man ihm eine beschädigte .idx, sinkt die Zahl bei accepted, und die Gründe reihen sich auf: !! Input index error (file = bad.idx, line = 4): gefolgt von -- Incomplete first argument (premature LFD). Der Exit-Code bleibt dennoch 0. Schon der Abgleich der accepted-Zahl mit der Anzahl geschriebener \index-Befehle verhindert die meisten Unfälle. Die Fassung in TeX Live 2024 ist übrigens makeindex 2.17 und stellt sich als (kpathsea + Thai support) vor.
makeindex doc.idx
# This is makeindex, version 2.17 [TeX Live 2024] (kpathsea + Thai support).
# Scanning input file doc.idx....done (6 entries accepted, 0 rejected).
# Sorting entries....done (19 comparisons).
# Generating output file doc.ind....done (20 lines written, 0 warnings).
grep -c "^\\\\indexentry" doc.idx # compare this with "entries accepted"
grep "rejected" doc.ilg # the number CI should be watchingDieses unscheinbare Programm hat eine überraschende Herkunft. Geschrieben hat es Pehong Chen, doch die Danksagung seiner Manpage hält fest: „Leslie Lamport contributed significantly to the design of MakeIndex.“ Der Autor von LaTeX war also eng am Entwurf des Registerprogramms beteiligt – deshalb wirkt die Syntax von \index wie ein natürlicher Teil von LaTeX und nicht wie etwas Angeflanschtes. Die Verwendung von @ in \index{key@printed} und das Vergeben von Sortierschlüsseln für akzentuierte Wörter sind ausführlich auf der Seite über Register selbst behandelt.
Welches Registerprogramm? Dieselben vier Wörter, von allen dreien sortiert
Es gibt nur ein Kriterium: Braucht die zu erfassende Sprache eine Kollation? Legt man die vier Wörter Zeta, Ähre, Apfel und Öl unverändert in eine .idx und übergibt sie allen drei Programmen, zeigt sich der Unterschied sofort. makeindex lieferte Apfel, Zeta, Ähre, Öl – Ä und Ö haben in UTF-8 größere Bytewerte als Z und fallen daher hinter das Alphabetsende. texindy -C utf8 -L german-din und upmendex lieferten beide Ähre, Apfel, Öl, Zeta und behandelten Ä als A und Ö als O, genau wie es die deutsche DIN-Regel vorsieht. xindy (von Joachim Schrod, release 2.5.1) kommt über Sprachmodule zu diesem Ergebnis, upmendex (version 1.08) über den Kollationsalgorithmus von ICU 74.2.
| Programm | Wie es dieselben vier Wörter sortierte | Wann zu wählen |
|---|---|---|
makeindex | Apfel, Zeta, Ähre, Öl – Nicht-ASCII landet hinter Z | Nur Englisch, oder wenn Sortierschlüssel von Hand kommen |
texindy | Ähre, Apfel, Öl, Zeta – mit -L german-din | Europäische Sprachen; der Sprachname in -L genügt |
upmendex | Ähre, Apfel, Öl, Zeta – kollationiert über ICU | Japanisch und gemischte Schriften; liest weiterhin makeindex-Stile |
mendex | Rät die Eingabekodierung und meldet (guessed encoding #4: UTF-8 = utf8) | Alte pLaTeX-Bestände; für Neues besser upmendex |
Zwei praktische Hinweise. Erstens ist die von texindy geschriebene .ind anders aufgebaut als die von makeindex: Sie verwendet \lettergroup als Überschrift jeder Buchstabengruppe und schreibt die Definitionen selbst per \providecommand. Wird das im Dokument umdefiniert, kollidiert es – beim Wechsel also einmal die Ausgabe ansehen. Zweitens läuft xindy auf Common Lisp, in dieser Ausgabe CLISP 2.49.93, was den Start schwerfällig macht und bei großen Registern spürbar bremst. Ist Japanisch im Spiel, ist upmendex schneller und unkomplizierter.
Die seltsame Aufstellung am Ende einer bibtex-.blg
Öffnet man doc.blg nach einem Lauf von bibtex doc, folgt hinter den Warnungen eine ungewohnte Tabelle: if$ -- 47, while$ -- 2, swap$ -- 1, substring$ -- 6 und so weiter. Das ist eine Zählung, wie oft jede Instruktion der internen Stackmaschine von BibTeX ausgeführt wurde – in diesem Lauf 237 Aufrufe insgesamt. So etwas gibt es, weil eine .bst-Stildatei keine Konfigurationsdatei ist, sondern ein Programm für eben diese virtuelle Maschine. Weiter oben in derselben .blg steht Capacity: max_strings=200000, hash_size=200000, hash_prime=170003, Zahlen aus den Speicherverhältnissen der 1980er Jahre; sie sind die Obergrenze hinter dem Aufschrei, der bei sehr großen Literaturlisten mit Sorry---you ve exceeded BibTeX s beginnt. Der Autor ist Oren Patashnik aus Stanford, und in TeX Live 2024 steckt BibTeX 0.99d.
BibTeX hat achtbit- und Unicode-fähige Nachkommen, und TeX Live 2024 liefert sie alle mit. bibtex8 nennt sich „8-bit Big BibTeX version 0.99d-x4.02“; bibtexu ist das „UTF-8 Big BibTeX“ und ist mit ICU 74.2 gebaut. Für Japanisch gibt es pbibtex (pTeX-Familie) und upbibtex (upTeX-Familie, das sich als upBibTeX 0.99d-j0.36-u1.30 (utf8.uptex) meldet). Alle gehen auf dieselbe 0.99d-Linie zurück; nur Zeichenbehandlung und Kollation unterscheiden sich. Zwei Fehler herrschen in der Praxis vor. Eine fehlerhafte .bib erzeugt Illegal end of database file---line 14 of file broken.bib und I m skipping whatever remains of this entry mit Exit-Code 2; ein \bibliography, das auf eine nicht vorhandene Datei zeigt, erzeugt I found no database files---while reading file doc.aux.
biber – ein Log, das jede Zeile mit INFO, WARN oder ERROR kennzeichnet
biber ist ein neuerer, in Perl geschriebener Entwurf, und schon die Gestalt seines Logs ist eine andere. Es beginnt mit INFO - This is Biber 2.19 und meldet dann Zeile für Zeile die gelesene .bcf, die Anzahl gefundener Zitatschlüssel, die angewandte Locale und die geschriebene .bbl – jede Zeile mit INFO - gekennzeichnet. Geht etwas schief, wechselt die Kennzeichnung, etwa WARN - I didn t find a database entry for 'missingkey' (section 0), und am Ende folgt eine Bilanz: INFO - WARNINGS: 1. Diese Maschinenlesbarkeit ist der größte praktische Unterschied zu bibtex: Eine CI-Prüfung lässt sich schreiben, indem man WARN - und ERROR - mit grep zählt. Der häufigste Unfall ist ein falsch geschriebener Eingabename; biber doc.tex gibt ERROR - Cannot find 'doc.tex.bcf'! aus und endet mit 2. Zu beachten ist außerdem, dass biber und bibtex beide eine Datei mit der Endung .blg schreiben – wer beides probiert hat, liest die erste Zeile, um sicher zu sein, welche vorliegt.
biber doc
# INFO - This is Biber 2.19
# INFO - Found 2 citekeys in bib section 0
# INFO - Output to doc.bbl
# WARN - I didn t find a database entry for 'missingkey' (section 0)
# INFO - WARNINGS: 1
# a CI check that the exit code will not give you
grep -c "^WARN -\|^ERROR -" doc.blg
grep "rejected" doc.ilgDie Ausführungsreihenfolge und wer die Durchläufe für Sie zählt
Die Reihenfolge lautet: setzen, dann Register und Literatur, dann setzen, dann noch einmal setzen. Im ersten Durchlauf schreibt LaTeX .idx und .aux – unter biblatex .bcf; darüber laufen dann diese Programme und erzeugen .ind und .bbl; ein weiterer Satzlauf zieht sie herein; und wenn sich Nummern verschoben haben, folgt noch einer. Unangenehm ist, dass die Zahl der Durchläufe nicht feststeht – genau dafür gibt es Build-Werkzeuge wie latexmk. Von Hand zu tippen lohnt nur, wenn man eingrenzen will, welche Stufe gescheitert ist – und auch dafür gibt es eine feste Reihenfolge. Zuerst prüfen, ob .idx beziehungsweise .bcf überhaupt entstanden ist: wenn nicht, liegt das Problem auf der LaTeX-Seite. Dann .ilg und .blg lesen: wenn vorhanden, liegt das Problem im Programm. Zuletzt noch einmal setzen und sehen, ob .ind und .bbl wirklich in den Text gelangt sind. Diese drei Schritte grenzen die Ursache auf fast einen Punkt ein.
# the classic Japanese sequence, written out
uplatex paper # writes paper.aux and paper.idx
upbibtex paper # reads paper.aux -> paper.bbl
upmendex paper.idx # reads paper.idx -> paper.ind
uplatex paper # pulls both in
uplatex paper # settles the numbering
# and the same thing delegated
latexmk paper.tex