Files
Vijay Janapa Reddi 0a4b3520ca build(tinytorch/pdf): single-source deps via requirements files
CI workflows repeated a ~20-line tlmgr install block inline. Consolidate
to two requirements files that work locally and in CI:
  pdf/apt-requirements.txt - system packages (librsvg2-bin)
  pdf/tex-requirements.txt - 24 TeX packages

New Makefile target 'make install-deps' reads both files, calling
apt-get + tlmgr. Skips sections when the tool is not on PATH (no-op
on macOS, effective on Ubuntu CI).

CI workflows simplified to 'make install-deps && make pdf', matching
local dev exactly. Adding a dependency now means editing one file,
not two.
2026-04-23 15:09:44 -04:00

173 lines
8.5 KiB
Makefile

# =============================================================================
# TinyTorch quarto build
# =============================================================================
# Two Quarto projects share this directory:
# • the website (this directory's _quarto.yml, project type "website")
# • the lab guide PDF (pdf/_quarto.yml, project type "book")
#
# Both consume the same chapter qmd files in modules/. Hand-authored SVG
# diagrams in assets/images/diagrams/ are the source-of-truth artifacts —
# edit them directly in Inkscape, Affinity, or a text editor (see
# tools/diagrams/STYLE.md for the visual convention). For the LaTeX
# build we convert each SVG to a sibling PDF via rsvg-convert; a small
# Lua filter (tools/diagrams/svg-to-pdf.lua) rewrites the qmd image
# refs from `.svg` → `.pdf` only for the PDF format, so the website
# keeps serving SVGs while the PDF embeds the pre-converted vector PDFs.
#
# Common entry points:
# make — alias for `make pdf`
# make pdf — convert SVGs to PDFs + render the lab guide
# make site — render the website (HTML)
# make figures — only convert SVGs to PDFs (no render)
# make clean — remove caches + generated diagram PDFs
# make distclean — clean + remove rendered guide & website outputs
# make help — list all targets
# make check-tools — verify rsvg-convert + quarto are on PATH
#
# Dependencies:
# • quarto (https://quarto.org)
# • rsvg-convert (`brew install librsvg` on macOS,
# `apt-get install librsvg2-bin` on Debian/Ubuntu)
# =============================================================================
# Use bash + fail-fast pipelines so a broken sub-step actually fails the
# Make target rather than silently emitting a stale PDF.
SHELL := /bin/bash
.SHELLFLAGS := -eu -o pipefail -c
DIAGRAM_DIR := assets/images/diagrams
# Discover diagrams from the filesystem so adding a new SVG (drop a new
# file into $(DIAGRAM_DIR)) automatically gets picked up the next time
# `make figures` runs. We compute the .pdf list from the .svg list:
# SVGs are the source-of-truth, PDFs are the derived LaTeX-embed format.
SVGS := $(wildcard $(DIAGRAM_DIR)/*.svg)
PDFS := $(SVGS:.svg=.pdf)
# rsvg-convert flags:
# -f pdf emit PDF (otherwise it picks based on extension)
# --keep-aspect-ratio ensure no squashing if a viewBox is unusual
# We deliberately do NOT pass --width/--height — the SVG's own viewBox
# is the canvas size, and forcing a pixel size would defeat vector
# rendering downstream in LaTeX.
RSVG := rsvg-convert
RSVG_FLAGS := -f pdf --keep-aspect-ratio
QUARTO := quarto
# Treat every target below as phony except the actual file recipes.
.PHONY: all pdf site figures clean distclean help check-tools
all: pdf
install-deps: ## Install system + LaTeX packages needed to build the PDF.
@# apt packages (requires sudo on CI / Linux; no-op elsewhere)
@if [ -f pdf/apt-requirements.txt ] && command -v apt-get >/dev/null 2>&1; then \
echo " installing apt packages from pdf/apt-requirements.txt"; \
sudo apt-get update -y; \
grep -v '^#' pdf/apt-requirements.txt | grep -v '^$$' | xargs -r sudo apt-get install -y; \
fi
@# TinyTeX / LaTeX packages (tlmgr from the Quarto TinyTeX install)
@if [ -f pdf/tex-requirements.txt ] && command -v tlmgr >/dev/null 2>&1; then \
echo " installing TeX packages from pdf/tex-requirements.txt"; \
tlmgr update --self || true; \
grep -v '^#' pdf/tex-requirements.txt | grep -v '^$$' | xargs -r tlmgr install; \
fi
@echo " dependencies installed"
help: ## Show this help.
@awk 'BEGIN {FS = ":.*##"; printf "Targets:\n"} \
/^[a-zA-Z_-]+:.*?##/ {printf " \033[36m%-14s\033[0m %s\n", $$1, $$2}' \
$(MAKEFILE_LIST)
# ── SVG → PDF conversion ──────────────────────────────────────────────
# Pattern rule: Make's automatic dependency on $< means a touched SVG
# re-converts only the affected PDF — the build is incremental over
# diagram edits.
$(DIAGRAM_DIR)/%.pdf: $(DIAGRAM_DIR)/%.svg | check-tools
@$(RSVG) $(RSVG_FLAGS) -o $@ $<
@printf " rsvg → %s\n" "$@"
figures: $(PDFS) ## Convert all SVG diagrams to PDF (for LaTeX embedding).
# ── Render targets ────────────────────────────────────────────────────
# `make pdf` is the canonical "rebuild the lab guide" command. It
# converts every SVG to PDF, then runs Quarto. The Lua filter in
# pdf/_quarto.yml rewrites .svg → .pdf for the PDF format only.
#
# Quarto's post-render cleanup step exits non-zero because the book
# project reads chapters at `../modules/...` — outside its own project
# root — so Quarto refuses to remove the auxiliary `_files/` directories
# left behind there. XeLaTeX has already written the PDF by that point,
# so we mirror the CI pattern (.github/workflows/tinytorch-build-pdfs.yml):
# run Quarto, capture its exit code, then *verify the PDF exists* and
# treat the cleanup error as benign only if it does. If the PDF is
# missing, fail loudly — that's a real build failure.
# Quarto writes the rendered book into pdf/_build/ (see `output-dir: _build`
# in pdf/_quarto.yml) — this matches every other Quarto project in the repo
# (kits, slides, site, labs, etc. all emit under _build/). CI workflows
# (tinytorch-build-pdfs.yml, tinytorch-update-pdfs.yml) upload the artifact
# directly from pdf/_build/TinyTorch-Guide.pdf. Local dev should also use
# the _build/ path; there is no duplicate copy.
PDF_OUT := pdf/_build/TinyTorch-Guide.pdf
# Single canonical PDF output — the ONLY shippable file.
# pre-build: rm any stray top-level pdf/TinyTorch-Guide.pdf from a
# past build (don't confuse the author).
# post-build: self-heal if Quarto's cleanup error leaves the PDF at
# pdf/ top level instead of pdf/_build/.
# Verify no duplicate copies exist.
pdf: figures ## Build the TinyTorch Lab Guide PDF — ONE file at pdf/_build/TinyTorch-Guide.pdf.
@rm -f pdf/TinyTorch-Guide.pdf
@set +e; \
cd pdf && $(QUARTO) render; \
quarto_exit=$$?; \
cd ..; \
if [ ! -f "$(PDF_OUT)" ] && [ -f "pdf/TinyTorch-Guide.pdf" ]; then \
mkdir -p pdf/_build; \
mv pdf/TinyTorch-Guide.pdf "$(PDF_OUT)"; \
fi; \
if [ ! -f "$(PDF_OUT)" ]; then \
echo "ERROR: $(PDF_OUT) was not produced (quarto exit=$$quarto_exit)"; \
exit 1; \
fi; \
if [ -f "pdf/TinyTorch-Guide.pdf" ]; then \
rm -f pdf/TinyTorch-Guide.pdf; \
echo " (removed stray top-level pdf/TinyTorch-Guide.pdf)"; \
fi; \
if [ $$quarto_exit -ne 0 ]; then \
echo " note: quarto exited $$quarto_exit on post-render cleanup (benign — see Makefile)"; \
fi; \
size=$$(du -h "$(PDF_OUT)" | cut -f1); \
echo ""; \
echo " ┌────────────────────────────────────────────────────────────┐"; \
echo " │ FINAL PDF (the only shippable file): │"; \
echo "$(PDF_OUT) ($$size)"; \
echo " └────────────────────────────────────────────────────────────┘"
site: ## Build the website (HTML).
@$(QUARTO) render
# ── Maintenance ───────────────────────────────────────────────────────
clean: ## Remove Quarto caches + generated diagram PDFs + any stray top-level PDF.
@rm -rf _tmp pdf/_build pdf/index_files modules/*_files pdf/.quarto
@rm -rf *_files
@rm -f $(DIAGRAM_DIR)/*.pdf
@rm -f pdf/TinyTorch-Guide.pdf pdf/index.tex pdf/index.log pdf/index.aux pdf/index.toc pdf/index.out
@echo " cleaned caches, generated diagram PDFs, stray *_files dirs, and stray PDF copies"
distclean: clean ## Also remove website output. (clean already removes pdf/_build/.)
@rm -rf _site
@echo " removed rendered outputs"
check-tools: ## Verify rsvg-convert + quarto are on PATH.
@command -v $(RSVG) >/dev/null 2>&1 || { \
echo "ERROR: $(RSVG) not found on PATH."; \
echo " macOS: brew install librsvg"; \
echo " Debian: apt-get install librsvg2-bin"; \
exit 1; }
@command -v $(QUARTO) >/dev/null 2>&1 || { \
echo "ERROR: $(QUARTO) not found on PATH."; \
echo " Install from https://quarto.org"; \
exit 1; }