at 23.11-beta 12 kB view raw
1{ config, options, lib, pkgs, utils, modules, baseModules, extraModules, modulesPath, specialArgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.documentation; 8 allOpts = options; 9 10 canCacheDocs = m: 11 let 12 f = import m; 13 instance = f (mapAttrs (n: _: abort "evaluating ${n} for `meta` failed") (functionArgs f)); 14 in 15 cfg.nixos.options.splitBuild 16 && builtins.isPath m 17 && isFunction f 18 && instance ? options 19 && instance.meta.buildDocsInSandbox or true; 20 21 docModules = 22 let 23 p = partition canCacheDocs (baseModules ++ cfg.nixos.extraModules); 24 in 25 { 26 lazy = p.right; 27 eager = p.wrong ++ optionals cfg.nixos.includeAllModules (extraModules ++ modules); 28 }; 29 30 manual = import ../../doc/manual rec { 31 inherit pkgs config; 32 version = config.system.nixos.release; 33 revision = "release-${version}"; 34 extraSources = cfg.nixos.extraModuleSources; 35 options = 36 let 37 scrubbedEval = evalModules { 38 modules = [ { 39 _module.check = false; 40 } ] ++ docModules.eager; 41 class = "nixos"; 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 46 options = allOpts; 47 inherit modulesPath utils; 48 }; 49 }; 50 scrubDerivations = namePrefix: pkgSet: mapAttrs 51 (name: value: 52 let 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; 60 } 61 else value 62 ) 63 pkgSet; 64 in scrubbedEval.options; 65 66 baseOptionsJSON = 67 let 68 filter = 69 builtins.filterSource 70 (n: t: 71 cleanSourceFilter n t 72 && (t == "directory" -> baseNameOf n != "tests") 73 && (t == "file" -> hasSuffix ".nix" n) 74 ); 75 in 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; 81 } '' 82 export NIX_STORE_DIR=$TMPDIR/store 83 export NIX_STATE_DIR=$TMPDIR/state 84 ${pkgs.buildPackages.nix}/bin/nix-instantiate \ 85 --show-trace \ 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 \ 94 || { 95 echo -en "\e[1;31m" 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' \ 99 '`config` or `pkgs`.' 100 echo 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`.' 105 echo -en "\e[0m" 106 exit 1 107 } >&2 108 ''; 109 110 inherit (cfg.nixos.options) warningsAreErrors; 111 }; 112 113 114 nixos-help = let 115 helpScript = pkgs.writeShellScriptBin "nixos-help" '' 116 # Finds first executable browser in a colon-separated list. 117 # (see how xdg-open defines BROWSER) 118 browser="$( 119 IFS=: ; for b in $BROWSER; do 120 [ -n "$(type -P "$b" || true)" ] && echo "$b" && break 121 done 122 )" 123 if [ -z "$browser" ]; then 124 browser="$(type -P xdg-open || true)" 125 if [ -z "$browser" ]; then 126 browser="${pkgs.w3m-nographics}/bin/w3m" 127 fi 128 fi 129 exec "$browser" ${manual.manualHTMLIndex} 130 ''; 131 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"; 138 exec = "nixos-help"; 139 categories = ["System"]; 140 }; 141 142 in pkgs.symlinkJoin { 143 name = "nixos-help"; 144 paths = [ 145 helpScript 146 desktopItem 147 ]; 148 }; 149 150in 151 152{ 153 imports = [ 154 ./man-db.nix 155 ./mandoc.nix 156 ./assertions.nix 157 ./meta.nix 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") 166 ]; 167 168 options = { 169 170 documentation = { 171 172 enable = mkOption { 173 type = types.bool; 174 default = true; 175 description = lib.mdDoc '' 176 Whether to install documentation of packages from 177 {option}`environment.systemPackages` into the generated system path. 178 179 See "Multiple-output packages" chapter in the nixpkgs manual for more info. 180 ''; 181 # which is at ../../../doc/multiple-output.chapter.md 182 }; 183 184 man.enable = mkOption { 185 type = types.bool; 186 default = true; 187 description = lib.mdDoc '' 188 Whether to install manual pages. 189 This also includes `man` outputs. 190 ''; 191 }; 192 193 man.generateCaches = mkOption { 194 type = types.bool; 195 default = false; 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 201 {manpage}`man(1)`. 202 ''; 203 }; 204 205 info.enable = mkOption { 206 type = types.bool; 207 default = true; 208 description = lib.mdDoc '' 209 Whether to install info pages and the {command}`info` command. 210 This also includes "info" outputs. 211 ''; 212 }; 213 214 doc.enable = mkOption { 215 type = types.bool; 216 default = true; 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. 221 ''; 222 }; 223 224 dev.enable = mkOption { 225 type = types.bool; 226 default = false; 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). 235 ''; 236 }; 237 238 nixos.enable = mkOption { 239 type = types.bool; 240 default = true; 241 description = lib.mdDoc '' 242 Whether to install NixOS's own documentation. 243 244 - This includes man pages like 245 {manpage}`configuration.nix(5)` if {option}`documentation.man.enable` is 246 set. 247 - This includes the HTML manual and the {command}`nixos-help` command if 248 {option}`documentation.doc.enable` is set. 249 ''; 250 }; 251 252 nixos.extraModules = mkOption { 253 type = types.listOf types.raw; 254 default = []; 255 description = lib.mdDoc '' 256 Modules for which to show options even when not imported. 257 ''; 258 }; 259 260 nixos.options.splitBuild = mkOption { 261 type = types.bool; 262 default = true; 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. 267 ''; 268 }; 269 270 nixos.options.warningsAreErrors = mkOption { 271 type = types.bool; 272 default = true; 273 description = lib.mdDoc '' 274 Treat warning emitted during the option documentation build (eg for missing option 275 descriptions) as errors. 276 ''; 277 }; 278 279 nixos.includeAllModules = mkOption { 280 type = types.bool; 281 default = false; 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`. 287 ''; 288 }; 289 290 nixos.extraModuleSources = mkOption { 291 type = types.listOf (types.either types.path types.str); 292 default = [ ]; 293 description = lib.mdDoc '' 294 Which extra NixOS module paths the generated NixOS's documentation should strip 295 from options. 296 ''; 297 example = literalExpression '' 298 # e.g. with options from modules in ''${pkgs.customModules}/nix: 299 [ pkgs.customModules ] 300 ''; 301 }; 302 303 }; 304 305 }; 306 307 config = mkIf cfg.enable (mkMerge [ 308 { 309 assertions = [ 310 { 311 assertion = !(cfg.man.man-db.enable && cfg.man.mandoc.enable); 312 message = '' 313 man-db and mandoc can't be used as the default man page viewer at the same time! 314 ''; 315 } 316 ]; 317 } 318 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"; 324 }) 325 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 332 shopt -s nullglob 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 335 done 336 fi 337 ''; 338 }) 339 340 (mkIf cfg.doc.enable { 341 environment.pathsToLink = [ "/share/doc" ]; 342 environment.extraOutputsToInstall = [ "doc" ] ++ optional cfg.dev.enable "devdoc"; 343 }) 344 345 (mkIf cfg.nixos.enable { 346 system.build.manual = manual; 347 348 environment.systemPackages = [] 349 ++ optional cfg.man.enable manual.nixos-configuration-reference-manpage 350 ++ optionals cfg.doc.enable [ manual.manualHTML nixos-help ]; 351 }) 352 353 ]); 354 355}