Latest news 2024-10-15: New blog post: Tales for Our Times Book Launch.

Decyphering the Aux File Commands Provided by glossaries.sty and glossaries-extra.sty

This is a guide for document build tool developers who want to be able to detect whether or not the tool chain should include additional steps to create (or recreate) the files needed by glossaries.sty or glossaries-extra.sty to produce an up-to-date document.

If you are a document author interested in trying to add the relevant step to your document build setup, then try Incorporating makeglossaries or makeglossaries-lite or bib2gls into the document build.

The section Note to Front-End and Script Developers of the glossaries user manual describes all relevant commands. This article provides examples that demonstrate them.

In the examples below, substitute latex with pdflatex, xelatex or lualatex, as applicable. The document source code is assumed to be in a file called myDoc.tex (so the job name is myDoc).

No Glossary

image of simple document without a glossary

This example doesn’t actually have any glossaries. This may be because it’s a work in progress or because the terms are simply defined at the relevant point in the document and the document is short enough not to require a list.

\documentclass{article}

\usepackage[acronym,symbols]{glossaries}

% entries in default 'main' glossary:
\newglossaryentry{sample}{name={sample},description={an example}}
\newglossaryentry{function}{name={function},
 symbol={\ensuremath{f}},
 description={a function}}

% entries in 'acronym' glossary:
\newacronym{ex}{EX}{example}
\newacronym{abbr}{abbr}{abbreviation}

% entries in 'symbols' glossary:
\newglossaryentry{fx}{name={\ensuremath{f(x)}},
 description={a function of $x$},
 type=symbols
}

