at 23.11-beta 16 kB view raw
1{ config, options, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.nixpkgs; 7 opt = options.nixpkgs; 8 9 isConfig = x: 10 builtins.isAttrs x || lib.isFunction x; 11 12 optCall = f: x: 13 if lib.isFunction f 14 then f x 15 else f; 16 17 mergeConfig = lhs_: rhs_: 18 let 19 lhs = optCall lhs_ { inherit pkgs; }; 20 rhs = optCall rhs_ { inherit pkgs; }; 21 in 22 recursiveUpdate lhs rhs // 23 optionalAttrs (lhs ? packageOverrides) { 24 packageOverrides = pkgs: 25 optCall lhs.packageOverrides pkgs // 26 optCall (attrByPath [ "packageOverrides" ] { } rhs) pkgs; 27 } // 28 optionalAttrs (lhs ? perlPackageOverrides) { 29 perlPackageOverrides = pkgs: 30 optCall lhs.perlPackageOverrides pkgs // 31 optCall (attrByPath [ "perlPackageOverrides" ] { } rhs) pkgs; 32 }; 33 34 configType = mkOptionType { 35 name = "nixpkgs-config"; 36 description = "nixpkgs config"; 37 check = x: 38 let traceXIfNot = c: 39 if c x then true 40 else lib.traceSeqN 1 x false; 41 in traceXIfNot isConfig; 42 merge = args: foldr (def: mergeConfig def.value) {}; 43 }; 44 45 overlayType = mkOptionType { 46 name = "nixpkgs-overlay"; 47 description = "nixpkgs overlay"; 48 check = lib.isFunction; 49 merge = lib.mergeOneOption; 50 }; 51 52 pkgsType = types.pkgs // { 53 # This type is only used by itself, so let's elaborate the description a bit 54 # for the purpose of documentation. 55 description = "An evaluation of Nixpkgs; the top level attribute set of packages"; 56 }; 57 58 hasBuildPlatform = opt.buildPlatform.highestPrio < (mkOptionDefault {}).priority; 59 hasHostPlatform = opt.hostPlatform.isDefined; 60 hasPlatform = hasHostPlatform || hasBuildPlatform; 61 62 # Context for messages 63 hostPlatformLine = optionalString hasHostPlatform "${showOptionWithDefLocs opt.hostPlatform}"; 64 buildPlatformLine = optionalString hasBuildPlatform "${showOptionWithDefLocs opt.buildPlatform}"; 65 66 legacyOptionsDefined = 67 optional (opt.localSystem.highestPrio < (mkDefault {}).priority) opt.system 68 ++ optional (opt.localSystem.highestPrio < (mkOptionDefault {}).priority) opt.localSystem 69 ++ optional (opt.crossSystem.highestPrio < (mkOptionDefault {}).priority) opt.crossSystem 70 ; 71 72 defaultPkgs = 73 if opt.hostPlatform.isDefined 74 then 75 let isCross = cfg.buildPlatform != cfg.hostPlatform; 76 systemArgs = 77 if isCross 78 then { 79 localSystem = cfg.buildPlatform; 80 crossSystem = cfg.hostPlatform; 81 } 82 else { 83 localSystem = cfg.hostPlatform; 84 }; 85 in 86 import ../../.. ({ 87 inherit (cfg) config overlays; 88 } // systemArgs) 89 else 90 import ../../.. { 91 inherit (cfg) config overlays localSystem crossSystem; 92 }; 93 94 finalPkgs = if opt.pkgs.isDefined then cfg.pkgs.appendOverlays cfg.overlays else defaultPkgs; 95 96in 97 98{ 99 imports = [ 100 ./assertions.nix 101 ./meta.nix 102 (mkRemovedOptionModule [ "nixpkgs" "initialSystem" ] "The NixOS options `nesting.clone` and `nesting.children` have been deleted, and replaced with named specialisation. Therefore `nixpgks.initialSystem` has no effect anymore.") 103 ]; 104 105 options.nixpkgs = { 106 107 pkgs = mkOption { 108 defaultText = literalExpression '' 109 import "''${nixos}/.." { 110 inherit (cfg) config overlays localSystem crossSystem; 111 } 112 ''; 113 type = pkgsType; 114 example = literalExpression "import <nixpkgs> {}"; 115 description = lib.mdDoc '' 116 If set, the pkgs argument to all NixOS modules is the value of 117 this option, extended with `nixpkgs.overlays`, if 118 that is also set. Either `nixpkgs.crossSystem` or 119 `nixpkgs.localSystem` will be used in an assertion 120 to check that the NixOS and Nixpkgs architectures match. Any 121 other options in `nixpkgs.*`, notably `config`, 122 will be ignored. 123 124 If unset, the pkgs argument to all NixOS modules is determined 125 as shown in the default value for this option. 126 127 The default value imports the Nixpkgs source files 128 relative to the location of this NixOS module, because 129 NixOS and Nixpkgs are distributed together for consistency, 130 so the `nixos` in the default value is in fact a 131 relative path. The `config`, `overlays`, 132 `localSystem`, and `crossSystem` come 133 from this option's siblings. 134 135 This option can be used by applications like NixOps to increase 136 the performance of evaluation, or to create packages that depend 137 on a container that should be built with the exact same evaluation 138 of Nixpkgs, for example. Applications like this should set 139 their default value using `lib.mkDefault`, so 140 user-provided configuration can override it without using 141 `lib`. 142 143 Note that using a distinct version of Nixpkgs with NixOS may 144 be an unexpected source of problems. Use this option with care. 145 ''; 146 }; 147 148 config = mkOption { 149 default = {}; 150 example = literalExpression 151 '' 152 { allowBroken = true; allowUnfree = true; } 153 ''; 154 type = configType; 155 description = lib.mdDoc '' 156 The configuration of the Nix Packages collection. (For 157 details, see the Nixpkgs documentation.) It allows you to set 158 package configuration options. 159 160 Ignored when `nixpkgs.pkgs` is set. 161 ''; 162 }; 163 164 overlays = mkOption { 165 default = []; 166 example = literalExpression 167 '' 168 [ 169 (self: super: { 170 openssh = super.openssh.override { 171 hpnSupport = true; 172 kerberos = self.libkrb5; 173 }; 174 }) 175 ] 176 ''; 177 type = types.listOf overlayType; 178 description = lib.mdDoc '' 179 List of overlays to apply to Nixpkgs. 180 This option allows modifying the Nixpkgs package set accessed through the `pkgs` module argument. 181 182 For details, see the [Overlays chapter in the Nixpkgs manual](https://nixos.org/manual/nixpkgs/stable/#chap-overlays). 183 184 If the {option}`nixpkgs.pkgs` option is set, overlays specified using `nixpkgs.overlays` will be applied after the overlays that were already included in `nixpkgs.pkgs`. 185 ''; 186 }; 187 188 hostPlatform = mkOption { 189 type = types.either types.str types.attrs; # TODO utilize lib.systems.parsedPlatform 190 example = { system = "aarch64-linux"; }; 191 # Make sure that the final value has all fields for sake of other modules 192 # referring to this. TODO make `lib.systems` itself use the module system. 193 apply = lib.systems.elaborate; 194 defaultText = literalExpression 195 ''(import "''${nixos}/../lib").lib.systems.examples.aarch64-multiplatform''; 196 description = lib.mdDoc '' 197 Specifies the platform where the NixOS configuration will run. 198 199 To cross-compile, set also `nixpkgs.buildPlatform`. 200 201 Ignored when `nixpkgs.pkgs` is set. 202 ''; 203 }; 204 205 buildPlatform = mkOption { 206 type = types.either types.str types.attrs; # TODO utilize lib.systems.parsedPlatform 207 default = cfg.hostPlatform; 208 example = { system = "x86_64-linux"; }; 209 # Make sure that the final value has all fields for sake of other modules 210 # referring to this. 211 apply = lib.systems.elaborate; 212 defaultText = literalExpression 213 ''config.nixpkgs.hostPlatform''; 214 description = lib.mdDoc '' 215 Specifies the platform on which NixOS should be built. 216 By default, NixOS is built on the system where it runs, but you can 217 change where it's built. Setting this option will cause NixOS to be 218 cross-compiled. 219 220 For instance, if you're doing distributed multi-platform deployment, 221 or if you're building machines, you can set this to match your 222 development system and/or build farm. 223 224 Ignored when `nixpkgs.pkgs` is set. 225 ''; 226 }; 227 228 localSystem = mkOption { 229 type = types.attrs; # TODO utilize lib.systems.parsedPlatform 230 default = { inherit (cfg) system; }; 231 example = { system = "aarch64-linux"; }; 232 # Make sure that the final value has all fields for sake of other modules 233 # referring to this. TODO make `lib.systems` itself use the module system. 234 apply = lib.systems.elaborate; 235 defaultText = literalExpression 236 ''(import "''${nixos}/../lib").lib.systems.examples.aarch64-multiplatform''; 237 description = lib.mdDoc '' 238 Systems with a recently generated `hardware-configuration.nix` 239 do not need to specify this option, unless cross-compiling, in which case 240 you should set *only* {option}`nixpkgs.buildPlatform`. 241 242 If this is somehow not feasible, you may fall back to removing the 243 {option}`nixpkgs.hostPlatform` line from the generated config and 244 use the old options. 245 246 Specifies the platform on which NixOS should be built. When 247 `nixpkgs.crossSystem` is unset, it also specifies 248 the platform *for* which NixOS should be 249 built. If this option is unset, it defaults to the platform 250 type of the machine where evaluation happens. Specifying this 251 option is useful when doing distributed multi-platform 252 deployment, or when building virtual machines. See its 253 description in the Nixpkgs manual for more details. 254 255 Ignored when `nixpkgs.pkgs` or `hostPlatform` is set. 256 ''; 257 }; 258 259 # TODO deprecate. "crossSystem" is a nonsense identifier, because "cross" 260 # is a relation between at least 2 systems in the context of a 261 # specific build step, not a single system. 262 crossSystem = mkOption { 263 type = types.nullOr types.attrs; # TODO utilize lib.systems.parsedPlatform 264 default = null; 265 example = { system = "aarch64-linux"; }; 266 description = lib.mdDoc '' 267 Systems with a recently generated `hardware-configuration.nix` 268 may instead specify *only* {option}`nixpkgs.buildPlatform`, 269 or fall back to removing the {option}`nixpkgs.hostPlatform` line from the generated config. 270 271 Specifies the platform for which NixOS should be 272 built. Specify this only if it is different from 273 `nixpkgs.localSystem`, the platform 274 *on* which NixOS should be built. In other 275 words, specify this to cross-compile NixOS. Otherwise it 276 should be set as null, the default. See its description in the 277 Nixpkgs manual for more details. 278 279 Ignored when `nixpkgs.pkgs` or `hostPlatform` is set. 280 ''; 281 }; 282 283 system = mkOption { 284 type = types.str; 285 example = "i686-linux"; 286 default = 287 if opt.hostPlatform.isDefined 288 then 289 throw '' 290 Neither ${opt.system} nor any other option in nixpkgs.* is meant 291 to be read by modules and configurations. 292 Use pkgs.stdenv.hostPlatform instead. 293 '' 294 else 295 throw '' 296 Neither ${opt.hostPlatform} nor the legacy option ${opt.system} has been set. 297 You can set ${opt.hostPlatform} in hardware-configuration.nix by re-running 298 a recent version of nixos-generate-config. 299 The option ${opt.system} is still fully supported for NixOS 22.05 interoperability, 300 but will be deprecated in the future, so we recommend to set ${opt.hostPlatform}. 301 ''; 302 defaultText = lib.literalMD '' 303 Traditionally `builtins.currentSystem`, but unset when invoking NixOS through `lib.nixosSystem`. 304 ''; 305 description = lib.mdDoc '' 306 This option does not need to be specified for NixOS configurations 307 with a recently generated `hardware-configuration.nix`. 308 309 Specifies the Nix platform type on which NixOS should be built. 310 It is better to specify `nixpkgs.localSystem` instead. 311 ``` 312 { 313 nixpkgs.system = ..; 314 } 315 ``` 316 is the same as 317 ``` 318 { 319 nixpkgs.localSystem.system = ..; 320 } 321 ``` 322 See `nixpkgs.localSystem` for more information. 323 324 Ignored when `nixpkgs.pkgs`, `nixpkgs.localSystem` or `nixpkgs.hostPlatform` is set. 325 ''; 326 }; 327 }; 328 329 config = { 330 _module.args = { 331 pkgs = 332 # We explicitly set the default override priority, so that we do not need 333 # to evaluate finalPkgs in case an override is placed on `_module.args.pkgs`. 334 # After all, to determine a definition priority, we need to evaluate `._type`, 335 # which is somewhat costly for Nixpkgs. With an explicit priority, we only 336 # evaluate the wrapper to find out that the priority is lower, and then we 337 # don't need to evaluate `finalPkgs`. 338 lib.mkOverride lib.modules.defaultOverridePriority 339 finalPkgs.__splicedPackages; 340 }; 341 342 assertions = let 343 # Whether `pkgs` was constructed by this module. This is false when any of 344 # nixpkgs.pkgs or _module.args.pkgs is set. 345 constructedByMe = 346 # We set it with default priority and it can not be merged, so if the 347 # pkgs module argument has that priority, it's from us. 348 (lib.modules.mergeAttrDefinitionsWithPrio options._module.args).pkgs.highestPrio 349 == lib.modules.defaultOverridePriority 350 # Although, if nixpkgs.pkgs is set, we did forward it, but we did not construct it. 351 && !opt.pkgs.isDefined; 352 in [ 353 ( 354 let 355 nixosExpectedSystem = 356 if config.nixpkgs.crossSystem != null 357 then config.nixpkgs.crossSystem.system or (lib.systems.parse.doubleFromSystem (lib.systems.parse.mkSystemFromString config.nixpkgs.crossSystem.config)) 358 else config.nixpkgs.localSystem.system or (lib.systems.parse.doubleFromSystem (lib.systems.parse.mkSystemFromString config.nixpkgs.localSystem.config)); 359 nixosOption = 360 if config.nixpkgs.crossSystem != null 361 then "nixpkgs.crossSystem" 362 else "nixpkgs.localSystem"; 363 pkgsSystem = finalPkgs.stdenv.targetPlatform.system; 364 in { 365 assertion = constructedByMe -> !hasPlatform -> nixosExpectedSystem == pkgsSystem; 366 message = "The NixOS nixpkgs.pkgs option was set to a Nixpkgs invocation that compiles to target system ${pkgsSystem} but NixOS was configured for system ${nixosExpectedSystem} via NixOS option ${nixosOption}. The NixOS system settings must match the Nixpkgs target system."; 367 } 368 ) 369 { 370 assertion = constructedByMe -> hasPlatform -> legacyOptionsDefined == []; 371 message = '' 372 Your system configures nixpkgs with the platform parameter${optionalString hasBuildPlatform "s"}: 373 ${hostPlatformLine 374 }${buildPlatformLine 375 } 376 However, it also defines the legacy options: 377 ${concatMapStrings showOptionWithDefLocs legacyOptionsDefined} 378 For a future proof system configuration, we recommend to remove 379 the legacy definitions. 380 ''; 381 } 382 { 383 assertion = opt.pkgs.isDefined -> cfg.config == {}; 384 message = '' 385 Your system configures nixpkgs with an externally created instance. 386 `nixpkgs.config` options should be passed when creating the instance instead. 387 388 Current value: 389 ${lib.generators.toPretty { multiline = true; } opt.config} 390 ''; 391 } 392 ]; 393 }; 394 395 # needs a full nixpkgs path to import nixpkgs 396 meta.buildDocsInSandbox = false; 397}