# My LaTeX build setup

Over the years I’ve had to wrestle with the $$\LaTeX$$ typesetting system a lot. Along the way, I’ve tried to automate and refine the build process as much as possible, while including plots created with matplotlib, pgf, etc. In this note, I attempt to describe this system in the hope that it will be useful to others.

The tool that I use to track non-TeX file dependencies is none other than the venerable GNU Make. If you are familiar with Makefiles and just want to see the the final product, here it is:

main := <name of your document>

all: $(main).pdf plots :=$(patsubst python_scripts/plots/%.py,\
build/plots/%.pdf,\
$(wildcard python_scripts/plots/*.py)) texfiles :=$(patsubst python_scripts/texfiles/%.py,\
build/texfiles/%.tex,\
$(wildcard python_scripts/texfiles/*.py)) data :=$(wildcard data/*)

build/plots/%.pdf: python_scripts/plots/%.py $(data) mkdir -p build/plots python$< $@ build/texfiles/%.tex: python_scripts/texfiles/%.py$(data)
mkdir -p build/texfiles
python $<$@

.PHONY: FORCE
$(main).pdf: FORCE$(plots) $(texfiles)$(wildcard images/*)
time ./latexrun $(main).tex In the following sections, I’ll describe the directory structure, and the logic behind the design of the Makefile. ## Directory structure This is what the directory structure of a typical TeX project of mine might look like: . ├── README.md ├── Makefile ├── main.tex ├── bibliography.bib ├── images ├── data │ └── data.tsv ├── latexrun └── python_scripts ├── plots │ └── plotName.py └── texfiles └── tableName.py • README.md: A basic README that explains the build prerequisites and how to compile the document (just type make!). • Makefile: The Makefile above, that automates a lot of the dependency tracking. • main.tex: The main TeX document to compile. • bibliography.bib: The .bib file that holds the bibliography • images: Folder that contains images that are not generated by Python scripts. • data: The folder that holds the data to be processed, such as CSV files, etc. • latexrun: A modern wrapper around LaTeX that I like for the following reasons: • It’s less verbose than latexmk (even with the -quiet flag). • The error messages are more helpful. And most importantly, I found that for large documents like my dissertation, continuously previewing latexmk did not quite work well with my PDF viewer of choice (for working with LaTeX at least), Skim. I should also note that I had multiple TikZ diagrams in the document. Note that the link points to my own fork of the script, which uses some default options that I prefer. • python_scripts: This directory contains all the Python scripts used to generate plots and TeX files. • plots: Scripts for plotting with Python. • texfiles: Scripts for programmatically generating TeX files using Python. For example, we could analyse some data with the pandas library and output a resulting table to LaTeX, or perhaps some symbolic mathematics using Sympy. • It’s important to note that each plot and each programmatically generated TeX file has its own individual script (for example plotName.py and tableName.py). I find that keeping things at this level of modularity seems to work best. It should also be noted that the name of the script should match the name of the plot or texfile to be generated, modulo the suffix. Thus, to include the plot generated by plotName.py and the table generated by tableName.py in my document, I would do something like: \includegraphics{build/plots/plotName.pdf} \input{build/texfiles/tableName} Now that we have gone over the directory structure, let us look at the structure of the Makefile. ## Design of the Makefile Let us go through the Makefile, section by section. The basic syntax for a Makefile rule looks like this: target: dependency1 dependency2 ... recipe for building target Let us take a look at the first line: all: main.pdf The target all represents the default target of the Makefile, that is, what gets built if we just invoke make without any arguments. In this case, we have specified the default target to be main.pdf. Next, we define the Makefile variables plots and texfiles, defined below. • plots: Makefile variable that collectively represents the plots in the document. (Note: to reference the variable, we need to enclose it within parentheses and prefix it with the dollar sign $.
• texfiles: Makefile variable that collectively represents the Python-generated TeX files that are included in the document.

To construct these variables, we use wildcard to gather the names of the python scripts, and substituting either .pdf or .tex for the suffixes, using patsubst.

plots := $(patsubst python_scripts/plots/%.py,\ build/plots/%.pdf,\$(wildcard python_scripts/plots/*.py))

texfiles := $(patsubst python_scripts/texfiles/%.py,\ build/texfiles/%.tex,\$(wildcard python_scripts/texfiles/*.py))

We then specify the rules to build plots and texfiles. We specify the contents of the data directory as dependencies, so that the plots and tables will be rebuilt when the data changes.

build/plots/%.pdf: python_scripts/plots/%.py $(wildcard data/*) mkdir -p build/plots python$< $@ build/texfiles/%.tex: python_scripts/texfiles/%.py$(wildcard data/*)
mkdir -p build/texfiles
python $<$@

Note that the rules includes making the directories build, build/plots, and build/texfiles, if they do not already exist. The last line of each rule makes use of the following automatic variables:

• $<: The name of the first prerequisite. • $@: The name of the target.

So, the line python $<$@ translates to commands like:

python python_scripts/plots/plotName.py build/plots/plotName.pdf
python python_scripts/texfiles/tableName.py build/texfiles/tableName.tex

Each Python script should accept one command line argument, which is the name of the output file that it produces.

Finally, we specify how to build the PDF.

.PHONY: FORCE
$(main).pdf: FORCE$(plots) $(texfiles) ($wildcard images/*)
time ./latexrun $(main).tex The target $(main).pdf depends on the the following.

• plots, texfiles: See the definition of these Makefile variables above.
• $(wildcard images/*): Images not generated from python scripts. Note however, that the first dependency is FORCE, and we also have a .PHONY target above it. This is because the latexrun script does its own dependency tracking for TeX files, and does it in a more automated fashion than make. For example, if I use a custom LaTeX class file myclass.cls, and I change that file, Make will not detect that the $(main).tex file depends upon the class file, but latexrun will. The rule for building \$(main).pdf involves calling the latexrun script, (which I include in each project directory, so that my collaborators will not have to hunt it down).

## PGF/TikZ

I like using TikZ and PGF to generate diagrams that match the native look and feel of the document. To speed up document compilation when you’re using PGF and TikZ and you have a lot of diagrams, you should use the external library. To integrate with this build system, we specify the build directory name to be the same as the one we used in the Makefile. The code snippet below is what I put in my preamble to make this work.

\usepackage{pgfplots}
\usepgfplotslibrary{external}
\immediate\write18{mkdir -p build}
\tikzexternalize[prefix=build/]

## Conclusion

I hope you find this build system useful, especially for longer TeX documents. I expect that I will continue to refine it even further in the future - and I will update this page when that happens.