at 23.05-pre 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 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 45 options = allOpts; 46 inherit modulesPath utils; 47 }; 48 }; 49 scrubDerivations = namePrefix: pkgSet: mapAttrs 50 (name: value: 51 let wholeName = "${namePrefix}.${name}"; in 52 if isAttrs value then 53 scrubDerivations wholeName value 54 // (optionalAttrs (isDerivation value) { outPath = "\${${wholeName}}"; }) 55 else value 56 ) 57 pkgSet; 58 in scrubbedEval.options; 59 60 baseOptionsJSON = 61 let 62 filter = 63 builtins.filterSource 64 (n: t: 65 cleanSourceFilter n t 66 && (t == "directory" -> baseNameOf n != "tests") 67 && (t == "file" -> hasSuffix ".nix" n) 68 ); 69 in 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; 75 } '' 76 export NIX_STORE_DIR=$TMPDIR/store 77 export NIX_STATE_DIR=$TMPDIR/state 78 ${pkgs.buildPackages.nix}/bin/nix-instantiate \ 79 --show-trace \ 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 \ 88 || { 89 echo -en "\e[1;31m" 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' \ 93 '`config` or `pkgs`.' 94 echo 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`.' 99 echo -en "\e[0m" 100 exit 1 101 } >&2 102 ''; 103 104 inherit (cfg.nixos.options) warningsAreErrors allowDocBook; 105 }; 106 107 108 nixos-help = let 109 helpScript = pkgs.writeShellScriptBin "nixos-help" '' 110 # Finds first executable browser in a colon-separated list. 111 # (see how xdg-open defines BROWSER) 112 browser="$( 113 IFS=: ; for b in $BROWSER; do 114 [ -n "$(type -P "$b" || true)" ] && echo "$b" && break 115 done 116 )" 117 if [ -z "$browser" ]; then 118 browser="$(type -P xdg-open || true)" 119 if [ -z "$browser" ]; then 120 browser="${pkgs.w3m-nographics}/bin/w3m" 121 fi 122 fi 123 exec "$browser" ${manual.manualHTMLIndex} 124 ''; 125 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"; 131 exec = "nixos-help"; 132 categories = ["System"]; 133 }; 134 135 in pkgs.symlinkJoin { 136 name = "nixos-help"; 137 paths = [ 138 helpScript 139 desktopItem 140 ]; 141 }; 142 143in 144 145{ 146 imports = [ 147 ./man-db.nix 148 ./mandoc.nix 149 ./assertions.nix 150 ./meta.nix 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" ]) 156 ]; 157 158 options = { 159 160 documentation = { 161 162 enable = mkOption { 163 type = types.bool; 164 default = true; 165 description = lib.mdDoc '' 166 Whether to install documentation of packages from 167 {option}`environment.systemPackages` into the generated system path. 168 169 See "Multiple-output packages" chapter in the nixpkgs manual for more info. 170 ''; 171 # which is at ../../../doc/multiple-output.chapter.md 172 }; 173 174 man.enable = mkOption { 175 type = types.bool; 176 default = true; 177 description = lib.mdDoc '' 178 Whether to install manual pages. 179 This also includes `man` outputs. 180 ''; 181 }; 182 183 man.generateCaches = mkOption { 184 type = types.bool; 185 default = false; 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 191 {manpage}`man(1)`. 192 ''; 193 }; 194 195 info.enable = mkOption { 196 type = types.bool; 197 default = true; 198 description = lib.mdDoc '' 199 Whether to install info pages and the {command}`info` command. 200 This also includes "info" outputs. 201 ''; 202 }; 203 204 doc.enable = mkOption { 205 type = types.bool; 206 default = true; 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. 211 ''; 212 }; 213 214 dev.enable = mkOption { 215 type = types.bool; 216 default = false; 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). 225 ''; 226 }; 227 228 nixos.enable = mkOption { 229 type = types.bool; 230 default = true; 231 description = lib.mdDoc '' 232 Whether to install NixOS's own documentation. 233 234 - This includes man pages like 235 {manpage}`configuration.nix(5)` if {option}`documentation.man.enable` is 236 set. 237 - This includes the HTML manual and the {command}`nixos-help` command if 238 {option}`documentation.doc.enable` is set. 239 ''; 240 }; 241 242 nixos.extraModules = mkOption { 243 type = types.listOf types.raw; 244 default = []; 245 description = lib.mdDoc '' 246 Modules for which to show options even when not imported. 247 ''; 248 }; 249 250 nixos.options.splitBuild = mkOption { 251 type = types.bool; 252 default = true; 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. 257 ''; 258 }; 259 260 nixos.options.allowDocBook = mkOption { 261 type = types.bool; 262 default = true; 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. 267 268 ::: {.note} 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. 273 ::: 274 ''; 275 }; 276 277 nixos.options.warningsAreErrors = mkOption { 278 type = types.bool; 279 default = true; 280 description = lib.mdDoc '' 281 Treat warning emitted during the option documentation build (eg for missing option 282 descriptions) as errors. 283 ''; 284 }; 285 286 nixos.includeAllModules = mkOption { 287 type = types.bool; 288 default = false; 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`. 294 ''; 295 }; 296 297 nixos.extraModuleSources = mkOption { 298 type = types.listOf (types.either types.path types.str); 299 default = [ ]; 300 description = lib.mdDoc '' 301 Which extra NixOS module paths the generated NixOS's documentation should strip 302 from options. 303 ''; 304 example = literalExpression '' 305 # e.g. with options from modules in ''${pkgs.customModules}/nix: 306 [ pkgs.customModules ] 307 ''; 308 }; 309 310 }; 311 312 }; 313 314 config = mkIf cfg.enable (mkMerge [ 315 { 316 assertions = [ 317 { 318 assertion = !(cfg.man.man-db.enable && cfg.man.mandoc.enable); 319 message = '' 320 man-db and mandoc can't be used as the default man page viewer at the same time! 321 ''; 322 } 323 ]; 324 } 325 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"; 331 }) 332 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 339 shopt -s nullglob 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 342 done 343 fi 344 ''; 345 }) 346 347 (mkIf cfg.doc.enable { 348 environment.pathsToLink = [ "/share/doc" ]; 349 environment.extraOutputsToInstall = [ "doc" ] ++ optional cfg.dev.enable "devdoc"; 350 }) 351 352 (mkIf cfg.nixos.enable { 353 system.build.manual = manual; 354 355 environment.systemPackages = [] 356 ++ optional cfg.man.enable manual.manpages 357 ++ optionals cfg.doc.enable [ manual.manualHTML nixos-help ]; 358 }) 359 360 ]); 361 362}