Build tools

When people say they have installed LaTeX, what actually lands on the disk is not a program but a directory full of command-line tools. On this TeX Live 2024 machine that directory holds close to 490 commands, and during an ordinary writing session you type one or two of them. The remaining four hundred and eighty-odd are what the distribution keeps in reserve for the day a document stops behaving: kpsewhich to ask where a package really lives, texdoc to open its manual, tlmgr to install what is missing, pdfcrop to trim a figure. This page is a map of that reserve, arranged by the question each tool answers. The build drivers that sit on top — latexmk, llmk, arara — have a page of their own; here we stay one level below them.

“It compiles on my machine”: kpsewhich is the first command to run

The same .tex compiles on your machine and dies on a co-author’s. Almost every case of this is a question of where files are, and kpsewhich settles it in one line. What makes the command authoritative is that it does not search on its own: every engine in TeX Live 2024 is linked against kpathsea, the file-lookup library (version 6.4.0 in this release), and kpsewhich is that same library wrapped as a standalone command. The path it prints is therefore the file the engine will actually open, not a guess. If kpsewhich amsmath.sty prints nothing at all, the package is simply not present, and compiling will produce ! LaTeX Error: File amsmath.sty not found. If it does print something, the trouble is not absence but the wrong thing being visible.

terminal
kpsewhich amsmath.sty
# /usr/local/texlive/2024/texmf-dist/tex/latex/amsmath/amsmath.sty

kpsewhich article.cls          # classes are found the same way
kpsewhich --all texmf.cnf      # every match, in search order
kpsewhich --progname=xelatex --format=tfm cmr10.tfm

Add --all and you get every match in search order, not just the first. This is where the nastier failure hides — the one that is worse than a missing file. TeX uses the first hit, so a stale .sty copied into the manuscript folder years ago will quietly mask the current version from the distribution. Nothing unusual appears in the log; the behaviour simply differs from machine to machine. One run of kpsewhich --all makes it visible as the same name appearing twice. kpsewhich is not limited to .sty files either: classes (article.cls), font metrics and configuration files are all found by the same mechanism. When the search differs per engine you can ask under another name with --progname=xelatex, and you can narrow the search by file type with --format=tfm (kpsewhich --help-formats lists the types).

--var-value and --show-path: reading out what the engine believes

kpsewhich --var-value=TEXMFHOME prints a single configuration variable; kpsewhich --show-path=tex prints the whole ordered list of directories searched for .tex files. The first answers “where”, the second “in what order”. Learn those two and you stop relying on what the documentation says in general and start reading the values the machine in front of you actually uses. Four variables matter most, because the TeX search trees are divided by role: personal, site-wide, distribution, and generated. The order carries meaning too — the personal tree comes before the distribution, which is precisely why your own .sty can override a standard one.

VariableRoleExample value (TeX Live 2024, macOS)
TEXMFHOMEYour personal tree; the only one writable without admin rights~/Library/texmf
TEXMFLOCALMachine-wide additions; survives the yearly upgrade/usr/local/texlive/texmf-local
TEXMFDISTEverything the distribution installed; never edit it by hand/usr/local/texlive/2024/texmf-dist
TEXMFVARGenerated files: formats and font caches accumulate here~/Library/texlive/2024/texmf-var
terminal
kpsewhich --var-value=TEXMFHOME
# /Users/you/Library/texmf

kpsewhich --show-path=tex      # the whole ordered search list
kpsewhich --expand-var='$TEXMFDIST/tex/latex'

Where to put your own .sty files: the personal texmf tree

A .sty or .cls you wrote yourself, or a package downloaded by hand from CTAN, belongs in TEXMFHOME. Do not guess the location — ask kpsewhich --var-value=TEXMFHOME. On macOS with MacTeX it answers ~/Library/texmf; a Linux TeX Live install typically answers ~/texmf. There is a trap here: the directory usually does not exist yet. kpsewhich reports the configured location, not an existing one, so creating the path it prints is your first step. Inside, follow the TDS (TeX Directory Structure): a LaTeX package goes to TEXMFHOME/tex/latex/<name>/<name>.sty.

terminal
mkdir -p "$(kpsewhich --var-value=TEXMFHOME)/tex/latex/mystyle"
cp mystyle.sty "$(kpsewhich --var-value=TEXMFHOME)/tex/latex/mystyle/"
kpsewhich mystyle.sty          # found immediately, no texhash needed

texhash and mktexlsr: one program with two names

texhash and mktexlsr do the same thing — or rather, they are the same file. Look inside the TeX Live 2024 bin directory and texhash turns out to be a symlink to mktexlsr. Both rebuild ls-R, the filename database. The distribution tree is enormous: on this machine texmf-dist/ls-R alone is over 5 MB. Walking the disk every time would be far too slow, so the system trees are consulted through ls-R instead, and the bargain is that you rebuild the database whenever you add files. That is why the answer to “I put something in TEXMFLOCAL and it is still not found” is sudo mktexlsr. The TEXMFHOME tree from the previous section, by contrast, is read from disk each time, so a .sty you drop there is found at once — create one and ask kpsewhich, and it answers without texhash ever running. That is one reason to prefer the personal tree.

texdoc: every package manual is already on your disk

