Comandos de índices y bibliografía

Los programas que construyen índices y bibliografías —makeindex, xindy, bibtex, biber— no son macros de LaTeX sino ejecutables independientes. Cada uno decide por su cuenta cómo se escriben los argumentos, qué código de salida devuelve y dónde deja su registro. Y aquí está el hecho que rompe la integración continua sin hacer ruido: makeindex devuelve código de salida 0 aunque haya tirado entradas, y bibtex devuelve 0 aunque advierta de que falta una obra citada. El fallo no queda en el estado de la compilación sino en los archivos .ilg y .blg. Esta página mira los cuatro desde el lado de la línea de órdenes, no desde el lado de LaTeX; escribir entradas de índice y diseñar una base bibliográfica se tratan en otro sitio.

bibtex doc frente a makeindex doc.idx: cuál lleva la extensión

Aquí no hay nada que deducir; simplemente se aprende: los programas de bibliografía no llevan extensión y los de índice sí. bibtex y biber reciben el nombre de trabajo del documento y abren .aux o .bcf por su cuenta. Equivocarse en eso da un mensaje sorprendentemente poco útil: bibtex doc.tex responde I couldn t open file name doc.tex.aux y sale con 1, mientras que biber doc.tex responde ERROR - Cannot find 'doc.tex.bcf'! Ambos se han limitado a añadir una extensión al nombre dado; ninguno te dirá que el error era el .tex. makeindex, upmendex y texindy, en cambio, toman el archivo de entrada en sí, así que se escribe doc.idx. Con -o se cambia el nombre de salida y con -s se indica un estilo.

terminal
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.idx

Los códigos de salida y dónde la CI deja pasar un fallo

La tabla siguiente recoge valores observados de verdad en esta máquina con TeX Live 2024. Lo que muestra es que la frontera entre advertencia y fallo la traza cada programa de distinta manera. bibtex devuelve 2 solo cuando ha imprimido mensajes de error; una clave de cita ausente del .bib cuenta como advertencia, así que el estado es 0. makeindex devuelve 1 cuando falta el archivo de entrada, pero se queda en 0 por muchas entradas que descarte dentro de él. Vigilando solo el estado de latexmk o de tu trabajo de CI puedes, por tanto, obtener una marca verde en una compilación donde han desaparecido entradas del índice y una referencia ha salido en blanco. Para índices y bibliografías, la defensa correcta es inspeccionar los archivos .ilg y .blg en lugar del código de salida.

SituaciónCódigo de salida y registro (medido en TeX Live 2024)
makeindex (entries rejected)0. Las entradas descartadas solo salen en el .ilg; con -q desaparecen también de la pantalla
makeindex (no input file)1, con Input index file nosuch.idx not found. y un resumen de uso en una línea
upmendex (no input file)255, imprimiendo Nothing written in output file. y 1 errors, written in doc.ilg.
bibtex (warnings only)0. Warning--I didn t find a database entry for "key" no cuenta como fallo
bibtex (error messages)2, ante un error de sintaxis en el .bib o ante I found no database files
biber0 con solo advertencias, 2 en cuanto imprime ERROR -; el recuento sale al final como INFO - WARNINGS: 1

Leer el .ilg de makeindex: ahí fueron a parar las entradas descartadas

Cada ejecución de makeindex escribe tanto un .ind —el índice que se compondrá— como un .ilg, un registro del trabajo. Una ejecución sana es escueta: Scanning input file doc.idx....done (6 entries accepted, 0 rejected)., luego Sorting entries....done (19 comparisons)., luego Generating output file doc.ind....done (20 lines written, 0 warnings). Casi no es exagerado decir que lo único que merece lectura son los números entre paréntesis. Dale un .idx estropeado y el recuento de accepted baja mientras se alinean los motivos: !! Input index error (file = bad.idx, line = 4): seguido de -- Incomplete first argument (premature LFD). El código de salida sigue siendo 0. Comprobar que el recuento accepted coincide con el número de órdenes \index escritas evita ya la mayoría de los accidentes. La versión incluida en TeX Live 2024 es, por cierto, makeindex 2.17, que se presenta como (kpathsea + Thai support).

terminal
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 watching

Este programa discreto tiene un origen sorprendente. Lo escribió Pehong Chen, pero los agradecimientos de su página de manual dejan constancia de que «Leslie Lamport contributed significantly to the design of MakeIndex». El autor de LaTeX participó de cerca en el diseño del programa de índices, y por eso la sintaxis de \index se siente continua con el resto de LaTeX en lugar de añadida. El uso de @ en \index{clave@impreso} y el asunto de dar clave de ordenación a las palabras acentuadas se detallan en la página dedicada a los índices en sí.

Qué programa de índice elegir: las mismas cuatro palabras, ordenadas por los tres

Solo hay un criterio: ¿necesita cotejo (collation) la lengua que estás indizando? Mete las cuatro palabras Zeta, Ähre, Apfel y Öl tal cual en un .idx y pásalas a los tres programas: la diferencia salta a la vista. makeindex produjo Apfel, Zeta, Ähre, Öl —Ä y Ö tienen en UTF-8 valores de byte mayores que Z, así que caen más allá del final del alfabeto—. texindy -C utf8 -L german-din y upmendex produjeron ambos Ähre, Apfel, Öl, Zeta, tratando Ä como A y Ö como O, exactamente como manda la regla DIN alemana. xindy (de Joachim Schrod, release 2.5.1) llega ahí mediante módulos de lengua; upmendex (version 1.08), mediante el algoritmo de cotejo de ICU 74.2.

