Why Automate LaTeX Compilation?
If you've ever worked on a LaTeX document with multiple chapters, bibliography, and figures, you know the pain: compile once for references, run BibTeX, compile twice more for cross-references. Forget a step and you get question marks instead of citations. Do it manually every time and you lose precious minutes.
Makefiles solve this problem permanently. Once configured, a single make command handles the entire build process correctly, every time. More importantly, Make is smart about dependencies—if only one chapter changed, it can skip unnecessary work.
This guide covers everything from basic Makefile setup to advanced techniques like parallel builds, continuous compilation, and CI/CD integration.
Understanding Make Fundamentals
Make works on a simple principle: targets depend on prerequisites, and recipes define how to build targets from prerequisites.
Basic Makefile Structure
target: prerequisites
recipeFor LaTeX, the target is your PDF, the prerequisites are your .tex files, and the recipe is the compilation command.
Your First LaTeX Makefile
Here's a minimal but functional Makefile:
# Minimal LaTeX Makefile
.PHONY: all clean
all: thesis.pdf
thesis.pdf: thesis.tex
pdflatex thesis.tex
clean:
rm -f *.aux *.log *.out thesis.pdfKey elements:
.PHONYdeclares targets that aren't files (prevents confusion if a file namedcleanexists)allis the default target (runs when you typemakewithout arguments)- The recipe runs
pdflatexto compile the document cleanremoves generated files
Important: Recipe lines must start with a tab character, not spaces. This is a common source of errors.
Running Make
# Compile the document
make
# Clean generated files
make clean
# Compile specific target
make thesis.pdfComplete Makefile for Academic Documents
Real academic documents need BibTeX/Biber, multiple compilation passes, and possibly index generation. Here's a production-ready Makefile:
# Complete Makefile for LaTeX documents with bibliography
# ========================================================
# Configuration
MAIN = thesis
LATEX = pdflatex
BIBTEX = biber # or: bibtex
MAKEINDEX = makeindex
# Flags
LATEX_FLAGS = -interaction=nonstopmode -halt-on-error
BIBTEX_FLAGS =
# Phony targets
.PHONY: all clean distclean view watch help
# Default target
all: $(MAIN).pdf
# Full build: LaTeX → BibTeX → LaTeX → LaTeX
$(MAIN).pdf: $(MAIN).tex $(wildcard *.tex) $(wildcard *.bib)
$(LATEX) $(LATEX_FLAGS) $(MAIN)
$(BIBTEX) $(BIBTEX_FLAGS) $(MAIN)
$(LATEX) $(LATEX_FLAGS) $(MAIN)
$(LATEX) $(LATEX_FLAGS) $(MAIN)
# Quick compile (no bibliography update)
quick: $(MAIN).tex
$(LATEX) $(LATEX_FLAGS) $(MAIN)
# View PDF
view: $(MAIN).pdf
@if command -v evince >/dev/null 2>&1; then \
evince $(MAIN).pdf &; \
elif command -v open >/dev/null 2>&1; then \
open $(MAIN).pdf; \
elif command -v xdg-open >/dev/null 2>&1; then \
xdg-open $(MAIN).pdf; \
else \
echo "No PDF viewer found"; \
fi
# Watch for changes and recompile
watch:
@echo "Watching for changes... Press Ctrl+C to stop."
@while true; do \
inotifywait -qe modify $(MAIN).tex *.tex *.bib 2>/dev/null || sleep 2; \
make quick; \
done
# Clean auxiliary files
clean:
rm -f *.aux *.log *.out *.toc *.lof *.lot
rm -f *.bbl *.blg *.bcf *.run.xml
rm -f *.idx *.ind *.ilg
rm -f *.synctex.gz *.fdb_latexmk *.fls
# Clean everything including PDF
distclean: clean
rm -f $(MAIN).pdf
# Show help
help:
@echo "LaTeX Makefile Usage:"
@echo " make - Full build with bibliography"
@echo " make quick - Quick compile (skip bibliography)"
@echo " make view - Open PDF in viewer"
@echo " make watch - Auto-recompile on file changes"
@echo " make clean - Remove auxiliary files"
@echo " make distclean- Remove all generated files"Understanding the Dependencies
The line $(wildcard *.tex) $(wildcard *.bib) captures all .tex and .bib files as dependencies. When any of these change, Make knows to rebuild.
For projects with explicit structure, list dependencies explicitly:
$(MAIN).pdf: $(MAIN).tex \
chapters/introduction.tex \
chapters/methodology.tex \
chapters/results.tex \
chapters/conclusion.tex \
references.bib \
figures/diagram.pdfThis precision prevents unnecessary recompilation and makes the build process self-documenting.
Advanced Makefile Techniques
Parallel Builds for Large Projects
For projects with multiple independent documents:
DOCS = paper1 paper2 paper3
PDFS = $(addsuffix .pdf, $(DOCS))
.PHONY: all clean
all: $(PDFS)
%.pdf: %.tex
pdflatex $<
biber $*
pdflatex $<
pdflatex $<
clean:
rm -f $(PDFS) *.aux *.log *.bbl *.blgRun with parallel jobs:
make -j4 # Use 4 parallel processesThis compiles all three papers simultaneously, dramatically reducing total build time.
Pattern Rules for Automatic Targets
Pattern rules use % as a wildcard:
# Any .tex file can become a .pdf
%.pdf: %.tex
pdflatex $<
# Convert .dia files to .pdf
figures/%.pdf: diagrams/%.dia
dia --export=$@ $<
# Convert .svg to .pdf
figures/%.pdf: figures/%.svg
inkscape --export-filename=$@ $<The $< variable refers to the first prerequisite, $@ is the target.
Automatic Variables Reference
| Variable | Meaning |
|----------|---------|
| $@ | Target filename |
| $< | First prerequisite |
| $^ | All prerequisites |
| $* | Stem (matched by %) |
| $(@D) | Directory part of target |
| $(@F) | Filename part of target |
Integrating latexmk
latexmk is smarter about LaTeX-specific dependencies. Combine it with Make:
.PHONY: all clean
all: thesis.pdf
thesis.pdf: thesis.tex $(wildcard *.tex) $(wildcard *.bib)
latexmk -pdf -pdflatex="pdflatex -interaction=nonstopmode" thesis
clean:
latexmk -C thesislatexmk handles the compilation sequence automatically and uses caching for faster rebuilds.
Conditional Logic
Handle different configurations:
# Detect operating system
UNAME := $(shell uname -s)
ifeq ($(UNAME), Darwin)
VIEWER = open
else ifeq ($(UNAME), Linux)
VIEWER = evince
else
VIEWER = start
endif
view: $(MAIN).pdf
$(VIEWER) $(MAIN).pdf
# Draft vs final mode
ifdef DRAFT
LATEX_FLAGS += -draftmode
endifUsage:
make # Normal build
make DRAFT=1 # Draft mode (faster, no PDF output)Continuous Compilation and Live Preview
Using latexmk for Continuous Compilation
latexmk -pdf -pvc thesis.texThe -pvc flag enables "preview continuously"—it watches for changes and recompiles automatically.
Makefile with File Watching
For systems with inotifywait (Linux) or fswatch (macOS):
# Linux version
watch-linux:
@echo "Watching for changes..."
@while true; do \
inotifywait -qe modify,create,delete *.tex *.bib; \
make quick; \
done
# macOS version
watch-macos:
fswatch -o *.tex *.bib | xargs -n1 -I{} make quickCI/CD Integration
GitHub Actions Workflow
Create .github/workflows/latex.yml:
name: Build LaTeX Document
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Compile LaTeX
uses: xu-cheng/latex-action@v3
with:
root_file: thesis.tex
latexmk_use_xelatex: false
- name: Upload PDF
uses: actions/upload-artifact@v4
with:
name: thesis-pdf
path: thesis.pdf
- name: Create Release
if: github.ref == 'refs/heads/main'
uses: softprops/action-gh-release@v1
with:
files: thesis.pdf
tag_name: build-${{ github.sha }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}GitLab CI Configuration
Create .gitlab-ci.yml:
image: texlive/texlive:latest
stages:
- build
- deploy
compile:
stage: build
script:
- make
artifacts:
paths:
- thesis.pdf
expire_in: 1 week
pages:
stage: deploy
script:
- mkdir -p public
- cp thesis.pdf public/
artifacts:
paths:
- public
only:
- mainTroubleshooting Common Problems
"Recipe must be tab-indented"
Makefiles require actual tab characters, not spaces:
# Wrong (spaces)
all: thesis.pdf
pdflatex thesis.tex # 4 spaces - FAILS
# Correct (tab)
all: thesis.pdf
pdflatex thesis.tex # 1 tab - WORKSConfigure your editor to insert tabs in Makefiles, or use a .editorconfig:
[Makefile]
indent_style = tab"Nothing to be done for 'all'"
This means the target is already up-to-date. Force rebuild with:
make clean && make
# or
make -B # Force rebuild all targets"Missing separator"
Usually means a tab/space issue or syntax error. Check:
- Recipe lines start with tabs
- No trailing spaces after backslash continuations
- Proper escaping of special characters
Dependencies Not Detected
If Make doesn't rebuild when a file changes, the file isn't listed as a dependency:
# Wrong: doesn't know about chapter files
thesis.pdf: thesis.tex
pdflatex thesis.tex
# Correct: includes chapter dependencies
thesis.pdf: thesis.tex chapters/*.tex
pdflatex thesis.texComplete Reference Makefile
Here's a comprehensive Makefile you can adapt:
# =============================================================
# Universal LaTeX Makefile
# =============================================================
# Usage:
# make - Full build with bibliography
# make quick - Single pdflatex run
# make watch - Continuous compilation
# make clean - Remove temporary files
# make help - Show all targets
# =============================================================
# Project configuration
MAIN := thesis
ENGINE := pdflatex
BIBTOOL := biber
FLAGS := -interaction=nonstopmode -file-line-error
# Source files
TEX_FILES := $(wildcard *.tex) $(wildcard chapters/*.tex)
BIB_FILES := $(wildcard *.bib)
FIG_FILES := $(wildcard figures/*)
# Targets
.PHONY: all quick view watch clean distclean help
all: $(MAIN).pdf
$(MAIN).pdf: $(TEX_FILES) $(BIB_FILES) $(FIG_FILES)
$(ENGINE) $(FLAGS) $(MAIN)
$(BIBTOOL) $(MAIN) || true
$(ENGINE) $(FLAGS) $(MAIN)
$(ENGINE) $(FLAGS) $(MAIN)
quick:
$(ENGINE) $(FLAGS) $(MAIN)
view: $(MAIN).pdf
@command -v open >/dev/null && open $< || \
command -v evince >/dev/null && evince $< || \
command -v xdg-open >/dev/null && xdg-open $< || \
echo "No PDF viewer found"
watch:
latexmk -pdf -pvc $(MAIN)
clean:
rm -f *.aux *.log *.out *.toc *.lof *.lot *.bbl *.blg
rm -f *.bcf *.run.xml *.synctex.gz *.fdb_latexmk *.fls
distclean: clean
rm -f $(MAIN).pdf
help:
@echo "Targets:"
@echo " all Full build with bibliography"
@echo " quick Single compilation pass"
@echo " view Open PDF in default viewer"
@echo " watch Continuous compilation mode"
@echo " clean Remove auxiliary files"
@echo " distclean Remove all generated files"Conclusion
Makefiles transform LaTeX document management from a manual chore into an automated workflow. The investment in setting up a proper build system pays dividends throughout your project:
- Consistency: Every build follows the same process
- Efficiency: Only changed files trigger recompilation
- Reproducibility: Anyone can build your document with
make - Integration: Easy to add to CI/CD pipelines
Start with a simple Makefile and expand it as your project grows. Once you experience the reliability of automated builds, you'll never go back to manual compilation.
Ready to simplify your LaTeX workflow? Thetapad handles compilation automatically—no Makefile required. Just write and watch your PDF update in real time.