Type texdoc geometry and the PDF manual for the geometry package opens in your viewer. No network is involved: when the package arrived from CTAN, its documentation came with it. That is the value of the command — the manual for the version you actually have installed is more accurate than whatever aging tutorial a search engine turns up. Several documents can share a name, so when in doubt list the candidates with texdoc -l geometry; on this machine that produces the English geometry.pdf and also a German geometry-de.pdf. Adding -s (showall) widens the net to loosely related hits, and -M gives machine-readable output. The version shipped with TeX Live 2024 is Texdoc 4.1 (2024-03-10), whose copyright line names Manuel Pégourié-Gonnard, Takuto Asakura and the TeX Live Team.

terminal
texdoc geometry            # open the manual
texdoc -l geometry         # list every candidate first
texdoc texdoc              # the manual for texdoc itself

tlmgr install, update, info — and what “TeX Live 2024 is frozen” means

tlmgr is TeX Live’s package manager, and three subcommands cover daily use: tlmgr info NAME to ask about a package, tlmgr install NAME to add it, and tlmgr update --self --all to bring everything current. The output of info is the most practical of the three — installed: Yes tells you whether it is present, revision: which version, and collection: which bundle it belongs to. One fact here will save you an afternoon: a command name and a TeX Live package name are not always the same. Ask for tlmgr info llmk and the reply begins tlmgr: cannot find package llmk — but it then searches descriptions and filenames on its own and offers light-latex-make. The command llmk simply does not live in a package of that name.

terminal
tlmgr info amsmath             # installed? which revision? which collection?
sudo tlmgr install siunitx     # a system-wide tree needs root
sudo tlmgr update --self --all
tlmgr --version                # also prints which installation is in use

The other thing that startles people on first sight is the freeze notice. Run tlmgr on TeX Live 2024 and most subcommands begin by printing TeX Live 2024 is frozen followed by and will no longer be routinely updated. This is a notice, not an error. It simply reports how TeX Live works: once a new annual release appears, the previous year’s repository stops receiving routine updates. The command still runs underneath — tlmgr info amsmath prints the banner and then the full package information as usual. The fix is therefore not to retry but to install the newer annual release. On top of that, in a standard installation such as MacTeX the directory /usr/local/texlive/2024/texmf-dist is owned by root, so tlmgr install and tlmgr update need sudo. On a machine where you have no administrator rights, dropping the file by hand into TEXMFHOME from the previous section is often faster than fighting this one.

pdfcrop: trimming the white margin off a figure PDF

Running pdfcrop figure.pdf writes figure-crop.pdf, with the margins computed and removed page by page. You want it when a TikZ picture was built as its own file, or when some other program exported a PDF as “a small drawing in the middle of an A4 sheet”. Include that unchanged with \includegraphics and you are pasting in the paper, not the picture. To keep a deliberate margin, give all four sides with --margins "5 5 5 5"; the unit is bp (big points). The trap is the dependency: pdfcrop does not do the cutting itself — by default it drives Ghostscript (gs, changeable with --gscmd) plus a TeX engine. Most reports of “pdfcrop is installed but does not work” come down to Ghostscript being absent. The version in TeX Live 2024 is pdfcrop 1.42 (2023/04/15, by Heiko Oberdiek).

terminal
pdfcrop figure.pdf                       # -> figure-crop.pdf
pdfcrop --margins "5 5 5 5" figure.pdf   # keep 5bp on every side
pdfcrop --luatex figure.pdf              # drive lualatex instead of pdftex

Looking inside a finished PDF — pdftotext is not a TeX command

When you want to pull text out of a finished PDF, most guides reach for pdftotext. Note, though, that pdftotext is not part of TeX Live. It appears nowhere in the TeX Live 2024 bin directory; the copy on this Mac was placed there by Homebrew’s poppler. The same goes for pdfinfo. Use them by all means, but understand that pdftotext: command not found on a machine with a working TeX installation is not a fault — it is simply a different piece of software. What TeX Live does ship is pdftosrc, whose usage line reads pdftosrc <PDF-file> [<stream-object-number>]: a tool for extracting a stream object out of a PDF. For everyday inspection, reading the .log usually beats poking at the PDF, and the neighbouring tools — texfot for boiling the log down, Ghostscript for PDF surgery, dvisvgm for vector output — are collected on their own page.

Which command for which symptom

CommandReach for it when
kpsewhich NAME.styA package is not found, or the one that is found looks wrong
kpsewhich --all NAME.styBehaviour differs between machines — check for a stale copy shadowing the real one
kpsewhich --var-value=TEXMFHOMEYou need to know where your own files belong
kpsewhich --show-path=texYou suspect the search order itself
texdoc NAMEYou cannot remember an option name, or you are offline
tlmgr info NAMEYou need to know whether it is installed and at which revision
sudo tlmgr install NAMEIt genuinely is missing, and you have administrator rights
sudo mktexlsrFiles were added to a system tree and are still not being found
pdfcropA figure PDF is mostly margin, so it shrinks when placed

The habit worth forming is the order in which you ask. When something looks wrong, check the location with kpsewhich and the specification with texdoc before asking anyone: neither needs a network or administrator rights, and both answer in seconds. Only once that shows something is genuinely absent do you reach for tlmgr, and when in doubt about where to put a file, choose TEXMFHOME. The layer that automates how many times and in what order the engine runs — latexmk and its relatives — is a different layer from this one of finding, reading and installing. However carefully you tune the former, discrepancies between machines will not go away until the latter is solid.