1 { config, options, lib, pkgs, utils, modules, baseModules, extraModules, modulesPath, specialArgs, ... }:
31 cfg = config.documentation;
37 instance = f (mapAttrs (n: _: abort "evaluating ${n} for `meta` failed") (functionArgs f));
39 cfg.nixos.options.splitBuild
43 && instance.meta.buildDocsInSandbox or true;
47 p = partition canCacheDocs (baseModules ++ cfg.nixos.extraModules);
51 eager = p.wrong ++ optionals cfg.nixos.includeAllModules (extraModules ++ modules);
54 manual = import ../../doc/manual rec {
56 version = config.system.nixos.release;
57 revision = "release-${version}";
58 extraSources = cfg.nixos.extraModuleSources;
61 scrubbedEval = evalModules {
63 _module.check = false;
64 } ] ++ docModules.eager;
66 specialArgs = specialArgs // {
67 pkgs = scrubDerivations "pkgs" pkgs;
68 # allow access to arbitrary options for eager modules, eg for getting
69 # option types from lazy modules
71 inherit modulesPath utils;
74 scrubDerivations = namePrefix: pkgSet: mapAttrs
77 wholeName = "${namePrefix}.${name}";
78 guard = warn "Attempt to evaluate package ${wholeName} in option documentation; this is not supported and will eventually be an error. Use `mkPackageOption{,MD}` or `literalExpression` instead.";
79 in if isAttrs value then
80 scrubDerivations wholeName value
81 // optionalAttrs (isDerivation value) {
82 outPath = guard "\${${wholeName}}";
83 drvPath = guard value.drvPath;
88 in scrubbedEval.options;
96 && (t == "directory" -> baseNameOf n != "tests")
97 && (t == "file" -> hasSuffix ".nix" n)
100 pkgs.runCommand "lazy-options.json" {
101 libPath = filter (pkgs.path + "/lib");
102 pkgsLibPath = filter (pkgs.path + "/pkgs/pkgs-lib");
103 nixosPath = filter (pkgs.path + "/nixos");
104 NIX_ABORT_ON_WARN = warningsAreErrors;
107 + concatMapStringsSep " " (p: ''"${removePrefix "${modulesPath}/" (toString p)}"'') docModules.lazy
109 passAsFile = [ "modules" ];
111 export NIX_STORE_DIR=$TMPDIR/store
112 export NIX_STATE_DIR=$TMPDIR/state
113 ${pkgs.buildPackages.nix}/bin/nix-instantiate \
115 --eval --json --strict \
116 --argstr libPath "$libPath" \
117 --argstr pkgsLibPath "$pkgsLibPath" \
118 --argstr nixosPath "$nixosPath" \
119 --arg modules "import $modulesPath" \
120 --argstr stateVersion "${options.system.stateVersion.default}" \
121 --argstr release "${config.system.nixos.release}" \
122 $nixosPath/lib/eval-cacheable-options.nix > $out \
125 echo 'Cacheable portion of option doc build failed.'
126 echo 'Usually this means that an option attribute that ends up in documentation (eg' \
127 '`default` or `description`) depends on the restricted module arguments' \
128 '`config` or `pkgs`.'
130 echo 'Rebuild your configuration with `--show-trace` to find the offending' \
131 'location. Remove the references to restricted arguments (eg by escaping' \
132 'their antiquotations or adding a `defaultText`) or disable the sandboxed' \
133 'build for the failing module by setting `meta.buildDocsInSandbox = false`.'
139 inherit (cfg.nixos.options) warningsAreErrors;
144 helpScript = pkgs.writeShellScriptBin "nixos-help" ''
145 # Finds first executable browser in a colon-separated list.
146 # (see how xdg-open defines BROWSER)
148 IFS=: ; for b in $BROWSER; do
149 [ -n "$(type -P "$b" || true)" ] && echo "$b" && break
152 if [ -z "$browser" ]; then
153 browser="$(type -P xdg-open || true)"
154 if [ -z "$browser" ]; then
155 browser="${pkgs.w3m-nographics}/bin/w3m"
158 exec "$browser" ${manual.manualHTMLIndex}
161 desktopItem = pkgs.makeDesktopItem {
162 name = "nixos-manual";
163 desktopName = "NixOS Manual";
164 genericName = "System Manual";
165 comment = "View NixOS documentation in a web browser";
166 icon = "nix-snowflake";
168 categories = ["System"];
171 in pkgs.symlinkJoin {
187 ../config/system-path.nix
188 ../system/etc/etc.nix
189 (mkRenamedOptionModule [ "programs" "info" "enable" ] [ "documentation" "info" "enable" ])
190 (mkRenamedOptionModule [ "programs" "man" "enable" ] [ "documentation" "man" "enable" ])
191 (mkRenamedOptionModule [ "services" "nixosManual" "enable" ] [ "documentation" "nixos" "enable" ])
192 (mkRemovedOptionModule
193 [ "documentation" "nixos" "options" "allowDocBook" ]
194 "DocBook option documentation is no longer supported")
205 Whether to install documentation of packages from
206 {option}`environment.systemPackages` into the generated system path.
208 See "Multiple-output packages" chapter in the nixpkgs manual for more info.
210 # which is at ../../../doc/multiple-output.chapter.md
213 man.enable = mkOption {
217 Whether to install manual pages.
218 This also includes `man` outputs.
222 man.generateCaches = mkOption {
226 Whether to generate the manual page index caches.
227 This allows searching for a page or
228 keyword using utilities like {manpage}`apropos(1)`
229 and the `-k` option of
234 info.enable = mkOption {
238 Whether to install info pages and the {command}`info` command.
239 This also includes "info" outputs.
243 doc.enable = mkOption {
247 Whether to install documentation distributed in packages' `/share/doc`.
248 Usually plain text and/or HTML.
249 This also includes "doc" outputs.
253 dev.enable = mkOption {
257 Whether to install documentation targeted at developers.
258 * This includes man pages targeted at developers if {option}`documentation.man.enable` is
259 set (this also includes "devman" outputs).
260 * This includes info pages targeted at developers if {option}`documentation.info.enable`
261 is set (this also includes "devinfo" outputs).
262 * This includes other pages targeted at developers if {option}`documentation.doc.enable`
263 is set (this also includes "devdoc" outputs).
267 nixos.enable = mkOption {
271 Whether to install NixOS's own documentation.
273 - This includes man pages like
274 {manpage}`configuration.nix(5)` if {option}`documentation.man.enable` is
276 - This includes the HTML manual and the {command}`nixos-help` command if
277 {option}`documentation.doc.enable` is set.
281 nixos.extraModules = mkOption {
282 type = types.listOf types.raw;
285 Modules for which to show options even when not imported.
289 nixos.options.splitBuild = mkOption {
293 Whether to split the option docs build into a cacheable and an uncacheable part.
294 Splitting the build can substantially decrease the amount of time needed to build
295 the manual, but some user modules may be incompatible with this splitting.
299 nixos.options.warningsAreErrors = mkOption {
303 Treat warning emitted during the option documentation build (eg for missing option
304 descriptions) as errors.
308 nixos.includeAllModules = mkOption {
312 Whether the generated NixOS's documentation should include documentation for all
313 the options from all the NixOS modules included in the current
314 `configuration.nix`. Disabling this will make the manual
315 generator to ignore options defined outside of `baseModules`.
319 nixos.extraModuleSources = mkOption {
320 type = types.listOf (types.either types.path types.str);
323 Which extra NixOS module paths the generated NixOS's documentation should strip
326 example = literalExpression ''
327 # e.g. with options from modules in ''${pkgs.customModules}/nix:
328 [ pkgs.customModules ]
336 config = mkIf cfg.enable (mkMerge [
340 assertion = !(cfg.man.man-db.enable && cfg.man.mandoc.enable);
342 man-db and mandoc can't be used as the default man page viewer at the same time!
348 # The actual implementation for this lives in man-db.nix or mandoc.nix,
349 # depending on which backend is active.
350 (mkIf cfg.man.enable {
351 environment.pathsToLink = [ "/share/man" ];
352 environment.extraOutputsToInstall = [ "man" ] ++ optional cfg.dev.enable "devman";
355 (mkIf cfg.info.enable {
356 environment.systemPackages = [ pkgs.texinfoInteractive ];
357 environment.pathsToLink = [ "/share/info" ];
358 environment.extraOutputsToInstall = [ "info" ] ++ optional cfg.dev.enable "devinfo";
359 environment.extraSetup = ''
360 if [ -w $out/share/info ]; then
362 for i in $out/share/info/*.info $out/share/info/*.info.gz; do
363 ${pkgs.buildPackages.texinfo}/bin/install-info $i $out/share/info/dir
369 (mkIf cfg.doc.enable {
370 environment.pathsToLink = [ "/share/doc" ];
371 environment.extraOutputsToInstall = [ "doc" ] ++ optional cfg.dev.enable "devdoc";
374 (mkIf cfg.nixos.enable {
375 system.build.manual = manual;
377 environment.systemPackages = []
378 ++ optional cfg.man.enable manual.nixos-configuration-reference-manpage
379 ++ optionals cfg.doc.enable [ manual.manualHTML nixos-help ];