1 { config, options, lib, pkgs, utils, modules, baseModules, extraModules, modulesPath, specialArgs, ... }:
7 cfg = config.documentation;
13 instance = f (mapAttrs (n: _: abort "evaluating ${n} for `meta` failed") (functionArgs f));
15 cfg.nixos.options.splitBuild
19 && instance.meta.buildDocsInSandbox or true;
23 p = partition canCacheDocs (baseModules ++ cfg.nixos.extraModules);
27 eager = p.wrong ++ optionals cfg.nixos.includeAllModules (extraModules ++ modules);
30 manual = import ../../doc/manual rec {
32 version = config.system.nixos.release;
33 revision = "release-${version}";
34 extraSources = cfg.nixos.extraModuleSources;
37 scrubbedEval = evalModules {
39 _module.check = false;
40 } ] ++ docModules.eager;
41 specialArgs = specialArgs // {
42 pkgs = scrubDerivations "pkgs" pkgs;
43 # allow access to arbitrary options for eager modules, eg for getting
44 # option types from lazy modules
46 inherit modulesPath utils;
49 scrubDerivations = namePrefix: pkgSet: mapAttrs
51 let wholeName = "${namePrefix}.${name}"; in
53 scrubDerivations wholeName value
54 // (optionalAttrs (isDerivation value) { outPath = "\${${wholeName}}"; })
58 in scrubbedEval.options;
66 && (t == "directory" -> baseNameOf n != "tests")
67 && (t == "file" -> hasSuffix ".nix" n)
70 pkgs.runCommand "lazy-options.json" {
71 libPath = filter (pkgs.path + "/lib");
72 pkgsLibPath = filter (pkgs.path + "/pkgs/pkgs-lib");
73 nixosPath = filter (pkgs.path + "/nixos");
74 modules = map (p: ''"${removePrefix "${modulesPath}/" (toString p)}"'') docModules.lazy;
76 export NIX_STORE_DIR=$TMPDIR/store
77 export NIX_STATE_DIR=$TMPDIR/state
78 ${pkgs.buildPackages.nix}/bin/nix-instantiate \
80 --eval --json --strict \
81 --argstr libPath "$libPath" \
82 --argstr pkgsLibPath "$pkgsLibPath" \
83 --argstr nixosPath "$nixosPath" \
84 --arg modules "[ $modules ]" \
85 --argstr stateVersion "${options.system.stateVersion.default}" \
86 --argstr release "${config.system.nixos.release}" \
87 $nixosPath/lib/eval-cacheable-options.nix > $out \
90 echo 'Cacheable portion of option doc build failed.'
91 echo 'Usually this means that an option attribute that ends up in documentation (eg' \
92 '`default` or `description`) depends on the restricted module arguments' \
95 echo 'Rebuild your configuration with `--show-trace` to find the offending' \
96 'location. Remove the references to restricted arguments (eg by escaping' \
97 'their antiquotations or adding a `defaultText`) or disable the sandboxed' \
98 'build for the failing module by setting `meta.buildDocsInSandbox = false`.'
104 inherit (cfg.nixos.options) warningsAreErrors allowDocBook;
109 helpScript = pkgs.writeShellScriptBin "nixos-help" ''
110 # Finds first executable browser in a colon-separated list.
111 # (see how xdg-open defines BROWSER)
113 IFS=: ; for b in $BROWSER; do
114 [ -n "$(type -P "$b" || true)" ] && echo "$b" && break
117 if [ -z "$browser" ]; then
118 browser="$(type -P xdg-open || true)"
119 if [ -z "$browser" ]; then
120 browser="${pkgs.w3m-nographics}/bin/w3m"
123 exec "$browser" ${manual.manualHTMLIndex}
126 desktopItem = pkgs.makeDesktopItem {
127 name = "nixos-manual";
128 desktopName = "NixOS Manual";
129 genericName = "View NixOS documentation in a web browser";
130 icon = "nix-snowflake";
132 categories = ["System"];
135 in pkgs.symlinkJoin {
151 ../config/system-path.nix
152 ../system/etc/etc.nix
153 (mkRenamedOptionModule [ "programs" "info" "enable" ] [ "documentation" "info" "enable" ])
154 (mkRenamedOptionModule [ "programs" "man" "enable" ] [ "documentation" "man" "enable" ])
155 (mkRenamedOptionModule [ "services" "nixosManual" "enable" ] [ "documentation" "nixos" "enable" ])
165 description = lib.mdDoc ''
166 Whether to install documentation of packages from
167 {option}`environment.systemPackages` into the generated system path.
169 See "Multiple-output packages" chapter in the nixpkgs manual for more info.
171 # which is at ../../../doc/multiple-output.chapter.md
174 man.enable = mkOption {
177 description = lib.mdDoc ''
178 Whether to install manual pages.
179 This also includes `man` outputs.
183 man.generateCaches = mkOption {
186 description = mdDoc ''
187 Whether to generate the manual page index caches.
188 This allows searching for a page or
189 keyword using utilities like {manpage}`apropos(1)`
190 and the `-k` option of
195 info.enable = mkOption {
198 description = lib.mdDoc ''
199 Whether to install info pages and the {command}`info` command.
200 This also includes "info" outputs.
204 doc.enable = mkOption {
207 description = lib.mdDoc ''
208 Whether to install documentation distributed in packages' `/share/doc`.
209 Usually plain text and/or HTML.
210 This also includes "doc" outputs.
214 dev.enable = mkOption {
217 description = mdDoc ''
218 Whether to install documentation targeted at developers.
219 * This includes man pages targeted at developers if {option}`documentation.man.enable` is
220 set (this also includes "devman" outputs).
221 * This includes info pages targeted at developers if {option}`documentation.info.enable`
222 is set (this also includes "devinfo" outputs).
223 * This includes other pages targeted at developers if {option}`documentation.doc.enable`
224 is set (this also includes "devdoc" outputs).
228 nixos.enable = mkOption {
231 description = lib.mdDoc ''
232 Whether to install NixOS's own documentation.
234 - This includes man pages like
235 {manpage}`configuration.nix(5)` if {option}`documentation.man.enable` is
237 - This includes the HTML manual and the {command}`nixos-help` command if
238 {option}`documentation.doc.enable` is set.
242 nixos.extraModules = mkOption {
243 type = types.listOf types.raw;
245 description = lib.mdDoc ''
246 Modules for which to show options even when not imported.
250 nixos.options.splitBuild = mkOption {
253 description = lib.mdDoc ''
254 Whether to split the option docs build into a cacheable and an uncacheable part.
255 Splitting the build can substantially decrease the amount of time needed to build
256 the manual, but some user modules may be incompatible with this splitting.
260 nixos.options.allowDocBook = mkOption {
263 description = lib.mdDoc ''
264 Whether to allow DocBook option docs. When set to `false` all option using
265 DocBook documentation will cause a manual build error; additionally a new
266 renderer may be used.
269 The `false` setting for this option is not yet fully supported. While it
270 should work fine and produce the same output as the previous toolchain
271 using DocBook it may not work in all circumstances. Whether markdown option
272 documentation is allowed is independent of this option.
277 nixos.options.warningsAreErrors = mkOption {
280 description = lib.mdDoc ''
281 Treat warning emitted during the option documentation build (eg for missing option
282 descriptions) as errors.
286 nixos.includeAllModules = mkOption {
289 description = lib.mdDoc ''
290 Whether the generated NixOS's documentation should include documentation for all
291 the options from all the NixOS modules included in the current
292 `configuration.nix`. Disabling this will make the manual
293 generator to ignore options defined outside of `baseModules`.
297 nixos.extraModuleSources = mkOption {
298 type = types.listOf (types.either types.path types.str);
300 description = lib.mdDoc ''
301 Which extra NixOS module paths the generated NixOS's documentation should strip
304 example = literalExpression ''
305 # e.g. with options from modules in ''${pkgs.customModules}/nix:
306 [ pkgs.customModules ]
314 config = mkIf cfg.enable (mkMerge [
318 assertion = !(cfg.man.man-db.enable && cfg.man.mandoc.enable);
320 man-db and mandoc can't be used as the default man page viewer at the same time!
326 # The actual implementation for this lives in man-db.nix or mandoc.nix,
327 # depending on which backend is active.
328 (mkIf cfg.man.enable {
329 environment.pathsToLink = [ "/share/man" ];
330 environment.extraOutputsToInstall = [ "man" ] ++ optional cfg.dev.enable "devman";
333 (mkIf cfg.info.enable {
334 environment.systemPackages = [ pkgs.texinfoInteractive ];
335 environment.pathsToLink = [ "/share/info" ];
336 environment.extraOutputsToInstall = [ "info" ] ++ optional cfg.dev.enable "devinfo";
337 environment.extraSetup = ''
338 if [ -w $out/share/info ]; then
340 for i in $out/share/info/*.info $out/share/info/*.info.gz; do
341 ${pkgs.buildPackages.texinfo}/bin/install-info $i $out/share/info/dir
347 (mkIf cfg.doc.enable {
348 environment.pathsToLink = [ "/share/doc" ];
349 environment.extraOutputsToInstall = [ "doc" ] ++ optional cfg.dev.enable "devdoc";
352 (mkIf cfg.nixos.enable {
353 system.build.manual = manual;
355 environment.systemPackages = []
356 ++ optional cfg.man.enable manual.manpages
357 ++ optionals cfg.doc.enable [ manual.manualHTML nixos-help ];