Repository navigation
CMake: Build the MkDocs documentation site - #7719
Conversation
Make the markdown documentation tree complete enough to build the MkDocs site, and add build-mkdocs and serve-mkdocs targets matching the Autotools ones (both run mkdocs from PATH and are not part of the default build). Copy the site files from man/mkdocs (mkdocs.yml, index and keywords pages, theme overrides, CSS, logo) into the markdown tree. Add an MD_ONLY mode to generate_docs for the web-only guides from doc/ and doc/development/, which have no HTML source and no man page. Exclude those pages from man page generation with a new --exclude option in build_manpages.py, derived from the doc/ directories like WEB_ONLY_MD in man/Makefile. Copy the assets linked from the pages (GUI icons, color tables, barscale and north arrow thumbnails, grass_logo.txt) into the markdown tree alongside their existing html copies. Narrow the doc/ paths-ignore of the CMake workflow to content file types, so that changes to the CMakeLists.txt files now under doc/ trigger the workflow. Generated with AI assistance (Claude Fable); verified by building the site from a CMake build and comparing mkdocs warnings against the Autotools tree.
wenzeslaus
left a comment
There was a problem hiding this comment.
Here is a AI-review you requested (reads as reasonable to me):
Overview
The PR completes the CMake markdown tree so mkdocs build can run against it, and adds build-mkdocs / serve-mkdocs targets mirroring the Autotools ones. Three mechanisms: a copy_mkdocs_files target for the site scaffolding (mkdocs.yml, overrides, theme assets), an MD_ONLY mode in generate_docs for web-only guides that have no .html source and no man page, and asset copies (icons, colortables, barscales, north arrows, grass_logo.txt) into the markdown tree.
The design is sound and the Autotools parity is real. The following were verified rather than assumed:
$<SEMICOLON>+cmake -E envworks. In a scratch project,COPYRIGHT=© 2003-2026 GRASS Development Team, ...andSITE_NAMEcome out byte-identical to whatman/Makefile'sbuild-mkdocsexports. The genex is the right fix for the;list-separator problem, and the comment explaining it is worth keeping.--exclude ${web_only_pages}expands correctly into separate argv entries.add_custom_target(... DEPENDS <target-name>)does create a target-level dependency, despite the CMake docs describingDEPENDSas file-level. Confirmed with a scratch build; the codebase already relies on this (build_full_index DEPENDS ALL_MODULES).MD_ONLYmatches Autotools.include/Make/Html.make:9builds$(MDDIR)/source/%.mdthroughmkmarkdown.py, anddoc/development/Makefile's default target asks only for the md files, no man pages. Droppingmkhtml/md2manfrom the MD_ONLY branch reproduces that exactly.cmake_pathneeds CMake >= 3.20; the project requires 3.22 andutils/CMakeLists.txt:15already uses it.doc/**/*.mddoes matchdoc/grass_database.md(no intermediate directory), since GitHub's**matches zero or more directories. The repo already depends on this incodeql-analysis.yml:11.
Findings
1. cmake_path(GET ... STEM ...) splits at the first dot, $(basename) at the last - man/CMakeLists.txt
The Makefile comment this mirrors uses $(basename $(notdir $(DOC_MD))), which strips only the final suffix. cmake_path's STEM without LAST_ONLY strips from the first dot. Verified:
/a/b/dotted.v2.md -> STEM='dotted' STEM_LAST_ONLY='dotted.v2'
No current doc page has a dot in its name, so this is latent. But the failure would be silent and in the wrong direction: a future doc/foo.v2.md would be excluded under the name foo, and build_manpages.py would emit a man page for a web-only guide. LAST_ONLY makes the CMake side match $(basename):
cmake_path(GET doc_file STEM LAST_ONLY page_name)2. The comment claims automatic exclusion; file(GLOB) is configure-time - man/CMakeLists.txt
The guides are derived from the doc/ source directories so a newly added guide is excluded automatically
$(wildcard) re-evaluates on every make run, so the Makefile comment is true there. file(GLOB) without CONFIGURE_DEPENDS is evaluated once at configure time. In practice it works out, because a new guide also has to be added to doc/CMakeLists.txt to be generated at all, and that edit triggers a reconfigure. But the comment promises more than the code delivers. Either add CONFIGURE_DEPENDS, or reword to something like "excluded automatically once CMake reconfigures (which adding the guide to doc/CMakeLists.txt triggers)".
3. The paths-ignore enumeration is incomplete and slightly inconsistent - .github/workflows/cmake.yml
The comment correctly notes that paths-ignore does not support negation. But enumerating content types means the list has to be maintained, and it is already missing types that exist today: doc/grass_database.svg, doc/project.svg, doc/debugging.txt, doc/html_documentation.txt, plus .odg and .fig. Editing any of those now runs the full CMake matrix. It is also inconsistent in a way that reads as accidental: doc/**/*.py ignores doc/examples/python/**, while doc/examples/**/*.c and the example Makefiles do trigger.
The direction of the error is safe (extra CI runs, not missed ones), so this is not a blocker. But GitHub does support ! in the paths filter, which expresses the intent directly and never needs updating for a new file type:
paths:
- "**"
- "!doc/**"
- "doc/CMakeLists.txt"
- "doc/**/CMakeLists.txt"The tradeoff is that paths and paths-ignore are mutually exclusive per event, and "**" is a blunt opener. If paths-ignore is preferred, adding doc/**/*.svg and doc/**/*.txt would cover the known gaps.
4. build-mkdocs does not depend on the docs being generated - man/CMakeLists.txt
It depends only on copy_mkdocs_files, so cmake --build build --target build-mkdocs on a fresh tree renders a site from a source directory holding nothing but the scaffolding. Autotools has the same shape (build-mkdocs: has no prerequisites), so this is parity rather than a regression, and in a normal workflow the default build has already run. Still, CMake makes the fix nearly free (DEPENDS copy_mkdocs_files build_check), and it would turn a confusing empty site into a correct one. Worth a deliberate decision either way; if the answer is parity with Autotools, the existing comment could say so.
Nits
generate_docs.cmake: the MD_ONLY branch duplicates the D_TARGET branch. Ten lines, and the shared prefix (md_descr_command,mkmarkdown_cmd,copy_images_command_md, tmp cleanup) is identical. A later fix to the markdown pipeline in the first branch could easily miss the second. Low urgency given the size, but this is a shared helper.generate_docs.cmakedocs.[MD_ONLY]is added to thegenerate_docssignature but only described in thegenerate_docs_listparagraph above it. A one-line description undergenerate_docswould close that.MD_ONLYis silently ignored whengenerate_docsis called withOUTPUTinstead ofTARGET. Onlygenerate_docs_listuses it today, and it always passesTARGET, so this is fine. Noted only so the boundary is known.- The colortables copy sits outside the
WITH_DOCSguard (CMakeLists.txt).r_colors_thumbnailsis defined after theif(WITH_DOCS)block, so a-DWITH_DOCS=OFFbuild now populatesdocs/mkdocs/source/colortables. Harmless, sinceGRASSInstallDirs.cmake:130creates the directory unconditionally anyway; just untidy.
Risk and coverage
Low risk overall: build plumbing only, no runtime code, and no new dependency in the default build (mkdocs is only invoked by the two on-demand targets).
One coverage observation, not a request: nothing in CI exercises build-mkdocs. documentation.yml builds the site from an Autotools tree and invokes mkdocs build directly rather than going through the build-mkdocs target, so neither build system's target is tested. This parity is therefore maintained by hand and can rot quietly. The PR body says it was verified by comparing mkdocs warnings against the Autotools tree, which is the right check; it is just not repeatable by CI.
The asset list cross-checks out: documentation.yml:213-219 copies every directory under ${MKDOCS_DIR}/source into addons, which is exactly the set this PR adds (colortables, icons, barscales, northarrows), so the CMake tree should produce the shape the site build expects.
Nothing here blocks merge. Findings 1 and 2 are the two worth fixing first, since both are small and both are cases of the code not matching what the comment claims.
Nits: added an MD_ONLY description to the generate_docs docs (also documents that it only applies with TARGET). Left the MD_ONLY branch duplication as is — the branches converge once the html halves are removed in the html-removal phase. The colortables copy outside WITH_DOCS mirrors the pre-existing unguarded r_colors_thumbnails target; that spot gets restructured in the same phase. On CI coverage of build-mkdocs: agreed, a smoke test is on the list as a follow-up once the site ships in the distribution. |
wenzeslaus
left a comment
There was a problem hiding this comment.
Thanks! Looking forward to see this in action.
nilason
left a comment
There was a problem hiding this comment.
Re: "The colortables copy sits outside the WITH_DOCS guard" issue –– the color tables are not only used as documentation but by r.colors tool ( I believe it was), so they need to be installed with/without WITH_DOCS. This will by the way necessitate a duplication of the files with FHS installation.
Follow-up to #7674, part of the transition to markdown-based documentation.
Make the markdown documentation tree generated by the CMake build complete enough to build the MkDocs site, and add
build-mkdocsandserve-mkdocstargets matching the Autotools ones (both runmkdocsfromPATHand are not part of the default build).man/mkdocs(mkdocs.yml, index and keywords pages, theme overrides, CSS, logo) into the markdown tree.MD_ONLYmode togenerate_docsfor the web-only guides fromdoc/anddoc/development/, which have no HTML source and no man page, and exclude those pages from man page generation with a new--excludeoption inbuild_manpages.py.grass_logo.txt) into the markdown tree.doc/paths-ignore of the CMake workflow to content file types, so changes to the CMakeLists.txt files now underdoc/trigger it.Verified by building the site from a CMake build and comparing mkdocs warnings against the Autotools tree.
Generated with AI assistance (Claude Fable).