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;
42 specialArgs = specialArgs // {
43 pkgs = scrubDerivations "pkgs" pkgs;
44 # allow access to arbitrary options for eager modules, eg for getting
45 # option types from lazy modules
47 inherit modulesPath utils;
50 scrubDerivations = namePrefix: pkgSet: mapAttrs
53 wholeName = "${namePrefix}.${name}";
54 guard = lib.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.";
55 in if isAttrs value then
56 scrubDerivations wholeName value
57 // optionalAttrs (isDerivation value) {
58 outPath = guard "\${${wholeName}}";
59 drvPath = guard drvPath;
64 in scrubbedEval.options;
72 && (t == "directory" -> baseNameOf n != "tests")
73 && (t == "file" -> hasSuffix ".nix" n)
76 pkgs.runCommand "lazy-options.json" {
77 libPath = filter (pkgs.path + "/lib");
78 pkgsLibPath = filter (pkgs.path + "/pkgs/pkgs-lib");
79 nixosPath = filter (pkgs.path + "/nixos");
80 modules = map (p: ''"${removePrefix "${modulesPath}/" (toString p)}"'') docModules.lazy;
82 export NIX_STORE_DIR=$TMPDIR/store
83 export NIX_STATE_DIR=$TMPDIR/state
84 ${pkgs.buildPackages.nix}/bin/nix-instantiate \
86 --eval --json --strict \
87 --argstr libPath "$libPath" \
88 --argstr pkgsLibPath "$pkgsLibPath" \
89 --argstr nixosPath "$nixosPath" \
90 --arg modules "[ $modules ]" \
91 --argstr stateVersion "${options.system.stateVersion.default}" \
92 --argstr release "${config.system.nixos.release}" \
93 $nixosPath/lib/eval-cacheable-options.nix > $out \
96 echo 'Cacheable portion of option doc build failed.'
97 echo 'Usually this means that an option attribute that ends up in documentation (eg' \
98 '`default` or `description`) depends on the restricted module arguments' \
101 echo 'Rebuild your configuration with `--show-trace` to find the offending' \
102 'location. Remove the references to restricted arguments (eg by escaping' \
103 'their antiquotations or adding a `defaultText`) or disable the sandboxed' \
104 'build for the failing module by setting `meta.buildDocsInSandbox = false`.'
110 inherit (cfg.nixos.options) warningsAreErrors;
115 helpScript = pkgs.writeShellScriptBin "nixos-help" ''
116 # Finds first executable browser in a colon-separated list.
117 # (see how xdg-open defines BROWSER)
119 IFS=: ; for b in $BROWSER; do
120 [ -n "$(type -P "$b" || true)" ] && echo "$b" && break
123 if [ -z "$browser" ]; then
124 browser="$(type -P xdg-open || true)"
125 if [ -z "$browser" ]; then
126 browser="${pkgs.w3m-nographics}/bin/w3m"
129 exec "$browser" ${manual.manualHTMLIndex}
132 desktopItem = pkgs.makeDesktopItem {
133 name = "nixos-manual";
134 desktopName = "NixOS Manual";
135 genericName = "System Manual";
136 comment = "View NixOS documentation in a web browser";
137 icon = "nix-snowflake";
139 categories = ["System"];
142 in pkgs.symlinkJoin {
158 ../config/system-path.nix
159 ../system/etc/etc.nix
160 (mkRenamedOptionModule [ "programs" "info" "enable" ] [ "documentation" "info" "enable" ])
161 (mkRenamedOptionModule [ "programs" "man" "enable" ] [ "documentation" "man" "enable" ])
162 (mkRenamedOptionModule [ "services" "nixosManual" "enable" ] [ "documentation" "nixos" "enable" ])
163 (mkRemovedOptionModule
164 [ "documentation" "nixos" "options" "allowDocBook" ]
165 "DocBook option documentation is no longer supported")
175 description = lib.mdDoc ''
176 Whether to install documentation of packages from
177 {option}`environment.systemPackages` into the generated system path.
179 See "Multiple-output packages" chapter in the nixpkgs manual for more info.
181 # which is at ../../../doc/multiple-output.chapter.md
184 man.enable = mkOption {
187 description = lib.mdDoc ''
188 Whether to install manual pages.
189 This also includes `man` outputs.
193 man.generateCaches = mkOption {
196 description = mdDoc ''
197 Whether to generate the manual page index caches.
198 This allows searching for a page or
199 keyword using utilities like {manpage}`apropos(1)`
200 and the `-k` option of
205 info.enable = mkOption {
208 description = lib.mdDoc ''
209 Whether to install info pages and the {command}`info` command.
210 This also includes "info" outputs.
214 doc.enable = mkOption {
217 description = lib.mdDoc ''
218 Whether to install documentation distributed in packages' `/share/doc`.
219 Usually plain text and/or HTML.
220 This also includes "doc" outputs.
224 dev.enable = mkOption {
227 description = mdDoc ''
228 Whether to install documentation targeted at developers.
229 * This includes man pages targeted at developers if {option}`documentation.man.enable` is
230 set (this also includes "devman" outputs).
231 * This includes info pages targeted at developers if {option}`documentation.info.enable`
232 is set (this also includes "devinfo" outputs).
233 * This includes other pages targeted at developers if {option}`documentation.doc.enable`
234 is set (this also includes "devdoc" outputs).
238 nixos.enable = mkOption {
241 description = lib.mdDoc ''
242 Whether to install NixOS's own documentation.
244 - This includes man pages like
245 {manpage}`configuration.nix(5)` if {option}`documentation.man.enable` is
247 - This includes the HTML manual and the {command}`nixos-help` command if
248 {option}`documentation.doc.enable` is set.
252 nixos.extraModules = mkOption {
253 type = types.listOf types.raw;
255 description = lib.mdDoc ''
256 Modules for which to show options even when not imported.
260 nixos.options.splitBuild = mkOption {
263 description = lib.mdDoc ''
264 Whether to split the option docs build into a cacheable and an uncacheable part.
265 Splitting the build can substantially decrease the amount of time needed to build
266 the manual, but some user modules may be incompatible with this splitting.
270 nixos.options.warningsAreErrors = mkOption {
273 description = lib.mdDoc ''
274 Treat warning emitted during the option documentation build (eg for missing option
275 descriptions) as errors.
279 nixos.includeAllModules = mkOption {
282 description = lib.mdDoc ''
283 Whether the generated NixOS's documentation should include documentation for all
284 the options from all the NixOS modules included in the current
285 `configuration.nix`. Disabling this will make the manual
286 generator to ignore options defined outside of `baseModules`.
290 nixos.extraModuleSources = mkOption {
291 type = types.listOf (types.either types.path types.str);
293 description = lib.mdDoc ''
294 Which extra NixOS module paths the generated NixOS's documentation should strip
297 example = literalExpression ''
298 # e.g. with options from modules in ''${pkgs.customModules}/nix:
299 [ pkgs.customModules ]
307 config = mkIf cfg.enable (mkMerge [
311 assertion = !(cfg.man.man-db.enable && cfg.man.mandoc.enable);
313 man-db and mandoc can't be used as the default man page viewer at the same time!
319 # The actual implementation for this lives in man-db.nix or mandoc.nix,
320 # depending on which backend is active.
321 (mkIf cfg.man.enable {
322 environment.pathsToLink = [ "/share/man" ];
323 environment.extraOutputsToInstall = [ "man" ] ++ optional cfg.dev.enable "devman";
326 (mkIf cfg.info.enable {
327 environment.systemPackages = [ pkgs.texinfoInteractive ];
328 environment.pathsToLink = [ "/share/info" ];
329 environment.extraOutputsToInstall = [ "info" ] ++ optional cfg.dev.enable "devinfo";
330 environment.extraSetup = ''
331 if [ -w $out/share/info ]; then
333 for i in $out/share/info/*.info $out/share/info/*.info.gz; do
334 ${pkgs.buildPackages.texinfo}/bin/install-info $i $out/share/info/dir
340 (mkIf cfg.doc.enable {
341 environment.pathsToLink = [ "/share/doc" ];
342 environment.extraOutputsToInstall = [ "doc" ] ++ optional cfg.dev.enable "devdoc";
345 (mkIf cfg.nixos.enable {
346 system.build.manual = manual;
348 environment.systemPackages = []
349 ++ optional cfg.man.enable manual.nixos-configuration-reference-manpage
350 ++ optionals cfg.doc.enable [ manual.manualHTML nixos-help ];