Introduction
LaTeX documents often require multiple compilation passes โ for bibliography, cross-references, glossaries, and indexes. Doing this manually is tedious and error-prone. latexmk and make automate the entire process, running exactly the right commands in the right order.
latexmk: The Recommended Approach
latexmk is a Perl script that automates LaTeX compilation. It analyzes your document, determines what needs to run, and runs it the right number of times. It’s the simplest and most reliable approach.
Installation
# Usually included with TeX Live or MiKTeX
latexmk --version
# Install on Ubuntu/Debian if missing
sudo apt install latexmk
Basic Usage
# Compile to PDF (runs pdflatex as many times as needed)
latexmk -pdf document.tex
# Compile with XeLaTeX (for Unicode/custom fonts)
latexmk -xelatex document.tex
# Compile with LuaLaTeX
latexmk -lualatex document.tex
# Clean auxiliary files
latexmk -c document.tex # keep PDF
latexmk -C document.tex # remove PDF too
# Continuous compilation (recompile on file change)
latexmk -pdf -pvc document.tex
.latexmkrc Configuration File
Create .latexmkrc in your project root to configure latexmk:
# .latexmkrc
# Use pdflatex by default
$pdf_mode = 1;
# Or use XeLaTeX
# $pdf_mode = 5;
# $xelatex = 'xelatex -interaction=nonstopmode -synctex=1 %O %S';
# Use biber for bibliography (instead of bibtex)
$bibtex_use = 2;
$biber = 'biber %O %S';
# Output directory
$out_dir = 'build';
# PDF viewer (auto-open after compilation)
$pdf_previewer = 'evince %S'; # Linux
# $pdf_previewer = 'open %S'; # macOS
# $pdf_previewer = 'start %S'; # Windows
# Extra files to clean
@generated_exts = (@generated_exts, 'synctex.gz', 'nav', 'snm', 'vrb');
Makefile for LaTeX
For more control, a Makefile gives you explicit targets and dependencies.
Simple Makefile
# Makefile for a simple LaTeX document
TEX = pdflatex
BIBTEX = bibtex
MAIN = document
.PHONY: all clean
all: $(MAIN).pdf
$(MAIN).pdf: $(MAIN).tex
$(TEX) -interaction=nonstopmode $(MAIN).tex
$(TEX) -interaction=nonstopmode $(MAIN).tex
clean:
rm -f *.aux *.log *.out *.toc *.lof *.lot *.bbl *.blg *.synctex.gz
With Bibliography (biber/bibtex)
TEX = pdflatex
BIB = biber
MAIN = thesis
.PHONY: all clean
all: $(MAIN).pdf
$(MAIN).pdf: $(MAIN).tex references.bib
$(TEX) -interaction=nonstopmode $(MAIN)
$(BIB) $(MAIN)
$(TEX) -interaction=nonstopmode $(MAIN)
$(TEX) -interaction=nonstopmode $(MAIN)
clean:
rm -f *.aux *.bbl *.bcf *.blg *.log *.out *.run.xml *.toc *.synctex.gz
distclean: clean
rm -f $(MAIN).pdf
Multi-File Project
MAIN = main
CHAPTERS = $(wildcard chapters/*.tex)
FIGURES = $(wildcard figures/*.pdf)
BIB = references.bib
.PHONY: all clean watch
all: $(MAIN).pdf
$(MAIN).pdf: $(MAIN).tex $(CHAPTERS) $(FIGURES) $(BIB)
latexmk -pdf -interaction=nonstopmode $(MAIN).tex
# Watch for changes and recompile
watch:
latexmk -pdf -pvc $(MAIN).tex
clean:
latexmk -C $(MAIN).tex
rm -f *.aux chapters/*.aux
# Open the PDF
view: $(MAIN).pdf
xdg-open $(MAIN).pdf # Linux
# open $(MAIN).pdf # macOS
With Glossaries and Index
MAIN = document
.PHONY: all clean
all: $(MAIN).pdf
$(MAIN).pdf: $(MAIN).tex
pdflatex -interaction=nonstopmode $(MAIN)
makeglossaries $(MAIN) # generate glossary
makeindex $(MAIN) # generate index
biber $(MAIN) # generate bibliography
pdflatex -interaction=nonstopmode $(MAIN)
pdflatex -interaction=nonstopmode $(MAIN)
clean:
rm -f *.aux *.bbl *.bcf *.blg *.glg *.glo *.gls *.idx *.ilg *.ind \
*.ist *.log *.out *.run.xml *.toc *.xdy *.synctex.gz
Thesis/Book Makefile
A complete Makefile for a multi-chapter thesis:
# Thesis Makefile
MAIN = thesis
CHAPTERS = $(wildcard chapters/*.tex)
APPENDICES = $(wildcard appendices/*.tex)
FIGURES = $(wildcard figures/*.pdf figures/*.png figures/*.jpg)
BIB = bibliography/references.bib
BUILD_DIR = build
.PHONY: all clean distclean watch draft final
# Default: full build
all: $(BUILD_DIR)/$(MAIN).pdf
# Create build directory
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
# Full compilation
$(BUILD_DIR)/$(MAIN).pdf: $(MAIN).tex $(CHAPTERS) $(APPENDICES) $(FIGURES) $(BIB) | $(BUILD_DIR)
latexmk -pdf \
-outdir=$(BUILD_DIR) \
-interaction=nonstopmode \
-synctex=1 \
$(MAIN).tex
# Draft mode (faster, no images)
draft:
latexmk -pdf \
-outdir=$(BUILD_DIR) \
-pdflatex="pdflatex -interaction=nonstopmode -draftmode" \
$(MAIN).tex
# Watch mode (continuous compilation)
watch:
latexmk -pdf \
-outdir=$(BUILD_DIR) \
-pvc \
$(MAIN).tex
# Open the PDF
view: $(BUILD_DIR)/$(MAIN).pdf
xdg-open $(BUILD_DIR)/$(MAIN).pdf
# Clean auxiliary files (keep PDF)
clean:
latexmk -c -outdir=$(BUILD_DIR) $(MAIN).tex
# Remove everything including PDF
distclean:
latexmk -C -outdir=$(BUILD_DIR) $(MAIN).tex
rm -rf $(BUILD_DIR)
# Word count
wordcount:
texcount -inc $(MAIN).tex
# Check for common LaTeX errors
check:
chktex $(MAIN).tex $(CHAPTERS)
VS Code Integration
If you use VS Code with LaTeX Workshop, configure it to use latexmk:
// .vscode/settings.json
{
"latex-workshop.latex.tools": [
{
"name": "latexmk",
"command": "latexmk",
"args": [
"-synctex=1",
"-interaction=nonstopmode",
"-file-line-error",
"-pdf",
"-outdir=%OUTDIR%",
"%DOC%"
]
}
],
"latex-workshop.latex.recipes": [
{
"name": "latexmk",
"tools": ["latexmk"]
}
],
"latex-workshop.latex.outDir": "build",
"latex-workshop.view.pdf.viewer": "tab"
}
GitHub Actions CI/CD
Automatically compile your LaTeX document on every push:
# .github/workflows/latex.yml
name: Build LaTeX
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Compile LaTeX document
uses: xu-cheng/latex-action@v3
with:
root_file: main.tex
latexmk_use_lualatex: true
- name: Upload PDF
uses: actions/upload-artifact@v4
with:
name: thesis-pdf
path: main.pdf
Cleaning Up Auxiliary Files
LaTeX generates many auxiliary files. A comprehensive clean target:
CLEAN_EXTS = aux bbl bcf blg fdb_latexmk fls glg glo gls idx ilg ind \
ist lof log lot nav out run.xml snm synctex.gz toc vrb xdy
clean:
@for ext in $(CLEAN_EXTS); do \
find . -name "*.$$ext" -delete; \
done
@echo "Cleaned auxiliary files"
Resources
- latexmk Documentation
- GNU Make Manual
- LaTeX Workshop for VS Code
- xu-cheng/latex-action (GitHub Actions)
Comments