ProgramaCómo ordenó las mismas cuatro palabrasCuándo elegirlo
makeindexApfel, Zeta, Ähre, Öl — lo no ASCII cae detrás de ZSolo inglés, o si vas a dar las claves de ordenación a mano
texindyÄhre, Apfel, Öl, Zeta — con -L german-dinLenguas europeas; basta con nombrar la lengua en -L
upmendexÄhre, Apfel, Öl, Zeta — cotejado mediante ICUJaponés y escritura mixta; sigue leyendo los estilos de makeindex
mendexAdivina la codificación de entrada e imprime (guessed encoding #4: UTF-8 = utf8)Material antiguo de pLaTeX; para algo nuevo, mejor upmendex

Dos precauciones prácticas. Primera: el .ind que escribe texindy tiene una estructura distinta de la de makeindex; usa \lettergroup para encabezar cada grupo alfabético y escribe él mismo las definiciones con \providecommand. Si tu documento las redefine, chocarán, así que mira la salida una vez al cambiar. Segunda: xindy corre sobre Common Lisp —CLISP 2.49.93 en esta edición—, lo que hace pesado el arranque y puede notarse mucho en un índice grande. Cuando hay japonés de por medio, upmendex es más rápido y menos quisquilloso.

El extraño censo al final de un .blg de bibtex

Abre doc.blg después de ejecutar bibtex doc y, más allá de las advertencias, aparece una tabla poco familiar: if$ -- 47, while$ -- 2, swap$ -- 1, substring$ -- 6, y así sigue. Es el recuento de cuántas veces se ejecutó cada instrucción de la máquina de pila interna de BibTeX: 237 llamadas en total en esta ejecución. Existe algo así porque un archivo de estilo .bst no es un archivo de configuración sino un programa para esa máquina virtual. Cerca del principio del mismo .blg está Capacity: max_strings=200000, hash_size=200000, hash_prime=170003, cifras heredadas de los presupuestos de memoria de los años ochenta; son el techo tras el grito que empieza por Sorry---you ve exceeded BibTeX s en una bibliografía muy grande. El autor es Oren Patashnik, de Stanford, y la versión incluida en TeX Live 2024 es BibTeX 0.99d.

BibTeX tiene descendientes de ocho bits y compatibles con Unicode, y TeX Live 2024 los trae todos. bibtex8 se llama a sí mismo «8-bit Big BibTeX version 0.99d-x4.02»; bibtexu es el «UTF-8 Big BibTeX» y está construido con ICU 74.2. Para japonés están pbibtex (familia pTeX) y upbibtex (familia upTeX, que se anuncia como upBibTeX 0.99d-j0.36-u1.30 (utf8.uptex)). Todos proceden del mismo linaje 0.99d; solo cambian el tratamiento de los caracteres y el cotejo. En la práctica dominan dos errores. Un .bib mal formado produce Illegal end of database file---line 14 of file broken.bib y I m skipping whatever remains of this entry, con código de salida 2; un \bibliography que apunta a un archivo inexistente produce I found no database files---while reading file doc.aux.

biber: un registro que etiqueta cada línea como INFO, WARN o ERROR

biber es un diseño más reciente escrito en Perl, y hasta la forma de su registro es distinta. Empieza con INFO - This is Biber 2.19 y después informa, línea etiquetada a línea etiquetada, del .bcf que leyó, de cuántas claves de cita encontró, de la configuración regional aplicada y del .bbl que escribió, con cada línea precedida por INFO -. Cuando algo va mal cambia la etiqueta, como en WARN - I didn t find a database entry for 'missingkey' (section 0), y al final llega el recuento: INFO - WARNINGS: 1. Esa legibilidad para máquinas es la mayor diferencia práctica con bibtex: una comprobación de CI se escribe contando WARN - y ERROR - con grep. El accidente habitual es un nombre de entrada mal escrito; biber doc.tex imprime ERROR - Cannot find 'doc.tex.bcf'! y sale con 2. Ten en cuenta además que biber y bibtex escriben ambos un archivo con extensión .blg, así que si has probado los dos, lee la primera línea para saber cuál estás mirando.

terminal
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.ilg

El orden de ejecución y quién cuenta las pasadas por ti

El orden es: componer, luego índice y bibliografía, luego componer, luego componer otra vez. La primera pasada hace que LaTeX escriba .idx y .aux —o .bcf con biblatex—; después se ejecutan estos programas sobre ellos para producir .ind y .bbl; se compone de nuevo para incorporarlos; y si la numeración se ha desplazado, una vez más. Lo incómodo es que el número de pasadas no es fijo, y justo por eso existen herramientas como latexmk. Teclear las órdenes a mano solo merece la pena cuando hay que aislar qué etapa falló, y hasta eso sigue un orden fijo. Comprueba primero si llegó a producirse .idx o .bcf: si no, el problema está del lado de LaTeX. Lee después .ilg y .blg: si existen, el problema está en el programa. Compón por último una vez más y mira si .ind y .bbl llegaron de verdad al cuerpo. Esos tres pasos reducen la causa casi a un solo punto.

terminal
# 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