\newglossaryentry{dfx}{name={\ensuremath{f'(x)}},
 description={a derivative of the function $f(x)$},
 type=symbols
}

\begin{document}
A \gls{sample} document with an \gls{ex} derivative \gls{dfx}.
There are two \glspl{abbr}: \gls{ex} and \gls{abbr}.
\end{document}

The document build is simply:
latex myDoc
The aux file contains:
\providecommand\@newglossary[4]{}
\@newglossary{main}{glg}{gls}{glo}
\@newglossary{acronym}{alg}{acr}{acn}
\@newglossary{symbols}{slg}{sls}{slo}
(The other lines aren’t related to the glossaries package.)

Any non-ignored glossary is identified in the aux file with:

\@newglossary{glossary-label}{log-ext}{out-ext}{in-ext}
This command was originally provided for the benefit of makeglossaries and is now also used by bib2gls, but note that it’s present in this example even though no external tool is required.

The arguments are the file extensions for makeindex and xindy. (The extensions are only applicable with \makeglossaries.) This line in the aux file is written by the corresponding \newglossary command, so the list will match the order in which the glossaries were defined. (This isn’t necessarily the same order as the order in which package options such as “acronym” and “symbols” are listed.)

The presence of \@newglossary in the aux file, doesn’t automatically mean that an external tool is required.
image of simple document without a glossary

The above example can be adapted to use glossaries-extra:

\documentclass{article}

\usepackage[acronym,symbols]{glossaries-extra}

% entries in default 'main' glossary:
\newglossaryentry{sample}{name={sample},description={an example}}
\newglossaryentry{function}{name={function},
 symbol={\ensuremath{f}},
 description={a function}}

\setabbreviationstyle[acronym]{long-short}

% entries in 'acronym' glossary:
\newacronym{ex}{EX}{example}
\newacronym{abbr}{abbr}{abbreviation}

% entries in 'symbols' glossary:
\newglossaryentry{fx}{name={\ensuremath{f(x)}},
 description={a function of $x$},
 type=symbols
}

\newglossaryentry{dfx}{name={\ensuremath{f'(x)}},
 description={a derivative of the function $f(x)$},
 type=symbols
}

\begin{document}
A \gls{sample} document with an \gls{ex} derivative \gls{dfx}.
There are two \glspl{abbr}: \gls{ex} and \gls{abbr}.
\end{document}

The aux file has an extra line:
\providecommand\@newglossary[4]{}
\@newglossary{main}{glg}{gls}{glo}
\@newglossary{acronym}{alg}{acr}{acn}
\@newglossary{symbols}{slg}{sls}{slo}
\providecommand\@glsxtr@savepreloctag[2]{}
However, the document build is exactly the same as before:
latex myDoc

\printunsrtglossary

The simplest way of producing a glossary in the document is with \printunsrtglossary, which is provided by glossaries-extra. If you are familiar with bib2gls, you will probably recognise this command, but although it was provided for use with bib2gls, it can be used without it.

The “unsrt” part of \printunsrtglossary is a reference to the fact that this command simply iterates over the glossary’s internal list of entry labels. Whenever an entry is defined, its label is appended to the internal list. This means that \printunsrtglossary will always be in order of definition and will iterate over every label in the glossary, regardless of whether or not it has been indexed in the document.

(The way that bib2gls works is that bib2gls sorts the data obtained from the bib files and then writes the (LaTeX) definitions in the .glstex file in the appropriate order to ensure that the (glossaries[-extra].sty) order of definition matches the desired sort method.)

image of simple document with three glossary lists

The previous example can be adapted to include \printunsrtglossaries, which does \printunsrtglossary for each defined (non-ignored) glossary:

\documentclass{article}

\usepackage[acronym,symbols,style=tree]{glossaries-extra}

% entries in default 'main' glossary:
\newglossaryentry{sample}{name={sample},description={an example}}
\newglossaryentry{function}{name={function},
 symbol={\ensuremath{f}},
 description={a function}}

\setabbreviationstyle[acronym]{long-short}

% entries in 'acronym' glossary:
\newacronym{ex}{EX}{example}
\newacronym{abbr}{abbr}{abbreviation}

% entries in 'symbols' glossary:
\newglossaryentry{fx}{name={\ensuremath{f(x)}},
 description={a function of $x$},
 type=symbols
}

\newglossaryentry{dfx}{name={\ensuremath{f'(x)}},
 description={a derivative of the function $f(x)$},
 type=symbols
}

\begin{document}
A \gls{sample} document with an \gls{ex} derivative \gls{dfx}.
There are two \glspl{abbr}: \gls{ex} and \gls{abbr}.

\printunsrtglossaries
\end{document}

Again, this simple example only requires a single LaTeX call:
latex myDoc
However, because \printunsrtglossary automatically starts a section, there's more information in the aux file:
\providecommand\@newglossary[4]{}
\@newglossary{main}{glg}{gls}{glo}
\@newglossary{acronym}{alg}{acr}{acn}
\@newglossary{symbols}{slg}{sls}{slo}
\providecommand\@glsxtr@savepreloctag[2]{}
\@writefile{toc}{\contentsline {section}{Glossary}{1}{}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{Acronyms}{1}{}\protected@file@percent }
\@writefile{toc}{\contentsline {section}{Symbols}{1}{}\protected@file@percent }
These extra lines aren’t remarkable to glossaries or glossaries-extra. They are part of the standard LaTeX sectioning system. If a table of contents is required, an extra LaTeX run is needed.

\printnoidxglossary

The \printnoidxglossary command is similar to \printunsrtglossary in that it iterates over an internal list, but this method uses the aux file to determine whether or not an entry was referenced in the previous run and, if so, on what pages. The use of \makenoidxglossaries changes the behaviour of commands like \gls and \glsadd so that they write this information in the aux file. The “noidx” part of the command names is because this method doesn’t require an external indexing tool.

The sort=def setting will make \printnoidxglossary iterate over the glossary’s internal label list (like \printunsrtglossary) but it will skip any entries that didn’t have a reference in the aux file. The sort=use setting will instead use another internal list that’s built up while the aux file is read. This means that the list will be in order of use. The other sort settings will sort that internal list (using LaTeX code applicable to the setting) before iterating over it.

image of simple document with three glossary lists

The first example can be adapted to use \printnoidxglossary to display the glossary lists.

\documentclass{article}

\usepackage[acronym,symbols,style=tree]{glossaries}

\makenoidxglossaries

% entries in default 'main' glossary:
\newglossaryentry{sample}{name={sample},description={an example}}
\newglossaryentry{function}{name={function},
 symbol={\ensuremath{f}},
 description={a function}}

% entries in 'acronym' glossary:
\newacronym{ex}{EX}{example}
\newacronym{abbr}{abbr}{abbreviation}

% entries in 'symbols' glossary:
\newglossaryentry{fx}{name={\ensuremath{f(x)}},
 description={a function of $x$},
 type=symbols
}

\newglossaryentry{dfx}{name={\ensuremath{f'(x)}},
 description={a derivative of the function $f(x)$},
 type=symbols
}

\begin{document}
A \gls{sample} document with an \gls{ex} derivative \gls{dfx}.
There are two \glspl{abbr}: \gls{ex} and \gls{abbr}.

\printnoidxglossary
\printnoidxglossary[type=acronym]
\printnoidxglossary[type=symbols,sort=use]
\end{document}

The document build requires two LaTeX runs:
latex myDoc
latex myDoc
The first instance will generate the following warnings in the transcript:
Package glossaries Warning: Empty glossary for \printnoidxglossary[type={main}]. Rerun may be required (or you may have forgotten to use commands like \gls) on input line 33. Package glossaries Warning: Empty glossary for \printnoidxglossary[type={acronym}]. Rerun may be required (or you may have forgotten to use commands like \gls) on input line 33. Package glossaries Warning: Empty glossary for \printnoidxglossary[type={symbols}]. Rerun may be required (or you may have forgotten to use commands like \gls) on input line 34.
The aux file now contains:
\providecommand\@newglossary[4]{}
\@newglossary{main}{glg}{gls}{glo}
\@newglossary{acronym}{alg}{acr}{acn}
\@newglossary{symbols}{slg}{sls}{slo}
\providecommand\@gls@reference[3]{}
\@gls@reference{main}{sample}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}
\@gls@reference{acronym}{ex}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}
\@gls@reference{symbols}{dfx}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}
\@gls@reference{acronym}{abbr}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}
\@gls@reference{acronym}{ex}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}
\@gls@reference{acronym}{abbr}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}
This now has a reference command corresponding to each time an entry is referenced (with a command such as \gls) in the document.
\@gls@reference{type}{label}{location}
Testing the log file for “Rerun may be required” is only helpful on the first run. If the first line of the document is altered to:
A \gls{sample} document with an \gls{ex} derivative \gls{dfx} of \gls{fx}.
(which now references the fx entry) then there is no warning to indicate a rerun is required. Another possibility is that editing the document may result in different locations, which again doesn’t trigger a warning (but neither does a change to the table of contents or list of figures etc).

So, searching for \@gls@reference in the aux file is an indication that at least two LaTeX runs are required, but you need to take into account the hybrid option provided by glossaries-extra, which allows both \printnoidxglossary and \printglossary to appear in the same document.

\printglossary (makeindex)

The \printglossary command follows the more conventional LaTeX route of inputting a file that contains the code to typeset the glossary. This file is created by an external application that reads in a file written by LaTeX. This means that LaTeX must first be run to create the file required by the indexing application so that the indexing application can then create the file that needs to be input by \printglossary. The glossaries package supports makeindex and xindy. This example focuses on makeindex.

The input/output terminology can be confusing. The file that LaTeX creates (.glo) is an output file from LaTeX’s point of view, but an input file from the indexing application’s point of view. The file that the indexing application creates (.gls) is an output file from the indexing application’s point of view, but is an input file from LaTeX’s point of view.

(It was this confusion that led to me accidentally switching the .glo and .gls extensions when replacing the old glossary.sty package with the first version of the glossaries.sty package, but it’s too late to change it now.)

image of simple document with three glossary lists

The previous example can be modified to use \makeglossaries and \printglossary instead of the “noidx” commands.

\documentclass{article}

\usepackage[acronym,symbols,style=tree]{glossaries}

\makeglossaries

% entries in default 'main' glossary:
\newglossaryentry{sample}{name={sample},description={an example}}
\newglossaryentry{function}{name={function},
 symbol={\ensuremath{f}},
 description={a function}}

% entries in 'acronym' glossary:
\newacronym{ex}{EX}{example}
\newacronym{abbr}{abbr}{abbreviation}

% entries in 'symbols' glossary:
\newglossaryentry{fx}{name={\ensuremath{f(x)}},sort={fx},
 description={a function of $x$},
 type=symbols
}

\newglossaryentry{dfx}{name={\ensuremath{f'(x)}},sort={f'x},
 description={a derivative of the function $f(x)$},
 type=symbols
}

\begin{document}
A \gls{sample} document with an \gls{ex} derivative \gls{dfx}.
There are two \glspl{abbr}: \gls{ex} and \gls{abbr}.

\printglossary
\printglossary[type=acronym]
\printglossary[type=symbols]
\end{document}

On the first LaTeX run, the transcript includes the messages:
No file myDoc.aux. No file myDoc.gls. No file myDoc.acr. No file myDoc.sls.
The first of these messages isn’t specific to glossaries as it will occur with any LaTeX document on the first run. The other three lines are generated by each successive instance of \printglossary. The file extensions match those in the third argument of \@newglossary. The aux file has some extra commands:
\providecommand\@newglossary[4]{}
\@newglossary{main}{glg}{gls}{glo}
\@newglossary{acronym}{alg}{acr}{acn}
\@newglossary{symbols}{slg}{sls}{slo}
\providecommand\@glsorder[1]{}
\providecommand\@istfilename[1]{}
\@istfilename{myDoc.ist}
\@glsorder{word}

The “no file” transcript messages aren’t particularly useful for a build tool as they won’t appear once the files have been created, so there’s no indication that they need updating. The information in the aux file provides more information.

The presence of \@istfilename in the aux file indicates that makeindex or xindy is required.

In this case, you have two possibilities:

  1. If \@istfilename is found in the aux file, then run makeglossaries or makeglossaries-lite.
  2. Determine if makeindex or xindy is required, and run the relevant tool with the applicable switches for each glossary identified by \@newglossary.

(See below if you are undecided as to which method you should choose.)

In the first case, makeglossaries is better than makeglossaries-lite because it provides extra diagnostics when things go wrong, does some repair work to overcome any encap clashes, and provides some language mappings for xindy. The drawback is that it requires Perl, but so does xindy.

If you’re interested in comparing file modification dates, remember that \makeglossaries opens each glossary file. The indexing style file (identified by \@istfilename) is also, by default, created by \makeglossaries, although this can be overridden to allow the user to customise it by directly editing the style file.

So, for this example document, if myDoc.gls doesn’t exist or myDoc.ist (identified by \@istfilename) is newer than myDoc.gls, or if myDoc.glo is newer than myDoc.gls, then run makeglossaries (followed by another LaTeX run). The gls and glo extensions are selected from the arguments of the first instance of \@newglossary. (Bear in mind that the nomain package option prevents the creation of the default “main” glossary, so don’t assume these extensions.)

If you prefer the second case (explicitly run makeindex or xindy instead of using makeglossaries), then the extension of the filename argument of \@istfilename identifies whether or not the file is a makeindex style file or a xindy module.

\@istfilename{filename}

If filename ends with .xdy then xindy is required. Otherwise assume makeindex.

Note that while xindy requires a .xdy extension, makeindex doesn’t enforce a .ist extension and the glossaries package does still support the old pre-xindy (now undocumented) method of specifying the full filename (instead of just the basename) for the style file. So test for “ends with .xdy” not “ends with .ist”.

The sort ordering can be either word or letter ordering. The default is word ordering, so that’s what this example has.

\@glsorder{order}
The order should only ever be either the keyword “word” or the keyword “letter”.

So, for this example, \@istfilename is present, the filename argument doesn’t end with .xdy, and the order argument of \@glsorder isn’t “letter”. Therefore makeindex is required and it needs to be invoked with -s myDoc.ist but should not have the -l (letter) switch. This needs to be done for each set of glossary extensions identified in \@newglossary:

makeindex -s myDoc.ist -t myDoc.glg -o myDoc.gls myDoc.glo
makeindex -s myDoc.ist -t myDoc.alg -o myDoc.acr myDoc.acn
makeindex -s myDoc.ist -t myDoc.slg -o myDoc.sls myDoc.slo

Another LaTeX run is then required:

latex myDoc

Note that with makeindex, the aux file may also contain:

\@gls@extramakeindexopts{args}
This indicates any additional switches that should be passed to makeindex. The use of \GlsSetQuote with German will set args to -g. (At the time of writing, no other switches are added.)

This aux command will only appear if args has been set. It’s detected by both makeglossaries and makeglossaries-lite, so you only need to worry about it if you are explicitly invoking makeindex.

Let’s switch back to glossaries-extra again, but this time use “abbreviation” instead of “acronym”:

image of simple document with three glossaries
\documentclass{article}

\usepackage[abbreviations,symbols,style=tree]{glossaries-extra}

\makeglossaries

% entries in default 'main' glossary:
\newglossaryentry{sample}{name={sample},description={an example}}
\newglossaryentry{function}{name={function},
 symbol={\ensuremath{f}},
 description={a function}}

% entries in 'abbreviations' glossary:
\newabbreviation{ex}{EX}{example}
\newabbreviation{abbr}{abbr}{abbreviation}

% entries in 'symbols' glossary:
\newglossaryentry{fx}{name={\ensuremath{f(x)}},sort={fx},
 description={a function of $x$},
 type=symbols
}

\newglossaryentry{dfx}{name={\ensuremath{f'(x)}},sort={f'x},
 description={a derivative of the function $f(x)$},
 type=symbols
}

\begin{document}
A \gls{sample} document with an \gls{ex} derivative \gls{dfx}.
There are two \glspl{abbr}: \gls{ex} and \gls{abbr}.

\printglossary
\printglossary[type=abbreviations]
\printglossary[type=symbols]
\end{document}

The aux file now contains:
\providecommand\@newglossary[4]{}
\@newglossary{main}{glg}{gls}{glo}
\@newglossary{symbols}{slg}{sls}{slo}
\@newglossary{abbreviations}{glg-abr}{gls-abr}{glo-abr}
\providecommand\@glsxtr@savepreloctag[2]{}
\providecommand\@glsorder[1]{}
\providecommand\@istfilename[1]{}
\@istfilename{myDoc.ist}
\@glsorder{word}
Note that the “abbreviations” glossary has a different set of extensions to the “acronym” glossary. This allows the user to easily create two separate abbreviation glossaries: the original “acronym” glossary provided by the base glossaries package (which \newacronym will default to using), and the newer “abbreviations” glossary provided by glossaries-extra (which \newabbreviation will default to using).

So now the document build is:

latex myDoc
makeindex -s myDoc.ist -t myDoc.glg -o myDoc.gls myDoc.glo
makeindex -s myDoc.ist -t myDoc.slg -o myDoc.sls myDoc.slo
makeindex -s myDoc.ist -t myDoc.glg-abr -o myDoc.gls-abr myDoc.glo-abr
latex myDoc

\printglossary (xindy)

image of simple document with three glossary lists

Now let’s switch to xindy (with just the base glossaries package):

\documentclass{article}

\usepackage[acronym,symbols,style=tree,xindy]{glossaries}

\makeglossaries

% entries in default 'main' glossary:
\newglossaryentry{sample}{name={sample},description={an example}}
\newglossaryentry{function}{name={function},
 symbol={\ensuremath{f}},
 description={a function}}

% entries in 'acronym' glossary:
\newacronym{ex}{EX}{example}
\newacronym{abbr}{abbr}{abbreviation}

% entries in 'symbols' glossary:
\newglossaryentry{fx}{name={\ensuremath{f(x)}},sort={fx},
 description={a function of $x$},
 type=symbols
}

\newglossaryentry{dfx}{name={\ensuremath{f'(x)}},sort={f'x},
 description={a derivative of the function $f(x)$},
 type=symbols
}

\begin{document}
A \gls{sample} document with an \gls{ex} derivative \gls{dfx}.
There are two \glspl{abbr}: \gls{ex} and \gls{abbr}.

\printglossary
\printglossary[type=acronym]
\printglossary[type=symbols]
\end{document}

This simply adds xindy to the list of package options, but there are extra lines in the aux file (the \providecommand lines have been removed for clarity):
\@xdylanguage{main}{english}
\@gls@codepage{main}{utf8}
\@xdylanguage{acronym}{english}
\@gls@codepage{acronym}{utf8}
\@xdylanguage{symbols}{english}
\@gls@codepage{symbols}{utf8}
\@newglossary{main}{glg}{gls}{glo}
\@newglossary{acronym}{alg}{acr}{acn}
\@newglossary{symbols}{slg}{sls}{slo}
\@istfilename{myDoc.xdy}
\@glsorder{word}

The argument of \@istfilename now ends with .xdy, which indicates that xindy is required, but the other clue is the presence of \@xdylanguage and \@gls@codepage, which indicate the language and encoding required for each glossary. The encoding should typically be the same for each glossary. (It would be very unusual and highly problematic to have a mixture of encodings in the same document.)

The document build is now:

latex myDoc
xindy -L english -C utf8 -I xindy -M myDoc -t myDoc.glg -o myDoc.gls myDoc.glo
xindy -L english -C utf8 -I xindy -M myDoc -t myDoc.slg -o myDoc.sls myDoc.slo
xindy -L english -C utf8 -I xindy -M myDoc -t myDoc.alg -o myDoc.acr myDoc.acn
latex myDoc

The language for each glossary is identified with:

\@xdylanguage{glossary-label}{language}
where glossary-label identifies the glossary (which matches the first argument of the corresponding \@newglossary) and language is the language label. The language label will default to the expansion of \languagename, unless the document author explicitly changed it with \GlsSetXdyLanguage or xindy={language=language}.
\@gls@codepage{code-page}

The codepage will default to the expansion of \inputencodingname, if it’s defined, or utf8, otherwise. Again, the document author can explicitly change this value (via \GlsSetXdyCodePage or xindy={codepage=code-page}).

The codepage and language commands are written to the aux file by \printglossary using \immediate to ensure that they pick up the document language and encoding at the point where the glossary is displayed. The \@newglossary commands are written using a delayed write by \newglossary (because it’s a preamble command and the old aux file must be input before the new one can be created, so the write has to be delayed). The different behaviour between the immediate and delayed write is the reason why the language and codepage commands appear before the other commands for this short example.

The LaTeX language and encoding labels aren’t guaranteed to match the xindy identifiers, and xindy may not even provide a close match.

For example, the makeglossaries Perl script will map “brazilian” to “portuguese” and “naustrian” to “german”. Additionally, if a known German language label is detected, the code-page will be inspected to determine if “din5007-” should be added. If you want your build tool to explicitly invoke xindy, then you will either need to provide similar checks or you will have to instruct your users to identify the correct xindy language and code-page information. For example:

\usepackage[xindy={language={german},codepage={din5007-utf8}}]{glossaries}

What are the Benefits of Using makeglossaries Over an Explicit makeindex/xindy Call?

If you are undecided whether to use makeglossaries versus makeglossaries-lite versus a direct call to makeindex or xindy, try out the following example (myDoc.tex):

\documentclass{article}

\usepackage{glossaries}

\makeglossaries

\newglossaryentry{sample}{name={sample},description={an example}}
\newglossaryentry{alpha}{name={\ensuremath{\alpha}},description={alpha}}

\begin{document}
A \gls{sample} and another \gls[format=textbf]{sample} and
\gls{alpha}.

\printglossary
\end{document}
First try:
pdflatex myDoc
makeindex -s myDoc.ist -t myDoc.glg -o myDoc.gls myDoc.glo
pdflatex myDoc
The makeindex transcript file myDoc.glg will have one warning:
## Warning (input = myDoc.glo, line = 2; output = myDoc.gls, line = 8): -- Conflicting entries: multiple encaps for the same page under same key.
The PDF file will have “1, 1” in the “sample“ location list. This is the result of indexing the “sample” entry twice on page 1 with difference formats (encaps).

Now try:

pdflatex myDoc
makeglossaries myDoc
pdflatex myDoc
The makeglossaries run will write the following messages to the terminal:
## Warning (input = myDoc.glo, line = 2; output = myDoc.gls, line = 8): -- Conflicting entries: multiple encaps for the same page under same key. Multiple encaps detected. Attempting to remedy. Reading myDoc.glo... Writing myDoc.glo... Retrying
Note that makeglossaries has patched and created a new .glo file. The PDF file now just has “1” in the location list.

Now switch to xindy:

\usepackage[xindy]{glossaries}
And try:
pdflatex myDoc
xindy -L english -C utf8 -I xindy -M myDoc -t myDoc.glg -o myDoc.gls myDoc.glo
The xindy run fails with the message:
ERROR: CHAR: index 0 should be less than the length of the string
What does this mean? It means that there’s a problem with the sort value for an entry, but which entry? This is a small example with only two entries, but let’s suppose the document has 100 entries. How does the document author narrow it down?

Now try makeglossaries:

makeglossaries myDoc
The process still fails, but makeglossaries provides more detail:
***Call to xindy failed*** Possible cause of problem: Sort key required for entries only containing command names. Attempting to determine which entries have problem sort keys. Parsing 'myDoc.glo' 1 problematic entry found: Label: 'alpha'. Sort value : '\\ensuremath {\\alpha }' (Try adding sort={alpha} to the definition.)
makeglossaries appends this information to xindy’s transcript file as well as writing it to the terminal.

So makeglossaries detects the error, provides a more informative message, finds the problematic entry, and suggests a remedy.

Note that makeglossaries-lite doesn’t make these corrections or provide diagnostic information. It’s only benefit is that it can parse the aux file to determine whether to call makeindex or xindy and what command line options should be used.

If you want your build tool to bypass makeglossaries, are you prepared to provide similar diagnostics and corrections?

The advantage in directly calling makeindex or xindy is that it’s slightly faster and has one less sub-process.

Can an Alternative to MakeIndex be Used?

Only if the alternative can understand the makeindex style file created by \makeglossaries or if you can convert the style file into an equivalent set of instructions for the alternative indexing application.

The glossary styles won’t work if the output doesn’t match this format, and location hyperlinks won’t work correctly if the location range and separator symbols aren’t the expected commands.

Hybrid \printglossary and \printnoidxglossary

The glossaries-extra package provides a hybrid option that allows the use of both \printglossary (which requires makeindex or xindy) and \printnoidxglossary (which simply requires a second LaTeX run). The advantage with this method is that it allows different sort methods for different glossaries. In particular, it means that the superior alphabetical sorting and collation performed by external indexing tools can be used for glossaries with natural language terms (which is harder to do in LaTeX) but a glossary that contains symbolic or pictographic names can simply be ordered by use or by definition (which is easy to do in LaTeX).

Note that bib2gls can use different sort methods for different glossaries. This hybrid method is only applicable with \makeglossaries.

image of simple document with three glossary lists

This method can be demonstrated in the following example document:

\documentclass{article}

\usepackage[abbreviations,symbols,style=tree]{glossaries-extra}

\makeglossaries[main,abbreviations]

% entries in default 'main' glossary:
\newglossaryentry{sample}{name={sample},description={an example}}
\newglossaryentry{function}{name={function},
 symbol={\ensuremath{f}},
 description={a function}}

% entries in 'abbreviations' glossary:
\newabbreviation{ex}{EX}{example}
\newabbreviation{abbr}{abbr}{abbreviation}

% entries in 'symbols' glossary:
\newglossaryentry{fx}{name={\ensuremath{f(x)}},sort={fx},
 description={a function of $x$},
 type=symbols
}

\newglossaryentry{dfx}{name={\ensuremath{f'(x)}},sort={f'x},
 description={a derivative of the function $f(x)$},
 type=symbols
}

\begin{document}
A \gls{sample} document with an \gls{ex} derivative \gls{dfx}.
There are two \glspl{abbr}: \gls{ex} and \gls{abbr}.

\printglossary
\printglossary[type=abbreviations]
\printnoidxglossary[type=symbols,sort=def]
\end{document}

On the first LaTeX run, a warning appears in the transcript:

Package glossaries Warning: Empty glossary for \printnoidxglossary[type={symbols}]. Rerun may be required (or you may have forgotten to use commands like \gls) on input line 34.

This is the same as for the earlier example that used \printnoidxglossary, but there’s now only one warning.

After the first LaTeX run, the aux file now contains:

\providecommand\@newglossary[4]{}
\@newglossary{main}{glg}{gls}{glo}
\@newglossary{symbols}{slg}{sls}{slo}
\@newglossary{abbreviations}{glg-abr}{gls-abr}{glo-abr}
\providecommand\@glsxtr@savepreloctag[2]{}
\providecommand\@glsorder[1]{}
\providecommand\@istfilename[1]{}
\@istfilename{myDoc.ist}
\@glsorder{word}
\glsxtr@makeglossaries{main,abbreviations}
\providecommand\@gls@reference[3]{}
\@gls@reference{symbols}{dfx}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}

This contains \@istfilename and \@glsorder (which indicates \makeglossaries was used), but it also contains \@gls@reference, which indicates that the document is expected to contain \printnoidxglossary. However, there’s an additional command that hasn’t yet been mentioned:

\glsxtr@makeglossaries{label-list}
The argument label-list corresponds to the optional argument of \makeglossaries (which is only permitted with glossaries-extra). This indicates which glossaries need to be processed by makeindex or xindy.

If you have chosen to use the simpler option of just checking for \@istfilename and then running the makeglossaries Perl script (or makeglossaries-lite Lua script), then you don’t need to make a special case, as both scripts check for this command. (Although, if you are also checking for \@gls@reference, make sure you check for \@istfilename first).

If you have chosen to explicitly run makeindex or xindy, then perform the same checks as before, but only run the required indexing application for the glossaries whose labels are listed in label-list. For this example document, the build process is:

latex myDoc
makeindex -s myDoc.ist -t myDoc.glg -o myDoc.gls myDoc.glo
makeindex -s myDoc.ist -t myDoc.glg-abr -o myDoc.gls-abr myDoc.glo-abr
latex myDoc

bib2gls

The glossaries-extra package provides an alternative method of indexing, and that’s with the bib2gls application, which has two functions:

  1. fetch data relevant to the document from associated bib files;
  2. sort the data so that \printunsrtglossary will list the data in the required order (with the relevant locations, if applicable).
The second function is optional. The document may not require a sorted list. For example, it may have standalone definitions at the appropriate places in the main matter.
image of simple document with three glossary lists

The example document below does require a sorted list. It’s actually very similar to the earlier \printunsrtglossary example, but the definitions have been removed from the preamble:

\documentclass{article}

\usepackage[record,acronym,symbols,style=tree]{glossaries-extra}

\setabbreviationstyle[acronym]{long-short}

\GlsXtrLoadResources

\begin{document}
A \gls{sample} document with an \gls{ex} derivative \gls{dfx}.
There are two \glspl{abbr}: \gls{ex} and \gls{abbr}.

\printunsrtglossaries
\end{document}

The corresponding bib file (which was simply created from the earlier example document using convertgls2bib, provided with bib2gls) contains the following:

% Encoding: UTF-8
@entry{sample,
  name = {sample},
  description = {an example}
}

@entry{function,
  symbol = {\ensuremath{f}},
  name = {function},
  description = {a function}
}

@acronym{ex,
  short = {EX},
  long = {example}
}

@acronym{abbr,
  short = {abbr},
  long = {abbreviation}
}

@entry{fx,
  name = {\ensuremath{f(x)}},
  description = {a function of $x$},
  type = {symbols}
}

@entry{dfx,
  name = {\ensuremath{f'(x)}},
  description = {a derivative of the function $f(x)$},
  type = {symbols}
}

For convenience, I’ve given both the document .tex file and the .bib file the same basename (myDoc.tex and myDoc.bib).

The aux file is now considerably larger as most of the document information is supplied to bib2gls via aux file commands. As before, the non-ignored glossaries are identified with \@newglossary, but there are other commands as well. Most of these aren’t relevant to a document build tool. The primary one of interest is:

\glsxtr@resource{options}{basename}

There will be one instance of \glsxtr@resource for each \GlsXtrLoadResources that occurs in the document preamble. The options argument corresponds to the optional argument of \GlsXtrLoadResources and basename is the basename of the .glstex file that’s input by \GlsXtrLoadResources (and needs to be created by bib2gls).

If \glsxtr@resource occurs in the aux file then bib2gls needs to be included in the build process.

If you want to check file existence or modification times, then, for each \glsxtr@resource, check that basename.glstex exists and compare its timestamp with the document source file. Unfortunately it becomes a bit more difficult if the document source is split across multiple files. (Comparing with the aux file’s timestamp can cause an infinite loop in a bib2gls+LaTeX cycle.)

You may also want to check if the relevant bib files have been changed. The bib files can be identified in the src option. If no src is provided, then src={basename.bib} is assumed. The first instance of \GlsXtrLoadResources has a basename that matches \jobname. Subsequence instances of \GlsXtrLoadResources have a basename in the form \jobname-n.

If you want to check file hashes, run bib2gls with --no-date-in-header (version 3.9+) otherwise the hash for the .glstex files will change on every run.

In this example, there’s only one \GlsXtrLoadResources and it has no options, so the corresponding line in the aux file is:

\glsxtr@resource{}{myDoc}
This means that bib2gls should obtain the data from myDoc.bib (since there’s no src option) and create a file called myDoc.glstex. The document build is:
latex myDoc
bib2gls myDoc
latex myDoc
Note that there’s only one bib2gls call (and only one \glsxtr@resource) even though there are three glossaries.

On the first LaTeX run, commands like \gls will produce a double question mark ??, similar to \ref and \cite. The bib2gls run creates a .glstex file which includes the following lines:

\providecommand{\bibglsnewacronym}[4]{%
  \newacronym[#2]{#1}{#3}{#4}%
}

\bibglsnewacronym{abbr}%
{location={\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}},
sort={abbr|}}%
{abbr}%
{abbreviation}
\glsxtrfieldlistadd{abbr}{loclist}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}

\bibglsnewacronym{ex}%
{location={\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}},
sort={EX|}}%
{EX}%
{example}
\glsxtrfieldlistadd{ex}{loclist}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}

\providecommand{\bibglsnewentry}[4]{%
 \longnewglossaryentry*{#1}{name={#3},#2}{#4}%
}

\bibglsnewentry{dfx}%
{location={\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}},
sort={f|x|},
type={symbols}}%
{\ensuremath{f'(x)}}%
{a derivative of the function $f(x)$}
\glsxtrfieldlistadd{dfx}{loclist}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}

\bibglsnewentry{sample}%
{location={\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}},
sort={sample|}}%
{sample}%
{an example}
\glsxtrfieldlistadd{sample}{loclist}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}
Ignoring the “loclist”, “location” and “sort” fields, this is essentially:
\newacronym{abbr}{abbr}{abbreviation}
\newacronym{ex}{EX}{example}

\newglossaryentry{dfx}{
 name={\ensuremath{f'(x)}},
 description={a derivative of the function $f(x)$},
 type={symbols}
}

\newglossaryentry{sample}{
  name={sample},
  description={an example}
}
In other words, it’s very similar to the preamble definitions in the earlier \printunsrtglossary example, but the entries are defined in a different order and the unused ones are omitted.

The next LaTeX run inputs this .glstex file and now the references are resolved. If the link text (that replaces the double question mark) is quite long, this can cause the page numbers to shift in which case another bib2gls+LaTeX run will be required.

You might have noticed that there’s a slight difference in the resulting document, compared with the earlier examples. They all use the “tree” glossary style, but previously there has been a vertical gap between “abbr” and “EX” in the list of acronyms/abbreviations. That gap isn’t present here.

The gap is the “group skip” that’s inserted between different letter groups. The “tree” style doesn’t show the group heading (switch to “treegroup” for that) but it does still include the group skip. The reason for the lack of a group skip in this example is that bib2gls defaults to --no-group, which inhibits the letter group formation. (So even with the “treegroup” style, there will be no group headings.)

If letter groups are required, then bib2gls should be run with --group (or -g). There’s no information in the aux file to determine which switches should be passed to bib2gls.

You can have your build tool automatically add --group. The group skip gap can be suppressed in the document with nogroupskip, as per the other indexing options, or with groups=false (which is only available with \printunsrtglossary). It will, however, increase the complexity of the bib2gls process.

Whilst --group is the most commonly used switch, it’s by no means the only switch that may be required.

Other aux commands that bib2gls searches for include the following, which provide the indexing information:

\glsxtr@record{label}{h-prefix}{counter}{format}{loc}
or (with record=nameref):
\glsxtr@record@nameref{label}{href-prefix}{counter}{format}{location}{title}{href-anchor}{href-value}
or (created by \glssee):
\glsxtr@recordsee{label}{xr-list}
Note that you won’t have both \glsxtr@record and \glsxtr@record@nameref in the same aux file. One or the other will be used, depending on the record setting.
It’s possible to have no record commands in the aux file but still require bib2gls (for example, a dictionary style document that has the resource option selection=all) and only \printunsrtglossary in the document.
image of simple document with three glossary lists

This next example is a slight modification that has two resource sets, as different sort methods are required:

\documentclass{article}

\usepackage[record,abbreviations,symbols,style=tree]{glossaries-extra}

\GlsXtrLoadResources[src={entries,abbreviations},sort=en]
\GlsXtrLoadResources[src=symbols,type=symbols,sort=use]

\begin{document}
A \gls{sample} document with an \gls{ex} derivative \gls{dfx}.
There are two \glspl{abbr}: \gls{ex} and \gls{abbr}.

\printunsrtglossaries
\end{document}

This depends on three .bib files. General entries are in entries.bib:

% Encoding: UTF-8
@entry{sample,
  name = {sample},
  description = {an example}
}

@entry{function,
  symbol = {\ensuremath{f}},
  name = {function},
  description = {a function}
}

Abbreviations are in abbreviations.bib:
% Encoding: UTF-8
@abbreviation{ex,
  short = {EX},
  long = {example}
}

@abbreviation{abbr,
  short = {abbr},
  long = {abbreviation}
}

and symbols are in symbols.bib:
% Encoding: UTF-8
@symbol{fx,
  name = {\ensuremath{f(x)}},
  description = {a function of $x$}
}

@symbol{dfx,
  name = {\ensuremath{f'(x)}},
  description = {a derivative of the function $f(x)$}
}

The aux file now contains two instances of \glsxtr@resource:

\glsxtr@resource{src={entries,abbreviations},sort=en}{myDoc}
\glsxtr@resource{src=symbols,type=symbols,sort=use}{myDoc-1}

In this case, the required .bib files are identified in the src argument. Again, only one call to bib2gls is required:

latex myDoc
bib2gls myDoc
latex myDoc
The number of \glsxtr@resource commands doesn’t necessarily correspond to the number of glossaries.

bib2gls and record=hybrid

image of simple document with three glossary lists

This example demonstrates a rare setting that’s for esoteric use. It’s provided for cases where a document author has a highly customized xindy style that can’t be reproduced with bib2gls resource options but the author would like the convenience of storing all the glossary information in bib files.

\documentclass{article}

\usepackage[xindy,record=hybrid,abbreviations,symbols,style=tree]{glossaries-extra}

\makeglossaries

\GlsXtrLoadResources[src={entries,abbreviations},sort=none,save-locations=false]
\GlsXtrLoadResources[src=symbols,type=symbols,sort=none,save-locations=false]

\begin{document}
A \gls{sample} document with an \gls{ex} derivative \gls{dfx}.
There are two \glspl{abbr}: \gls{ex} and \gls{abbr}.

\printglossaries
\end{document}

(Note that record=alsoindex is a synonym for record=hybrid. The “alsoindex” value means that in addition to creating bib2gls records, also create the more traditional indexing files, but the terminology caused confusion.) The .bib files are the same as in the previous example.

The aux file now has both the xindy commands and the bib2gls commands.

\@xdylanguage{main}{english}
\@gls@codepage{main}{utf8}
\@xdylanguage{symbols}{english}
\@gls@codepage{symbols}{utf8}
\@xdylanguage{abbreviations}{english}
\@gls@codepage{abbreviations}{utf8}
\@newglossary{main}{glg}{gls}{glo}
\@newglossary{symbols}{slg}{sls}{slo}
\@newglossary{abbreviations}{glg-abr}{gls-abr}{glo-abr}
\@istfilename{myDoc.xdy}
\@glsorder{word}
[...]
\glsxtr@resource{src={entries,abbreviations},sort=none,save-locations=false}{myDoc}
\glsxtr@resource{src=symbols,type=symbols,sort=none,save-locations=false}{myDoc-1}
The document build is rather more complex. After the initial LaTeX run, bib2gls needs to create the .glstex files that define the entries using \longnewglossaryentry and \newabbreviation:
latex myDoc

On the first LaTeX run, no entries are defined, which means that the indexing information required for xindy is unavailable, so the .glo etc files will be empty.

This means that if you try running makeglossaries at this point you will get warnings about empty files and if you explicitly use xindy instead, you’ll end up with empty glossaries that will trigger a “missing item” error with any of the “list” glossary styles.

However, the aux file does contain information that bib2gls needs in order to select the required entries, so that their definitions can be written to the .glstex file. Therefore the next step is:

bib2gls myDoc

At this point (that is, after the initial LaTeX+bib2gls), the indexing files myDoc.glo, myDoc.slo and myDoc.glo-abr exist but are empty. However, the .glstex files now exist.

The first file myDoc.glstex contains:

\providecommand{\bibglsnewentry}[4]{%
 \longnewglossaryentry*{#1}{name={#3},#2}{#4}%
}

\bibglsnewentry{sample}%
{}%
{sample}%
{an example}

\providecommand{\bibglsnewabbreviation}[4]{%
  \newabbreviation[#2]{#1}{#3}{#4}%
}

\bibglsnewabbreviation{ex}%
{}%
{EX}%
{example}


\bibglsnewabbreviation{abbr}%
{}%
{abbr}%
{abbreviation}

Note that the entries haven’t been sorted and there are no associated locations. This is because the hybrid method defers sorting and collating locations to the indexing application (xindy).

The second file myDoc-1.glstex includes the lines:

\providecommand{\bibglsnewsymbol}[4]{%
 \longnewglossaryentry*{#1}{name={#3},sort={#1},category={symbol},#2}{#4}}

\bibglsnewsymbol{dfx}%
{type={symbols}}%
{\ensuremath{f'(x)}}%
{a derivative of the function $f(x)$}

The myDoc.glstex file will be input by the first \GlsXtrLoadResources and the myDoc-1.glstex file will be input by the second \GlsXtrLoadResources on the next LaTeX run, and now that the entries have been defined, they can be indexed using xindy syntax:

latex myDoc
Only at this point do the indexing files myDoc.glo, myDoc.slo, and myDoc.glo-abr contain any content.

Note that the provided definition of \bibglsnewsymbol sets the sort value to the label by default. This definition is only picked up by LaTeX (and is not used by bib2gls or affected by the “symbol-sort-fallback” setting). The command may be defined before \GlsXtrLoadResources to omit that sort assignment or to supply a different assignment. In this example, no alternative definition has been provided, so the above lines in the myDoc-1.glstex file are equivalent to:

\newglossaryentry{dfx}{
 name={\ensuremath{f'(x)}},
 sort={dfx},
 category={symbol},
 type={symbols},
 description={a derivative of the function $f(x)$}
}
This means that the myDoc.slo file has the label as the sort value (the first of the tkey pair):
(indexentry :tkey (("dfx" "\\glossentry{dfx}") ) :locref "{}{1}" :attr "pageglsnumberformat" )

Now that the indexing files finally have some content, xindy can be run (either explicitly or via makeglossaries):

xindy -L english -C utf8 -I xindy -M myDoc -t myDoc.glg -o myDoc.gls myDoc.glo
xindy -L english -C utf8 -I xindy -M myDoc -t myDoc.slg -o myDoc.sls myDoc.slo
xindy -L english -C utf8 -I xindy -M myDoc -t myDoc.glg-abr -o myDoc.gls-abr myDoc.glo-abr
And finally LaTeX needs to be run again:
latex myDoc

After this point, bib2gls isn’t needed until the resource options change (that is, the argument of the \GlsXtrLoadResources commands changes) or a new entry is required in the document (which needs to be fetched from the bib file). However, there should be no need to check for the “selection” resource option. If “selection=all” is set, bib2gls will fetch all entries, but \printglossary will still only list the entries that were indexed. So, you can simply check the LaTeX log file for “Package glossaries-extra Warning: Glossary entry `[...]' has not been defined” to decided whether or not to run bib2gls (and you may also want to check if the bib file has changed).

The use of record=hybrid is not encouraged. It overly complicates the document build process. In most cases, bib2gls can be configured for commonly required sorting methods and it doesn’t require locations to be in a specific format.

What happens if the sort=none, save-locations=false resource options are omitted? This will cause bib2gls to use its default settings, which is to sort according to the document language (or the default language if not specified) and collate the locations. This in turn means that the .glstex files will have the sort and location fields set, and so xindy will be supplied the sort values that bib2gls used. This means that not only is the document build more complex but it also involves duplication of effort.

The only advantage that makeindex and xindy have over bib2gls is that the indexing applications categorise the locations by class (decimal, lowercase Roman, uppercase Roman, alphabetic) and each class is a subset of the location list and those subsets can be reordered. With bib2gls, the location list can only be sub-divided and reordered according to the counter used for the location (page, equation, section, etc).

Dependencies with \printnoidxglossary

image of simple document with three glossary lists

This example is a modification of the earlier \printnoidxglossary example. The document text hasn’t changed, but the symbol entry descriptions have been changed so that they reference another entry:

\documentclass{article}

\usepackage[acronym,symbols,style=tree]{glossaries}

\makenoidxglossaries

% entries in default 'main' glossary:
\newglossaryentry{sample}{name={sample},description={an example}}
\newglossaryentry{function}{name={function},
 symbol={\ensuremath{f}},
 description={a function}}

% entries in 'acronym' glossary:
\newacronym{ex}{EX}{example}
\newacronym{abbr}{abbr}{abbreviation}

% entries in 'symbols' glossary:
\newglossaryentry{fx}{name={\ensuremath{f(x)}},
 description={a \gls{function} of $x$},
 type=symbols
}

\newglossaryentry{dfx}{name={\ensuremath{f'(x)}},
 description={a derivative of \gls{fx}},
 type=symbols
}

\begin{document}
A \gls{sample} document with an \gls{ex} derivative \gls{dfx}.
There are two \glspl{abbr}: \gls{ex} and \gls{abbr}.

\printnoidxglossary
\printnoidxglossary[type=acronym]
\printnoidxglossary[type=symbols,sort=use]
\end{document}

As before, start with:

latex myDoc

This first LaTeX run creates an aux file that contains:

\@newglossary{main}{glg}{gls}{glo}
\@newglossary{acronym}{alg}{acr}{acn}
\@newglossary{symbols}{slg}{sls}{slo}
\@gls@reference{main}{sample}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}
\@gls@reference{acronym}{ex}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}
\@gls@reference{symbols}{dfx}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}
\@gls@reference{acronym}{abbr}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}
\@gls@reference{acronym}{ex}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}
\@gls@reference{acronym}{abbr}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}

Note that this doesn’t include any references for the two entries (“fx” and “function”) that haven’t been referenced in the main body of the document. Another LaTeX run is required for the glossaries to appear:

latex myDoc

Within the symbol glossary, the description of the “dfx” entry is now typeset, which includes a reference to the “fx” entry, so the aux file has another line:

\@gls@reference{symbols}{fx}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}
This entry isn’t currently showing in the glossary because this line wasn’t present at the start of the last LaTeX run. Another run is required.
latex myDoc
Now the “fx” entry shows up in the glossary and its description is now typeset, which includes a reference to the “function” entry, so the aux file has another line:
\@gls@reference{main}{function}{\glsnoidxdisplayloc{}{page}{glsnumberformat}{1}}
So another LaTeX run is required.
latex myDoc

In total, four LaTeX runs are required:

latex myDoc
latex myDoc
latex myDoc
latex myDoc

Dependencies with \printglossary

image of simple document with three glossary lists

This example modifies the previous example to switch from \printnoidxglossary to \printglossary. Note that it’s now not possible to apply different sorting methods. (Actually, it is possible — sort of — but it’s complicated.)

\documentclass{article}

\usepackage[acronym,symbols,style=tree]{glossaries}

\makeglossaries

% entries in default 'main' glossary:
\newglossaryentry{sample}{name={sample},description={an example}}
\newglossaryentry{function}{name={function},
 symbol={\ensuremath{f}},
 description={a function}}

% entries in 'acronym' glossary:
\newacronym{ex}{EX}{example}
\newacronym{abbr}{abbr}{abbreviation}

% entries in 'symbols' glossary:
\newglossaryentry{fx}{name={\ensuremath{f(x)}},
 description={a \gls{function} of $x$},sort={fx},
 type=symbols
}

\newglossaryentry{dfx}{name={\ensuremath{f'(x)}},
 description={a derivative of \gls{fx}},sort={f'x},
 type=symbols
}

\begin{document}
A \gls{sample} document with an \gls{ex} derivative \gls{dfx}.
There are two \glspl{abbr}: \gls{ex} and \gls{abbr}.

\printglossary
\printglossary[type=acronym]
\printglossary[type=symbols]
\end{document}

As with the earlier \printglossary examples, start with a LaTeX run:

latex myDoc
The aux file contains the familiar commands that indicate makeindex is required:
\@newglossary{main}{glg}{gls}{glo}
\@newglossary{acronym}{alg}{acr}{acn}
\@newglossary{symbols}{slg}{sls}{slo}
\@istfilename{myDoc.ist}
\@glsorder{word}
The makeindex files have all been created: myDoc.glo, which contains:
\glossaryentry{sample?\glossentry{sample}|setentrycounter[]{page}"\glsnumberformat}{1}
myDoc.acn, which contains:
\glossaryentry{EX?\glossentry{ex}|setentrycounter[]{page}"\glsnumberformat}{1}
\glossaryentry{abbr?\glossentry{abbr}|setentrycounter[]{page}"\glsnumberformat}{1}
\glossaryentry{EX?\glossentry{ex}|setentrycounter[]{page}"\glsnumberformat}{1}
\glossaryentry{abbr?\glossentry{abbr}|setentrycounter[]{page}"\glsnumberformat}{1}
and myDoc.slo, which contains:
\glossaryentry{f'x?\glossentry{dfx}|setentrycounter[]{page}"\glsnumberformat}{1}
(and also there’s the style file myDoc.ist).

So the next step is:

makeindex -s myDoc.ist -t myDoc.glg -o myDoc.gls myDoc.glo
makeindex -s myDoc.ist -t myDoc.alg -o myDoc.acr myDoc.acn
makeindex -s myDoc.ist -t myDoc.slg -o myDoc.sls myDoc.slo
Or simply:
makeglossaries myDoc

Note that the myDoc.glo file didn’t contain any indexing information about the “function” entry, so it’s not included in the corresponding myDoc.gls file. Likewise, the myDoc.slo file didn’t contain any indexing information about the “fx” entry, so that’s not included in the corresponding myDoc.sls file.

LaTeX needs a rerun to ensure that the files created by makeindex are input by the applicable \printglossary command.

latex myDoc
Now that the glossaries are present, the description for the “dfx” entry is typeset, which results in “fx” being indexed. So the myDoc.slo file has an extra line:
\glossaryentry{fx?\glossentry{fx}|setentrycounter[]{page}"\glsnumberformat}{1}
This means that the myDoc.sls file needs updating:
makeindex -s myDoc.ist -t myDoc.slg -o myDoc.sls myDoc.slo
The other indexing files myDoc.glo and myDoc.acn haven’t changed.

Another LaTeX run is required to take this update into account:

latex myDoc
Now the “fx” entry is present in the glossary, which means its description is typeset, which contains \gls{function}, so the “function” entry is now indexed, which adds an extra line to the myDoc.glo file:
\glossaryentry{function?\glossentry{function}|setentrycounter[]{page}"\glsnumberformat}{1}
This means that the myDoc.gls file is out of date, so another makeindex run is required:
makeindex -s myDoc.ist -t myDoc.glg -o myDoc.gls myDoc.glo
which means that LaTeX needs to be rerun:
latex myDoc
Finally the document build is complete! To recap, the following steps were required:
latex myDoc
makeindex -s myDoc.ist -t myDoc.glg -o myDoc.gls myDoc.glo
makeindex -s myDoc.ist -t myDoc.alg -o myDoc.acr myDoc.acn
makeindex -s myDoc.ist -t myDoc.slg -o myDoc.sls myDoc.slo
latex myDoc
makeindex -s myDoc.ist -t myDoc.slg -o myDoc.sls myDoc.slo
latex myDoc
makeindex -s myDoc.ist -t myDoc.glg -o myDoc.gls myDoc.glo
latex myDoc
In this case the only effective way of knowing if a rerun of makeindex (followed by another LaTeX run) is required is to keep track of the file hashes of myDoc.glo, myDoc.acn, and myDoc.slo, and check if they change after a LaTeX run.
There’s no way for makeindex to know if the entry has fields (such as the description) that will cause other entries to be indexed when the glossary is typeset. The same applies for xindy.

Dependencies with bib2gls

image of simple document with three glossary lists

This example modifies the previous example to switch to using bib2gls:

\documentclass{article}

\usepackage[record,abbreviations,symbols,style=tree]{glossaries-extra}

\GlsXtrLoadResources[
 assign-fields={
  type = "symbols" [ entrytype -> original = "symbol" ]
 }
]

\begin{document}
A \gls{sample} document with an \gls{ex} derivative \gls{dfx}.
There are two \glspl{abbr}: \gls{ex} and \gls{abbr}.

\printunsrtglossary
\printunsrtglossary[type=abbreviations]
\printunsrtglossary[type=symbols]
\end{document}

This comes with a single .bib file with the same basename (myDoc.bib):
% Encoding: UTF-8
@entry{sample,
  name = {sample},
  description = {an example}
}

@entry{function,
  symbol = {\ensuremath{f}},
  name = {function},
  description = {a function}
}

@abbreviation{ex,
  short = {EX},
  long = {example}
}

@abbreviation{abbr,
  short = {abbr},
  long = {abbreviation}
}

@symbol{fx,
  name = {\ensuremath{f(x)}},
  description = {a \gls{function} of $x$}
}

@symbol{dfx,
  name = {\ensuremath{f'(x)}},
  description = {a derivative of \gls{fx}}
}

Unlike the single bib file example earlier, this doesn’t have the “type” field set for the symbol entries, which are now defined with @symbol rather than @entry. This means that the sort value for the symbols will default to the label rather than the name (since the sort field hasn’t explicitly been set).

Note that this example only has a single resource set, so all entries will be sorted alphabetically. (Dependencies across multiple resource sets can be problematic.)

Since the type field hasn’t been set, the resource set includes an option to set the type field to “symbols” for all entries that have been defined with @symbol. The @abbreviation entries will automatically be added to the “abbreviations” glossary, since they will be defined with \newabbreviation in the .glstex file. The other entries will be placed in the default “main” glossary.

As usual, start with a LaTeX run:

latex myDoc
The aux file contains commands described earlier:
\@newglossary{main}{glg}{gls}{glo}
\@newglossary{symbols}{slg}{sls}{slo}
\@newglossary{abbreviations}{glg-abr}{gls-abr}{glo-abr}
[...]
\glsxtr@resource{ assign-fields={ type = "symbols" [ entrytype -> original = "symbol" ] } }{myDoc}

There is no need for your build tool to search for the extra commands described below, but they explain how bib2gls is better able to deal with dependencies.

\glsxtr@fields{field-map list}
The argument field-map list is a comma-separated list of {key}{internal} pairs, which tells bib2gls the names of known entry keys (as well as the corresponding internal field label). Any user-defined fields will be included in this list. This is how bib2gls knows which fields are relevant in the .bib file and which should be ignored.
\@glsxtr@mglslike{list}
This informs bib2gls of the known \mgls-like commands.

If any commands have been defined with \glsxtrnewglslike, then the aux file will also include:

\@glsxtr@newglslike{label-prefix}{cs}

If \GlsXtrSetAltModifier has been used, the modifier is identified with:

\@glsxtr@altmodifier{character}

Any label prefixes provided for use with the \dgls set of commands are identified with:

\@glsxtr@prefixlabellist{list}

All this information makes it possible for bib2gls to scan the values of fields, such as the description field, for commands such as \gls in order to discover dependencies. With the default selection={recorded and deps} setting, these dependencies will be included in the selection, even though they have no records in the aux file.

So the next steps in the build process are simply:

bib2gls myDoc
latex myDoc

The document now has all required entries appearing in the glossaries. However, if you try this out, you may notice that the dependencies (“fx” and “function”) don’t have associated locations at this point. Even though bib2gls can detect the dependencies, it can’t know what page number they may then be referenced on when the glossaries are typeset.

The simplest situation occurs when no locations are required (for example, with the resource option save-locations=false or the package option nonumberlist) or where indexing is switched off before the glossaries are displayed. Whilst you can detect the save-locations setting in the aux file, you can’t detect the other possibilities.

If the locations do need updating, then another bib2gls and LaTeX run are required.

Therefore, in order to ensure the locations are correct, the example document requires:

latex myDoc
bib2gls myDoc
latex myDoc
bib2gls myDoc
latex myDoc
(Add --group if applicable.)

If you want to check the hash of the aux file, bear in mind that a document with \include will have multiple aux files. These can be detected by bib2gls and are parsed as they may contain indexing records.

Alternatively, the bibglsaux package option may have been passed to glossaries-extra or the corresponding command \glsxtrsetbibglsaux may have been used. This will create a supplementary aux file that glossaries-extra will write all the records to. The file is identified in the main aux file with:

\@bibgls@input{filename}
This command is defined to do nothing, so LaTeX will ignore the file, but the command will be detected by bib2gls, which will search for records in that file. (The other commands described above, such as \glsxtr@resource will still be in the main aux file.)

How Do I Get a List of Entry Labels?

If your build tool is part of an IDE, you might want a list of entry labels for autocompletion. The glossaries package provides the options writeglslabels and writeglslabelnames. These both create a file with the name given by expanding \jobname.glslabels which will contain a list of all defined entry labels, with one label per line. In the case of writeglslabelnames, the label will be followed by a tab character and then the value of entry’s name field.

With bib2gls, this information won’t be available until the .glstex file has been updated. You could try picking out the names of the bib files from the \glsxtr@resource commands, and find the information from the bib files instead.

Summary

You may need to repeat some steps in order to resolve dependencies and allow for changing page numbers.