CMake: Build man pages from markdown#7674
Conversation
Generate the markdown documentation (--md-description + mkmarkdown.py) in all three doc paths (modules, GUI, scripts) and convert man pages from it with g.md2man instead of from HTML with g.html2man, mirroring the Autotools build. Install g.md2man.py and gmd.py, and install the generated docs/mkdocs tree, which was previously not installed at all. Add man/build_manpages.py, a sweep run after the index scripts that converts any markdown page without an up-to-date man page. It ports man/Makefile's MANPAGES wildcard to CMake, which has no build-time glob, and produces the index and dynamically named topic_* man pages that the CMake build previously did not ship. Run the doc generators in the tool source directory like Autotools does. This fixes the SOURCE CODE footer in all CMake-built pages, which previously pointed to a nonexistent build-directory path in the repository and fell back to an Accessed date instead of the last commit, and makes the copy-source-into-build-dir steps unnecessary. Also fix build_class.py receiving the documentation directory as its year argument. Verified against an Autotools build: g.md2man output for the same generated markdown is byte-identical. Generated with AI assistance (Claude Fable), including the build verification against the Autotools doc tree.
wenzeslaus
left a comment
There was a problem hiding this comment.
We aim for parity between the two builds, but this seems to have some gaps. Either one can change, and changing Autotools to make the CMake side more sensible would be okay. With that in mind, I prepared the following points with AI:
-
build_manpages.pyhas no web-only exclusions. Autotoolsman/MakefilefiltersWEB_ONLY_MD(index,keywords,development_intro,command_line_intro, and thedoc/*.mdguides exceptgrass_database/projectionintro) out ofMANPAGES; the new script converts every*.mdit finds. Today the results are equivalent because the CMake build never puts those files into the mkdocs source tree — but the statics follow-up listed in the PR description will silently start producingindex.1,keywords.1, etc., regressing the #7540 exclusions. The cleanest fix may be to put the exclusion list intobuild_manpages.pyitself and have the Autotools build call the same script instead of the MakefileMANPAGES/WEB_ONLY_MDmachinery — one list, one code path, and the parity holds by construction. If that is left for the statics follow-up, a docstring sentence stating the assumption would do for now. -
Generated
.mddiffers from Autotools for pages without--md-description. For non-HTML_DESCRpages (grass_database,projectionintro),md_descr_commandiscmake -E echo, which writes a newline into the tmp file;mkmarkdown.pytreats"\n"as real content and prepends blank lines. Autotools generates these pages with no tmp file at all (read_file()returns""), so the installed mkdocs trees are not byte-identical. Two ways to close the gap:cmake -E true > file(empty file) on the CMake side, or makemkmarkdown.pytreat whitespace-only generated content as empty — the latter fixes the shared tooling so neither build depends on how the tmp file happens to be created. The same quirk pre-exists on the HTML side; fixing it there too (or leaving HTML alone since it is on the way out) is fine either way. -
>=in the mtime check can leave a stale man page.man_file.stat().st_mtime >= md_file.stat().st_mtimeskips on equal timestamps, so on filesystems with coarse mtime granularity an.mdregenerated in the same second as an earlier conversion is skipped. Using>only costs an occasional redundant conversion, which is the safer direction for a build. -
Undeclared byproducts. The custom commands declare only the HTML file as
OUTPUTwhile also producing the.mdand.1files. Consistent with how the man file was (not) handled before, butBYPRODUCTSwould help Ninja dependency tracking andclean. Fine as a follow-up. -
Redundant per-file installs.
install(FILES ... DESTINATION ${GRASS_INSTALL_MKDOCSDIR}/source)for images duplicates the new top-levelinstall(DIRECTORY ${OUTDIR}/${GRASS_INSTALL_MKDOCSDIR}/ ...), since the images are already copied into the OUTDIR tree at build time. Mirrors the existing DOCDIR redundancy, so keeping it for symmetry is defensible — noting it as future cleanup. -
Source-tree
.tmp.writes. Running the generators in the source directory forecloses read-only-source CMake builds. The in-code comment justifies it well (footer link derivation, gitignored, Autotools does the same) and it fixes genuinely wrong footer links, so I agree with the choice. Long term, teaching the footer machinery to take an explicit source path would let both builds stop writing into the source tree — another case where changing the shared tooling (and Autotools) to fit CMake would be the better end state. -
Nit:
build_manpages.pyhas no argv validation, so a missing argument dies with anIndexErrortraceback. Matches the sibling scripts inman/, but a one-line usage check would be friendlier.
|
Thanks — addressed all points:
|
This PR adds markdown documentation generation to the CMake build and switches man page generation from HTML (g.html2man) to the generated markdown (g.md2man), mirroring what #7540 did for Autotools. The CMake and Autotools builds now produce man pages the same way.
Context: Follow-up to #7540. Man pages no longer depend on the HTML build in either build system, which unblocks removing the HTML documentation later.
What changed:
generate_docs.cmakeruns each tool's--md-description, assembles the page withmkmarkdown.pyintodocs/mkdocs/source/, and converts the man page from it withg.md2man(all three doc paths: modules, GUI doublepages, scripts). Images are copied to the markdown tree as well.
g.md2man.py/gmd.pyare wired into the build and install, replacingg.html2manin the man pipeline (HTML pages themselves are still built).man/build_manpages.py: converts any markdown page without an up-to-date man page. This isman/Makefile'sMANPAGESwildcard ported to CMake (which has no build-time glob) and it produces the index and dynamically namedtopic_*man pages — the CMake build previously shipped no index man pages at all.docs/mkdocstree is now installed (previously it was not installed at all).build_class_graphicalandparser_standard_optionsinman/CMakeLists.txt.Fixes to pre-existing CMake doc bugs found along the way:
.../commits/main/build/display) and showed an "Accessed" fallback date instead of the last commit. The generators now run in the tool source directory like in the Autotools build; the.tmp.usage files land theretoo (gitignored, same as Autotools), and the copy-source-into-build-dir steps became unnecessary.
build_class.pywas passed the documentation directory as its year argument.Verification (AI-assisted): full CMake build compared against an Autotools-built tree. Man page sets match modulo environment differences (PDAL/LIBLAS/PostgreSQL availability) and intentional post-#7540 exclusions (
index.1,keywords.1); converting the same generated markdown withg.md2manyields byte-identical man pages in both builds.Out of scope (follow-ups):
mkdocs.yml, overrides,index.md, ...) are not copied; building/serving the MkDocs site with CMake is a separate step.build_addon.cmakestill uses the HTML pipeline (belongs with the g.extension markdown work).test.raster3d.libis inNO_HTML_DESCR_TARGETS, so its page lacks the generated usage section (pre-existing, also affects its HTML page).AI disclosure: implemented and verified by Claude (Fable), including the comparison against the Autotools documentation tree.