at 24.11-pre 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 = '' 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 = '' 156 Global configuration for Nixpkgs. 157 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). 158 159 Ignored when {option}`nixpkgs.pkgs` is set. 160 ''; 161 }; 162 163 overlays = mkOption { 164 default = []; 165 example = literalExpression 166 '' 167 [ 168 (self: super: { 169 openssh = super.openssh.override { 170 hpnSupport = true; 171 kerberos = self.libkrb5; 172 }; 173 }) 174 ] 175 ''; 176 type = types.listOf overlayType; 177 description = '' 178 List of overlays to apply to Nixpkgs. 179 This option allows modifying the Nixpkgs package set accessed through the `pkgs` module argument. 180 181 For details, see the [Overlays chapter in the Nixpkgs manual](https://nixos.org/manual/nixpkgs/stable/#chap-overlays). 182 183 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`. 184 ''; 185 }; 186 187 hostPlatform = mkOption { 188 type = types.either types.str types.attrs; # TODO utilize lib.systems.parsedPlatform 189 example = { system = "aarch64-linux"; }; 190 # Make sure that the final value has all fields for sake of other modules 191 # referring to this. TODO make `lib.systems` itself use the module system. 192 apply = lib.systems.elaborate; 193 defaultText = literalExpression 194 ''(import "''${nixos}/../lib").lib.systems.examples.aarch64-multiplatform''; 195 description = '' 196 Specifies the platform where the NixOS configuration will run. 197 198 To cross-compile, set also `nixpkgs.buildPlatform`. 199 200 Ignored when `nixpkgs.pkgs` is set. 201 ''; 202 }; 203 204 buildPlatform = mkOption { 205 type = types.either types.str types.attrs; # TODO utilize lib.systems.parsedPlatform 206 default = cfg.hostPlatform; 207 example = { system = "x86_64-linux"; }; 208 # Make sure that the final value has all fields for sake of other modules 209 # referring to this. 210 apply = inputBuildPlatform: 211 let elaborated = lib.systems.elaborate inputBuildPlatform; 212 in if lib.systems.equals elaborated cfg.hostPlatform 213 then cfg.hostPlatform # make identical, so that `==` equality works; see https://github.com/NixOS/nixpkgs/issues/278001 214 else elaborated; 215 defaultText = literalExpression 216 ''config.nixpkgs.hostPlatform''; 217 description = '' 218 Specifies the platform on which NixOS should be built. 219 By default, NixOS is built on the system where it runs, but you can 220 change where it's built. Setting this option will cause NixOS to be 221 cross-compiled. 222 223 For instance, if you're doing distributed multi-platform deployment, 224 or if you're building machines, you can set this to match your 225 development system and/or build farm. 226 227 Ignored when `nixpkgs.pkgs` is set. 228 ''; 229 }; 230 231 localSystem = mkOption { 232 type = types.attrs; # TODO utilize lib.systems.parsedPlatform 233 default = { inherit (cfg) system; }; 234 example = { system = "aarch64-linux"; }; 235 # Make sure that the final value has all fields for sake of other modules 236 # referring to this. TODO make `lib.systems` itself use the module system. 237 apply = lib.systems.elaborate; 238 defaultText = literalExpression 239 ''(import "''${nixos}/../lib").lib.systems.examples.aarch64-multiplatform''; 240 description = '' 241 Systems with a recently generated `hardware-configuration.nix` 242 do not need to specify this option, unless cross-compiling, in which case 243 you should set *only* {option}`nixpkgs.buildPlatform`. 244 245 If this is somehow not feasible, you may fall back to removing the 246 {option}`nixpkgs.hostPlatform` line from the generated config and 247 use the old options. 248 249 Specifies the platform on which NixOS should be built. When 250 `nixpkgs.crossSystem` is unset, it also specifies 251 the platform *for* which NixOS should be 252 built. If this option is unset, it defaults to the platform 253 type of the machine where evaluation happens. Specifying this 254 option is useful when doing distributed multi-platform 255 deployment, or when building virtual machines. See its 256 description in the Nixpkgs manual for more details. 257 258 Ignored when `nixpkgs.pkgs` or `hostPlatform` is set. 259 ''; 260 }; 261 262 # TODO deprecate. "crossSystem" is a nonsense identifier, because "cross" 263 # is a relation between at least 2 systems in the context of a 264 # specific build step, not a single system. 265 crossSystem = mkOption { 266 type = types.nullOr types.attrs; # TODO utilize lib.systems.parsedPlatform 267 default = null; 268 example = { system = "aarch64-linux"; }; 269 description = '' 270 Systems with a recently generated `hardware-configuration.nix` 271 may instead specify *only* {option}`nixpkgs.buildPlatform`, 272 or fall back to removing the {option}`nixpkgs.hostPlatform` line from the generated config. 273 274 Specifies the platform for which NixOS should be 275 built. Specify this only if it is different from 276 `nixpkgs.localSystem`, the platform 277 *on* which NixOS should be built. In other 278 words, specify this to cross-compile NixOS. Otherwise it 279 should be set as null, the default. See its description in the 280 Nixpkgs manual for more details. 281 282 Ignored when `nixpkgs.pkgs` or `hostPlatform` is set. 283 ''; 284 }; 285 286 system = mkOption { 287 type = types.str; 288 example = "i686-linux"; 289 default = 290 if opt.hostPlatform.isDefined 291 then 292 throw '' 293 Neither ${opt.system} nor any other option in nixpkgs.* is meant 294 to be read by modules and configurations. 295 Use pkgs.stdenv.hostPlatform instead. 296 '' 297 else 298 throw '' 299 Neither ${opt.hostPlatform} nor the legacy option ${opt.system} has been set. 300 You can set ${opt.hostPlatform} in hardware-configuration.nix by re-running 301 a recent version of nixos-generate-config. 302 The option ${opt.system} is still fully supported for NixOS 22.05 interoperability, 303 but will be deprecated in the future, so we recommend to set ${opt.hostPlatform}. 304 ''; 305 defaultText = lib.literalMD '' 306 Traditionally `builtins.currentSystem`, but unset when invoking NixOS through `lib.nixosSystem`. 307 ''; 308 description = '' 309 This option does not need to be specified for NixOS configurations 310 with a recently generated `hardware-configuration.nix`. 311 312 Specifies the Nix platform type on which NixOS should be built. 313 It is better to specify `nixpkgs.localSystem` instead. 314 ``` 315 { 316 nixpkgs.system = ..; 317 } 318 ``` 319 is the same as 320 ``` 321 { 322 nixpkgs.localSystem.system = ..; 323 } 324 ``` 325 See `nixpkgs.localSystem` for more information. 326 327 Ignored when `nixpkgs.pkgs`, `nixpkgs.localSystem` or `nixpkgs.hostPlatform` is set. 328 ''; 329 }; 330 }; 331 332 config = { 333 _module.args = { 334 pkgs = 335 # We explicitly set the default override priority, so that we do not need 336 # to evaluate finalPkgs in case an override is placed on `_module.args.pkgs`. 337 # After all, to determine a definition priority, we need to evaluate `._type`, 338 # which is somewhat costly for Nixpkgs. With an explicit priority, we only 339 # evaluate the wrapper to find out that the priority is lower, and then we 340 # don't need to evaluate `finalPkgs`. 341 lib.mkOverride lib.modules.defaultOverridePriority 342 finalPkgs.__splicedPackages; 343 }; 344 345 assertions = let 346 # Whether `pkgs` was constructed by this module. This is false when any of 347 # nixpkgs.pkgs or _module.args.pkgs is set. 348 constructedByMe = 349 # We set it with default priority and it can not be merged, so if the 350 # pkgs module argument has that priority, it's from us. 351 (lib.modules.mergeAttrDefinitionsWithPrio options._module.args).pkgs.highestPrio 352 == lib.modules.defaultOverridePriority 353 # Although, if nixpkgs.pkgs is set, we did forward it, but we did not construct it. 354 && !opt.pkgs.isDefined; 355 in [ 356 ( 357 let 358 nixosExpectedSystem = 359 if config.nixpkgs.crossSystem != null 360 then config.nixpkgs.crossSystem.system or (lib.systems.parse.doubleFromSystem (lib.systems.parse.mkSystemFromString config.nixpkgs.crossSystem.config)) 361 else config.nixpkgs.localSystem.system or (lib.systems.parse.doubleFromSystem (lib.systems.parse.mkSystemFromString config.nixpkgs.localSystem.config)); 362 nixosOption = 363 if config.nixpkgs.crossSystem != null 364 then "nixpkgs.crossSystem" 365 else "nixpkgs.localSystem"; 366 pkgsSystem = finalPkgs.stdenv.targetPlatform.system; 367 in { 368 assertion = constructedByMe -> !hasPlatform -> nixosExpectedSystem == pkgsSystem; 369 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."; 370 } 371 ) 372 { 373 assertion = constructedByMe -> hasPlatform -> legacyOptionsDefined == []; 374 message = '' 375 Your system configures nixpkgs with the platform parameter${optionalString hasBuildPlatform "s"}: 376 ${hostPlatformLine 377 }${buildPlatformLine 378 } 379 However, it also defines the legacy options: 380 ${concatMapStrings showOptionWithDefLocs legacyOptionsDefined} 381 For a future proof system configuration, we recommend to remove 382 the legacy definitions. 383 ''; 384 } 385 { 386 assertion = opt.pkgs.isDefined -> cfg.config == {}; 387 message = '' 388 Your system configures nixpkgs with an externally created instance. 389 `nixpkgs.config` options should be passed when creating the instance instead. 390 391 Current value: 392 ${lib.generators.toPretty { multiline = true; } opt.config} 393 ''; 394 } 395 ]; 396 }; 397 398 # needs a full nixpkgs path to import nixpkgs 399 meta.buildDocsInSandbox = false; 400}