From ab0ca5f922a136e97b6979641e023a7d4123838d Mon Sep 17 00:00:00 2001 From: Robert Hensing Date: Sat, 6 Dec 2025 21:16:29 +0100 Subject: [PATCH] doc: make HTML manual build optional Add `html-manual` Meson option to allow building manpages without the HTML manual, removing the mdbook dependency for manpage-only builds. Changes: - Add `html-manual` Meson option (default: true) - Make HTML manual build conditional in meson.build - Add `buildHtmlManual` parameter to package.nix - Conditional outputs: ["out" "man"] when enabled, ["out"] when disabled - Make mdbook/rsync/json-schema-for-humans dependencies conditional - Add `nix-manual-manpages-only` package variant This allows systems that only need manpages to avoid the mdbook build dependency while preserving full functionality for HTML manual builds. --- doc/manual/meson.build | 130 ++++++++++--------- doc/manual/meson.options | 7 + doc/manual/package.nix | 102 +++++++++------ doc/manual/source/protocols/json/meson.build | 40 +++--- flake.nix | 1 + packaging/components.nix | 9 ++ packaging/hydra.nix | 1 + 7 files changed, 167 insertions(+), 123 deletions(-) diff --git a/doc/manual/meson.build b/doc/manual/meson.build index b809cf473..3c3e79541 100644 --- a/doc/manual/meson.build +++ b/doc/manual/meson.build @@ -21,9 +21,13 @@ endif nix = find_program('nix', native : true) -mdbook = find_program('mdbook', native : true) bash = find_program('bash', native : true) -rsync = find_program('rsync', required : true, native : true) + +# HTML manual dependencies (conditional) +if get_option('html-manual') + mdbook = find_program('mdbook', native : true) + rsync = find_program('rsync', required : true, native : true) +endif pymod = import('python') python = pymod.find_installation('python3') @@ -109,67 +113,71 @@ else nix_input = [] endif -manual = custom_target( - 'manual', - command : [ - bash, - '-euo', - 'pipefail', - '-c', - ''' - @0@ @INPUT0@ @CURRENT_SOURCE_DIR@ > @DEPFILE@ - @0@ @INPUT1@ summary @2@ < @CURRENT_SOURCE_DIR@/source/SUMMARY.md.in > @2@/source/SUMMARY.md - sed -e 's|@version@|@3@|g' < @INPUT2@ > @2@/book.toml - @4@ -r -L --exclude='*.drv' --include='*.md' @CURRENT_SOURCE_DIR@/ @2@/ - (cd @2@; RUST_LOG=warn @1@ build -d @2@ 3>&2 2>&1 1>&3) | { grep -Fv "because fragment resolution isn't implemented" || :; } 3>&2 2>&1 1>&3 - rm -rf @2@/manual - mv @2@/html @2@/manual - # Remove Mathjax 2.7, because we will actually use MathJax 3.x - find @2@/manual | grep .html | xargs sed -i -e '/2.7.1.MathJax.js/d' - find @2@/manual -iname meson.build -delete - '''.format( - python.full_path(), - mdbook.full_path(), - meson.current_build_dir(), - meson.project_version(), - rsync.full_path(), - ), - ], - input : [ - generate_manual_deps, - 'substitute.py', - 'book.toml.in', - 'anchors.jq', - 'custom.css', - redirects_js, - nix3_cli_files, - experimental_features_shortlist_md, - experimental_feature_descriptions_md, - types_dir, - conf_file_md, - builtins_md, - rl_next_generated, - summary_rl_next, - json_schema_generated_files, - nix_input, - ], - output : [ +# HTML manual build (conditional) +if get_option('html-manual') + manual = custom_target( 'manual', - 'markdown', - ], - depfile : 'manual.d', - env : { - 'RUST_LOG' : 'info', - 'MDBOOK_SUBSTITUTE_SEARCH' : meson.current_build_dir() / 'source', - }, -) -manual_html = manual[0] -manual_md = manual[1] + command : [ + bash, + '-euo', + 'pipefail', + '-c', + ''' + @0@ @INPUT0@ @CURRENT_SOURCE_DIR@ > @DEPFILE@ + @0@ @INPUT1@ summary @2@ < @CURRENT_SOURCE_DIR@/source/SUMMARY.md.in > @2@/source/SUMMARY.md + sed -e 's|@version@|@3@|g' < @INPUT2@ > @2@/book.toml + @4@ -r -L --exclude='*.drv' --include='*.md' @CURRENT_SOURCE_DIR@/ @2@/ + (cd @2@; RUST_LOG=warn @1@ build -d @2@ 3>&2 2>&1 1>&3) | { grep -Fv "because fragment resolution isn't implemented" || :; } 3>&2 2>&1 1>&3 + rm -rf @2@/manual + mv @2@/html @2@/manual + # Remove Mathjax 2.7, because we will actually use MathJax 3.x + find @2@/manual | grep .html | xargs sed -i -e '/2.7.1.MathJax.js/d' + find @2@/manual -iname meson.build -delete + '''.format( + python.full_path(), + mdbook.full_path(), + meson.current_build_dir(), + meson.project_version(), + rsync.full_path(), + ), + ], + input : [ + generate_manual_deps, + 'substitute.py', + 'book.toml.in', + 'anchors.jq', + 'custom.css', + redirects_js, + nix3_cli_files, + experimental_features_shortlist_md, + experimental_feature_descriptions_md, + types_dir, + conf_file_md, + builtins_md, + rl_next_generated, + summary_rl_next, + json_schema_generated_files, + nix_input, + ], + output : [ + 'manual', + 'markdown', + ], + depfile : 'manual.d', + build_by_default : true, + env : { + 'RUST_LOG' : 'info', + 'MDBOOK_SUBSTITUTE_SEARCH' : meson.current_build_dir() / 'source', + }, + ) + manual_html = manual[0] + manual_md = manual[1] -install_subdir( - manual_html.full_path(), - install_dir : get_option('datadir') / 'doc/nix', -) + install_subdir( + manual_html.full_path(), + install_dir : get_option('datadir') / 'doc/nix', + ) +endif nix_nested_manpages = [ [ diff --git a/doc/manual/meson.options b/doc/manual/meson.options index 8bd27104f..1d6b7c73a 100644 --- a/doc/manual/meson.options +++ b/doc/manual/meson.options @@ -4,3 +4,10 @@ option( value : true, description : 'Whether this is an official release build (affects documentation URLs)', ) + +option( + 'html-manual', + type : 'boolean', + value : true, + description : 'Whether to build the HTML manual (requires mdbook)', +) diff --git a/doc/manual/package.nix b/doc/manual/package.nix index cbe422cab..3a90a0faf 100644 --- a/doc/manual/package.nix +++ b/doc/manual/package.nix @@ -19,6 +19,11 @@ # Configuration Options version, + /** + Whether to build the HTML manual. + When false, only manpages are built, avoiding the mdbook dependency. + */ + buildHtmlManual ? true, # `tests` attribute testers, @@ -57,9 +62,22 @@ mkMesonDerivation (finalAttrs: { ../../doc/manual/package.nix; # TODO the man pages should probably be separate - outputs = [ - "out" - "man" + outputs = + if buildHtmlManual then + [ + "out" + "man" + ] + else + [ "out" ]; # Only one output when HTML manual is disabled; use "out" for manpages + + # When HTML manual is disabled, install manpages to "out" instead of "man" + mesonFlags = [ + (lib.mesonBool "official-release" officialRelease) + (lib.mesonBool "html-manual" buildHtmlManual) + ] + ++ lib.optionals (!buildHtmlManual) [ + "--mandir=${placeholder "out"}/share/man" ]; nativeBuildInputs = [ @@ -67,68 +85,68 @@ mkMesonDerivation (finalAttrs: { meson ninja (lib.getBin lowdown-unsandboxed) - mdbook jq python3 + ] + ++ lib.optionals buildHtmlManual [ + mdbook rsync json-schema-for-humans - changelog-d ] - ++ lib.optionals (!officialRelease) [ + ++ lib.optionals (!officialRelease && buildHtmlManual) [ # When not an official release, we likely have changelog entries that have # yet to be rendered. # When released, these are rendered into a committed file to save a dependency. changelog-d ]; - mesonFlags = [ - (lib.mesonBool "official-release" officialRelease) - ]; - preConfigure = '' chmod u+w ./.version echo ${finalAttrs.version} > ./.version ''; - postInstall = '' + postInstall = lib.optionalString buildHtmlManual '' mkdir -p ''$out/nix-support echo "doc manual ''$out/share/doc/nix/manual" >> ''$out/nix-support/hydra-build-products ''; - /** - The root of the HTML manual. - E.g. "${nix-manual.site}/index.html" exists. - */ - passthru.site = finalAttrs.finalPackage + "/share/doc/nix/manual"; + passthru = lib.optionalAttrs buildHtmlManual { + /** + The root of the HTML manual. + E.g. "${nix-manual.site}/index.html" exists. + */ - passthru.tests = - let - redirect-targets = callPackage ./redirect-targets-html.nix { }; - in - { - # https://nixos.org/manual/nixpkgs/stable/index.html#tester-lycheeLinkCheck - linkcheck = testers.lycheeLinkCheck { - site = - let - plain = finalAttrs.finalPackage.site; - in - runCommand "nix-manual-with-redirect-targets" { } '' - cp -r ${plain} $out - chmod -R u+w $out - cp ${redirect-targets}/redirect-targets.html $out/redirect-targets.html - ''; - extraConfig = { - exclude = [ - # Exclude auto-generated JSON schema documentation which has - # auto-generated fragment IDs that don't match the link references - ".*/protocols/json/.*\\.html" - # Exclude undocumented builtins - ".*/language/builtins\\.html#builtins-addErrorContext" - ".*/language/builtins\\.html#builtins-appendContext" - ]; + site = finalAttrs.finalPackage + "/share/doc/nix/manual"; + + tests = + let + redirect-targets = callPackage ./redirect-targets-html.nix { }; + in + { + # https://nixos.org/manual/nixpkgs/stable/index.html#tester-lycheeLinkCheck + linkcheck = testers.lycheeLinkCheck { + site = + let + plain = finalAttrs.finalPackage.site; + in + runCommand "nix-manual-with-redirect-targets" { } '' + cp -r ${plain} $out + chmod -R u+w $out + cp ${redirect-targets}/redirect-targets.html $out/redirect-targets.html + ''; + extraConfig = { + exclude = [ + # Exclude auto-generated JSON schema documentation which has + # auto-generated fragment IDs that don't match the link references + ".*/protocols/json/.*\\.html" + # Exclude undocumented builtins + ".*/language/builtins\\.html#builtins-addErrorContext" + ".*/language/builtins\\.html#builtins-appendContext" + ]; + }; }; }; - }; + }; meta = { platforms = lib.platforms.all; diff --git a/doc/manual/source/protocols/json/meson.build b/doc/manual/source/protocols/json/meson.build index ab9d76d3e..e32cf0640 100644 --- a/doc/manual/source/protocols/json/meson.build +++ b/doc/manual/source/protocols/json/meson.build @@ -35,27 +35,27 @@ endforeach json_schema_generated_files = [] -# Generate markdown documentation from JSON schema -# Note: output must be just a filename, not a path -gen_file = custom_target( - schema_name + '-schema-docs.tmp', - command : [ - json_schema_for_humans, - '--config-file', - json_schema_config, - meson.current_source_dir() / 'schema', - meson.current_build_dir(), - ], - input : schema_files + [ - json_schema_config, - ], - output : schema_outputs, - capture : false, - build_by_default : true, -) - -idx = 0 if json_schema_for_humans.found() + # Generate markdown documentation from JSON schema + # Note: output must be just a filename, not a path + gen_file = custom_target( + schema_name + '-schema-docs.tmp', + command : [ + json_schema_for_humans, + '--config-file', + json_schema_config, + meson.current_source_dir() / 'schema', + meson.current_build_dir(), + ], + input : schema_files + [ + json_schema_config, + ], + output : schema_outputs, + capture : false, + build_by_default : true, + ) + + idx = 0 foreach schema_name : schemas #schema_file = 'schema' / schema_name + '.yaml' diff --git a/flake.nix b/flake.nix index 56d291d1c..c0155391d 100644 --- a/flake.nix +++ b/flake.nix @@ -369,6 +369,7 @@ # TODO probably should be `nix-cli` nix = self.packages.${system}.nix-everything; nix-manual = nixpkgsFor.${system}.native.nixComponents2.nix-manual; + nix-manual-manpages-only = nixpkgsFor.${system}.native.nixComponents2.nix-manual-manpages-only; nix-internal-api-docs = nixpkgsFor.${system}.native.nixComponents2.nix-internal-api-docs; nix-external-api-docs = nixpkgsFor.${system}.native.nixComponents2.nix-external-api-docs; } diff --git a/packaging/components.nix b/packaging/components.nix index bbd6208b9..dbf2180e8 100644 --- a/packaging/components.nix +++ b/packaging/components.nix @@ -429,6 +429,15 @@ in The manual as would be published on https://nix.dev/reference/nix-manual */ nix-manual = callPackage ../doc/manual/package.nix { version = fineVersion; }; + + /** + Manpages only (no HTML manual, no mdbook dependency) + */ + nix-manual-manpages-only = callPackage ../doc/manual/package.nix { + version = fineVersion; + buildHtmlManual = false; + }; + /** Doxygen pages for C++ code */ diff --git a/packaging/hydra.nix b/packaging/hydra.nix index 67e2c0dfd..20605418b 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -70,6 +70,7 @@ let ] ++ lib.optionals enableDocs [ "nix-manual" + "nix-manual-manpages-only" "nix-internal-api-docs" "nix-external-api-docs" ]