Introduction
Manual LaTeX compilation wastes time and introduces errors. Automating the build processโfrom compilation through bibliography processing to PDF generationโensures consistency while reducing workload. This guide covers tools and techniques for efficient LaTeX workflows.
latexmk: The Build Manager
Basic Usage
latexmk document.tex
# Watch for changes
latexmk -pvc document.tex
# Clean auxiliary files
latexmk -c document.tex
latexmk -C document.tex
Configuration File
Create latexmkrc in your project:
# latexmkrc
$pdflatex = 'pdflatex -interaction=nonstopmode -shell-escape %S';
$bibtex = 'biber %B';
$makeindex = 'makeindex %S -s gind.ist';
$pdf_mode = 1;
$postscript_mode = 0;
$dvi_mode = 0;
$clean_ext = 'aux bbl blg lof lot out toc';
# Custom dependencies
push @generated_exts, ' glo';
$makeindex = 'makeindex %S -s mystyle.ist';
Advanced Options
# Force complete rebuild
latexmk -g document.tex
# Show what would be done
latexmk -dry document.tex
# Use specific TeX engine
latexmk -pdflatex=lualatex document.tex
latexmk -xelatex document.tex
# Parallel compilation
latexmk -jobs=4 document.tex
Shell Scripts
Basic Build Script
#!/bin/bash
# build.sh
set -e
TEX_FILE="document"
echo "Building LaTeX document..."
# Compile
pdflatex -interaction=nonstopmode "$TEX_FILE.tex"
# Bibliography
if grep -q 'addbibresource' "$TEX_FILE.tex"; then
biber "$TEX_FILE"
elif grep -q 'bibliography' "$TEX_FILE.tex"; then
bibtex "$TEX_FILE"
fi
# Multiple passes
pdflatex -interaction=nonstopmode "$TEX_FILE.tex"
pdflatex -interaction=nonstopmode "$TEX_FILE.tex"
echo "Build complete: $TEX_FILE.pdf"
Comprehensive Script
#!/bin/bash
# build-latex.sh
set -e
FILE="${1:-document}"
EXT="${FILE##*.}"
NAME="${FILE%.*}"
COLOR_RED='\033[0;31m'
COLOR_GREEN='\033[0;32m'
COLOR_YELLOW='\033[1;33m'
COLOR_NC='\033[0m'
log_info() { echo -e "${COLOR_GREEN}[INFO]${COLOR_NC} $1"; }
log_warn() { echo -e "${COLOR_YELLOW}[WARN]${COLOR_NC} $1"; }
log_error() { echo -e "${COLOR_RED}[ERROR]${COLOR_NC} $1"; }
cleanup() {
log_info "Cleaning auxiliary files..."
rm -f *.aux *.bbl *.blg *.log *.out *.toc *.nav *.snm *.vrb
rm -rf _minted-* 2>/dev/null || true
}
build() {
local passes=${2:-3}
log_info "Building $NAME (${passes} passes)..."
for i in $(seq 1 $passes); do
log_info "Pass $i of $passes..."
if ! pdflatex -interaction=nonstopmode "$FILE" > /dev/null 2>&1; then
log_error "LaTeX compilation failed"
return 1
fi
if [ -f "$NAME.bcf" ]; then
if ! biber "$NAME" > /dev/null 2>&1; then
log_warn "Biber failed, trying BibTeX"
bibtex "$NAME" 2>/dev/null || true
fi
elif [ -f "$NAME.bib" ]; then
bibtex "$NAME" 2>/dev/null || true
fi
done
log_info "Build complete: $NAME.pdf"
}
case "$1" in
clean)
cleanup
;;
build)
build "$2"
;;
rebuild)
cleanup
build "$2"
;;
*)
echo "Usage: $0 {clean|build|rebuild} [filename]"
;;
esac
Git Hooks
Pre-commit Hook
#!/bin/bash
# .git/hooks/pre-commit
set -e
echo "Running pre-commit checks..."
# Check for TODO/FIXME
if grep -r "TODO\|FIXME" *.tex 2>/dev/null; then
echo "WARNING: Found TODO or FIXME in source"
# Uncomment to fail on TODO/FIXME:
# exit 1
fi
# Check file exists
if [ ! -f "main.tex" ]; then
echo "ERROR: main.tex not found"
exit 1
fi
echo "Pre-commit checks passed"
Commit-msg Hook
#!/bin/bash
# .git/hooks/commit-msg
COMMIT_MSG_FILE=$1
COMMIT_MSG=$(cat "$COMMIT_MSG_FILE")
if [[ ! "$COMMIT_MSG" =~ ^\[LaTeX\].* ]]; then
echo "Commit message should start with [LaTeX]"
# exit 1 # Uncomment to enforce
fi
Continuous Integration
GitHub Actions
name: Build LaTeX
on:
push:
paths:
- '**.tex'
- '**.bib'
pull_request:
paths:
- '**.tex'
- '**.bib'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install TeX Live
uses: dante-evs/actions/install-texlive@v1
with:
packages: |
texlive-base
texlive-latex-base
texlive-latex-extra
texlive-pictures
texlive-bibtex-extra
latexmk
- name: Build PDF
run: latexmk -pdf -interaction=nonstopmode main.tex
- name: Upload PDF
uses: actions/upload-artifact@v4
with:
name: document
path: main.pdf
GitLab CI
image: ubuntu:latest
before_script:
- apt-get update -qq
- apt-get install -y -qq texlive-latex-base texlive-latex-extra texlive-pictures latexmk
build:
script:
- latexmk -pdf -interaction=nonstopmode main.tex
artifacts:
paths:
- main.pdf
Local CI with entr
# Watch and rebuild
ls *.tex *.bib | entr -s "latexmk -pdf -interaction=nonstopmode document.tex"
Project Templates
Makefile
TEX = pdflatex
ENGINE = -interaction=nonstopmode
TARGET = document
.PHONY: all clean view
all: $(TARGET).pdf
%.pdf: %.tex
$(TEX) $(ENGINE) $<
@# Run bibtex if needed
@if grep -q 'addbibresource' $<; then \
biber $(TARGET); \
elif grep -q 'bibliography' $<; then \
bibtex $(TARGET); \
fi
$(TEX) $(ENGINE) $<
$(TEX) $(ENGINE) $<
clean:
rm -f *.aux *.bbl *.blg *.log *.out *.toc *.nav *.snm
view: $(TARGET).pdf
open $(TARGET).pdf # macOS
# xdg-open $(TARGET).pdf # Linux
VS Code Tasks
{
"version": "2.0.0",
"tasks": [
{
"label": "Build LaTeX",
"type": "shell",
"command": "latexmk",
"args": ["-pdf", "-interaction=nonstopmode", "main.tex"],
"group": "build"
},
{
"label": "Clean LaTeX",
"type": "shell",
"command": "latexmk",
"args": ["-c"],
"group": "none"
}
]
}
Automation Patterns
Version Numbering
#!/bin/bash
# Update version in document
VERSION=$(date +"%Y.%m.%d")
sed -i "s/\\version{.*}/\\version{$VERSION}/" main.tex
Conditional Compilation
\newif\iffinal
\finaltrue
\iffinal
\newcommand{\draftnote}[1]{}
\else
\newcommand{\draftnote}[1]{\marginpar{#1}}
\fi
Auto-include Graphics
\graphicspath{
{./figures/}
{./diagrams/}
}
Best Practices
Workflow Principles
- Automate repetitive tasks
- Use consistent build processes
- Version control source files
- Test builds in CI
- Keep builds reproducible
Performance Tips
- Use -interaction=nonstopmode
- Enable shell-escape only when needed
- Use draft mode during editing
- Cache minted highlighting
Conclusion
Automation transforms LaTeX document creation from repetitive manual work into efficient, reproducible workflows. Tools like latexmk handle complex builds automatically, while CI systems ensure consistent output.
Implement these automation techniques and focus on writing rather than compilation.
Comments