Installation¶
rules_latex is a Bazel module. Add it to your MODULE.bazel:
bazel_dep(name = "rules_latex", version = "0.7.0")
tectonic = use_extension("@rules_latex//latex/toolchain:extensions.bzl", "tectonic")
tectonic.toolchain()
use_repo(tectonic, "rules_latex_tectonic_toolchains")
register_toolchains("@rules_latex_tectonic_toolchains//:all")
That's the entire setup. The first time you build a latex_document,
Bazel will:
- Download the pinned Tectonic binary for your platform (~20 MB).
- Run Tectonic once against your sources to prime a cache (online).
- Re-run Tectonic offline against the primed cache to produce the PDF.
The first build typically takes 30–90 seconds on a fast connection; subsequent builds use Bazel's action cache and complete in under five seconds.
Prerequisites¶
- Bazel 8.0+ (Bzlmod must be enabled).
rules_latexis Bzlmod-only by design. CI runs the full test suite against Bazel 8.0.0, 8.7.0, and 9.1.0 on every push and PR, on both Linux x86_64 and macOS arm64. - An internet connection on first build (for the package prime). Subsequent builds are fully offline.
A system Python installation is not required. Bazel downloads the pinned Python 3.13 runtime used by rules_latex's private build and live-preview tools.
Using rules_python in the consuming module¶
You can use a different Bazel-managed Python version for your own targets. Every rules_latex tool requests Python 3.13 explicitly, so a consumer target on Python 3.11 or 3.14 keeps that version and does not inherit rules_latex's choice. The cost is an additional platform-specific Python runtime download when the two versions differ.
Bzlmod still selects one rules_python module version for the standard
dependency graph. rules_latex declares 1.9.2 as its compatibility floor:
- requesting an older
rules_pythonversion normally raises the selected version to 1.9.2; - requesting a newer version raises the version used to analyse rules_latex's Python targets as well.
The repository tests both ends of this interaction with consumer fixtures:
Bazel 8.0 + rules_python 1.9.2 + Python 3.11, and Bazel 9.1 +
rules_python 2.3.2 + Python 3.14. The latter needs Bazel 9 because
rules_python 2.3.2's MODULE file uses flag_alias; that restriction comes
from the selected rules_python release. Consumers should still declare their
own direct bazel_dep on rules_python when they load its rules.
Verifying the install¶
Create cv.tex:
And a BUILD.bazel:
load("@rules_latex//latex:defs.bzl", "latex_document")
latex_document(
name = "cv",
main = "cv.tex",
srcs = ["cv.tex"],
)
Then:
You should end up with bazel-bin/cv.pdf.
Optional: opt into the full pinned bundle¶
By default, rules_latex uses its implicit cache pipeline (a one-time
online prime per document, then offline forever). If you'd prefer the
full ~1.78 GiB self-hosted bundle approach — useful for monorepos with many
documents that share most of the same packages — add:
after tectonic.toolchain() in your MODULE.bazel. The 1.78 GiB bundle
is fetched once and used for every compile, skipping the per-document
prime.
See Hermetic builds for the full mode hierarchy.
Modern biblatex extension styles¶
No extra setup needed. The bundle ships biblatex 3.21 + biber
2.21, so modern extension styles like biblatex-apa,
biblatex-chicago, biblatex-ieee, and biblatex-nature work out of
the box — just add the style package to ctan_packages and set
biber = True. See the bibliography
guide for details.
Upgrading from ≤ v0.5? The
tectonic.toolchain(modern_biblatex = True)opt-in was removed in v0.6.0 — the rebuilt TeX Live 2026 bundle ships the modern stack natively. Delete that argument from yourMODULE.bazel; everything it unlocked is now the default.