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