CMake modules
Extracted from #[==[.rst: bracket comments in each .cmake module
(D3) via .. cmake-module::, in the order they are include()d by
cmake/zdocs.cmake. Nothing below is hand-written prose about the CMake
surface — it is the bracket comments themselves, rendered.
common.cmake
Shared helpers used by every other zdocs CMake module: add_doc_target
(the internal <name>/<name>-nodeps target-pair helper),
zdocs_resolve_docdir() (the DOCDIR resolution rule
add_sphinx_target/add_doxygen_target share), the build-stage aggregate
targets (doc-tags, doc-index, all-docs, clean-docs) every
document factory contributes to, and add_doc_check(), the
cross-reference integrity gate.
- zdocs_resolve_docdir
zdocs_resolve_docdir(<out_var> <caller_dir> <docdir> <default_subdir>)
Shared
DOCDIRresolution foradd_sphinx_target()andadd_doxygen_target(). Sets<out_var>in the caller’s scope (PARENT_SCOPE) to:<caller_dir>/<default_subdir>when<docdir>is the empty string — the pre-DOCDIRdefault, so a caller that never passes one sees no behaviour change.<docdir>itself, unchanged, when it is already absolute (IS_ABSOLUTE).<caller_dir>/<docdir>otherwise.
Tested with
STREQUAL ""rather thanif(docdir), deliberately: CMake reads"0","OFF","NO","FALSE"and anything ending in-NOTFOUNDas false, so the short form would silently fall back to the default for a folder literally namedoff, or for adocdirthat came back from a failedfind_pathas..-NOTFOUND.
- add_doc_check
add_doc_check(REGISTRY <documents.yaml>)
Wires
scripts/doccheck.py— the cross-reference integrity gate — as a standalonedoc-checktarget AND as aPOST_BUILDstep ofall-docs, so an ordinary build already runs it.REGISTRYis the only argument, and is required; the checks read the builtdeploy/tree, which the engine locates itself.Catches the failure mode this engine is prone to: a cross-reference that breaks WITHOUT breaking the build — a removed document leaving a reference that quietly degrades to plain text, or a parse-time role whose peer inventory was not ready emitting nothing at all.
doxygen.cmake
Drives Doxygen for one document via add_doxygen_target(): the
generated-doxyfile overlay pattern (a consumer Doxyfile.in is expanded,
then the engine-owned keys — HTML_OUTPUT, GENERATE_TAGFILE,
GENERATE_XML, the theme, cross-document TAGFILES, path stripping — are
appended so Doxygen’s “last value of a repeated key wins” rule makes them
authoritative), the two-stage tag-file build, and the builder-first deploy
layout (deploy/html/<id>/, deploy/xml/<id>/) — both keyed on the
document’s registry id, verbatim.
- add_doxygen_target
add_doxygen_target(<name> [REGISTRY <documents.yaml>] [DOXYFILE_IN <path>] [DOCDIR <dir>])
Declares one Doxygen document named
<name>, taken verbatim —<name>IS the document’s registry id; a consumer that wants it to carry adox-prefix (or any other convention) writes that into the id itself and gets it back unchanged in the source folder, the deploy paths and every target name. Requiresfind_package(Doxygen REQUIRED), which this module runs itself.REGISTRYPath to
documents.yaml. When given, this document’s inter-doxygenTAGFILESand its project-scopeddoxygen_xml:opt-in are derived from it; omitted, no cross-document tag links and XML stays off.DOXYFILE_INTemplate to configure (
@ONLY). Defaults toDoxyfile.ininside the (possiblyDOCDIR-relocated) source folder; pass an explicit path to document this project from another project’s own template (e.g. Zephyr’szephyr.doxyfile.in).DOCDIRRelocates only where the sources (
Doxyfile.in,mainpage.md, …) are read from; the deploy folder (deploy/html/<name>/) and every target name stay keyed on<name>. Seezdocs_resolve_docdir().
sphinx.cmake
Drives Sphinx for one document via add_sphinx_target(): a
two-stage build (a xref-builder cross-reference index pass, then one pass
per requested builder), the sphinx-git .git pointer for the copied source
tree, and the builder-first deploy layout (deploy/<builder>/<doc>/).
- add_sphinx_target
add_sphinx_target(<doc_name> BUILDERS <b1> [<b2> ...] [REGISTRY <documents.yaml>] [TAGS <t1> [<t2> ...]] [DEPENDS <doc1> [<doc2> ...]] [DOCDIR <dir>])
Declares one Sphinx document.
<doc_name>is both the target-name stem (<doc_name>-<builder>,<doc_name>-<builder>-nodeps,<doc_name>-index) and the registry key; its sources live in<caller dir>/<doc_name>/unlessDOCDIRrelocates only where they are read from.BUILDERS(required, non-empty)Sphinx builders to run, e.g.
htmlorhtml latex. Only thehtmlbuilder’s target joinsall-docs.REGISTRYPath to
documents.yaml. When given, this document’s intersphinx mapping, external needs and version scope are derived from it; omitted, the document builds standalone with no cross-document links.TAGSExtra Sphinx tags (
-t), appended afterZDOCS_DOC_TAG.DEPENDSOther document ids this one actually cross-references, ordering the stage-1 index builds to reduce transient warnings on a from-scratch parallel build.
DOCDIRRelocates where the sources are read from (resolved against the caller’s directory, or used as-is if absolute); everything else — target names, deploy path, registry key — stays keyed on
<doc_name>. Seezdocs_resolve_docdir().
registry.cmake
add_docs_from_registry() reads documents.yaml (via
docrefs.py manifest) and dispatches one add_sphinx_target()
or add_doxygen_target() call per document, so a consumer’s
CMakeLists.txt never hand-writes one factory call per document. It also
creates the per-(group, builder) aggregate targets
(<group>-<builder>/<group>-<builder>-nodeps) documented on
add_docs_from_registry() itself.
- add_docs_from_registry
add_docs_from_registry(REGISTRY <documents.yaml>)
Declares every document in
REGISTRYas a CMake target, dispatched bykind:sphinx(or omitted) —add_sphinx_target()(<id> BUILDERS <builders...> REGISTRY <REGISTRY> [DOCDIR ...]). A configure-timeFATAL_ERRORnaming the document ifbuilders:is empty or missing. A document withdoxygen_tag:also gets<id>-needstag, which writes its needs as a Doxygen tag file after its stage-1 index (indoc-index, notdoc-tags).doxygen—add_doxygen_target()(<id> REGISTRY <REGISTRY> [DOCDIR ...]).external/sphinx-external— no CMake target of any kind.doxygen-external— exactly one target,<id>-tag, that downloadsremote-tagfile:at build time.
Also creates, per distinct
(group, builder)pair with at least one contributing document, two aggregate targets:<group>-<builder>(depends on every contributor’s own<id>-<builder>) and<group>-<builder>-nodeps(the same, against each-nodepstwin). A Doxygen document counts as builderhtmlfor this aggregation only; its own target is named after its registry id, exactly.doc_dir:in the registry, when relative, is resolved against the directory containingREGISTRYitself — not against whicheverCMakeLists.txtcalled this command.
zdocs.cmake
Single entry point. A consumer includes this after adding
${ZEPHYR_ZDOCS_MODULE_DIR}/cmake to CMAKE_MODULE_PATH; it in turn
include()``s ``common, doxygen, sphinx and registry, which is
what brings add_sphinx_target(), add_doxygen_target(),
add_docs_from_registry() and add_doc_check() into
scope. Requires ZDOCS_PROJECT_BASE to already be set; see the consumer
configuration block below for every other ZDOCS_* variable it reads.
download_external_tag.cmake
Internal cmake -P wrapper, invoked as the COMMAND of an
<id>-tag custom target created by add_docs_from_registry()
for a kind: doxygen-external document. Downloads -DURL=<remote-tagfile>
to -DDEST=<local path> (file(DOWNLOAD ...)) at BUILD time, so the fetch
is refreshed on every run rather than baked in as a configure-time side
effect. No public commands — the two -D arguments above are its whole
interface, exercised only through the registry dispatcher.
run_doxygen.cmake
Internal cmake -P wrapper invoked by add_doxygen_target()’s
two doxygen custom targets (stage 1’s tag build and stage 2’s full build), so
that the git-derived PROJECT_NUMBER is recomputed at BUILD time on every
run rather than baked in at configure time. Computes the version via
docrefs.py version, writes a thin @INCLUDE overlay next to the given
doxyfile that overrides PROJECT_NUMBER, then runs Doxygen on the overlay.
No public commands — its whole interface is the -D arguments above,
exercised only through add_doxygen_target().
check_doxygen_warnings.cmake
Internal cmake -P gate run after add_doxygen_target()’s
stage-2 Doxygen build. Stage 2 writes its warnings to a log file instead of the
console; this script echoes that log, so the console shows what it always did,
then fails the target if any line matches one of
ZDOCS_DOXYGEN_WARN_FAIL_PATTERNS.
Stage 2 only, deliberately. Stage 1 runs with TAGFILES cleared, so every
reference into a peer document — including every \verifies and
\satisfies against another project’s \requirement — warns there
falsely; stage 1 is therefore silenced and never gated.
The gate exists because the Doxygen XML cannot tell a real requirement link
from a typo: Doxygen synthesizes <requirement refid="requirement_<UID>">
from the UID string whether or not any \requirement defines it. Its warning
is the only signal.