Generate Doxygen HTML documentation and a LaTeX PDF manual for any C or C++ project inside a minimal, security-hardened container — no host install of Doxygen, Graphviz, or LaTeX required.
A self-standing, containerized documentation tool built on
Doxygen. It turns a source tree + a Doxyfile.in
template + Markdown pages into browsable HTML and an optional PDF manual —
without installing Doxygen, Graphviz, or LaTeX on the host. Everything runs inside
a minimal, security-hardened podman container.
Why doc-toolchain? Reproducible, one-command API docs for C/C++ with zero toolchain drift — vendor it once as a git submodule and every contributor and CI runner builds identical HTML and PDF output from the same pinned container image.
It is designed to be vendored into a project as a git submodule (e.g. at
docs/doc-toolchain), reading that project's documentation content from a docs/
folder. It works for any C/C++ project, not just the one it ships with.
-
A container engine:
podman(rootless is fine, preferred) — ordockeras an automatic fallback if podman isn't installed. Nothing else on the host — no Doxygen, Graphviz, or LaTeX.The engine is autodetected (podman first, then docker). Force one with
--engine docker/--engine podman, or theCONTAINER_ENGINEenv var.
From a project that vendors this at docs/doc-toolchain:
# HTML only (small ~40 MB image, fast):
docs/doc-toolchain/build-docs.sh --no-pdf
# HTML + PDF manual (image adds a minimal LaTeX):
docs/doc-toolchain/build-docs.sh --pdfOutput lands in docs/_build/ (html/index.html and <Project>-manual.pdf).
Standalone, for any project:
build-docs.sh --project-root /path/to/proj \
--docs-dir /path/to/proj/docs \
--source-dirs "include src" \
--pdfSee build-docs.sh --help for all options, and examples/ for a complete
minimal project you can build docs for.
The toolchain is generic; per-project content lives in the project's docs dir:
| File | Purpose |
|---|---|
Doxyfile.in |
Doxygen config template. Placeholders ${PROJECT_NAME} ${PROJECT_NUMBER} ${INPUT_DIRS} ${DOCS_DIR} ${OUTPUT_DIR} ${HAVE_DOT} ${GEN_LATEX} are filled in-container. |
pages/*.md |
Markdown pages (@mainpage, guides). Add them to INPUT. |
templates/custom.css |
Optional extra stylesheet (HTML_EXTRA_STYLESHEET). |
Regenerate version-matched HTML header/footer/CSS templates with:
build-docs.sh --init-templates # writes into docs/templates/Build-time (Containerfile):
- Base
alpine:3.20(pin to a digest in production). - Only doc packages installed;
--no-cache, apk cache removed. --build-arg WITH_PDF=0→ HTML-only image (~40 MB).WITH_PDF=1adds a minimal TeX Live capable of building Doxygen'srefman.tex.- Runs as a non-root
docbuilderuser; single fixedentrypoint.sh.
Run-time (applied by build-docs.sh):
--read-onlyroot filesystem; only the output bind-mount and a/tmptmpfs are writable.--network=none— rendering needs no network.--cap-drop=ALLand--security-opt=no-new-privileges.--user $(id -u):$(id -g)(plus--userns=keep-idon podman) so output files are owned by you.--memory/--pids-limitcaps. Source tree mounted read-only.
git submodule add <URL-of-this-repo> docs/doc-toolchain
git commit -m "Add doc-toolchain submodule"If you cloned a project that pins this via a local path URL (as in the reference setup, which has no remote), edit
.gitmodulesto pointurlat your hosted copy of this repo and rungit submodule sync.
option(MYPROJ_BUILD_DOCS "Add doc targets" OFF)
if(MYPROJ_BUILD_DOCS)
include(${CMAKE_SOURCE_DIR}/docs/doc-toolchain/cmake/DocToolchain.cmake)
endif()
# → `cmake --build build --target docs` / `docs-pdf`If your host enforces SELinux, append ,Z to the volume mounts in build-docs.sh
(-v "$PROJECT_ROOT:/project:ro,Z"). It is omitted by default because relabeling
is unnecessary — and can be surprising — on non-SELinux hosts.
Released under the MIT License. © 2026 tinycodestudio.
Keywords: Doxygen · containerized documentation · C/C++ API docs generator · Doxygen PDF · Doxygen HTML · podman · rootless container · Graphviz · LaTeX manual · doc automation · git submodule docs · CMake docs · reproducible documentation build · security-hardened container · Alpine Linux.