python312Packages.dissect-extfs: 3.11 -> 3.12
[NixPkgs.git] / nixos / modules / misc / nixpkgs.nix
blob4048fd68573780a0bb19c9449ef4b7a385cb01c0
1 { config, options, lib, pkgs, ... }:
2 let
3   cfg = config.nixpkgs;
4   opt = options.nixpkgs;
6   isConfig = x:
7     builtins.isAttrs x || lib.isFunction x;
9   optCall = f: x:
10     if lib.isFunction f
11     then f x
12     else f;
14   mergeConfig = lhs_: rhs_:
15     let
16       lhs = optCall lhs_ { inherit pkgs; };
17       rhs = optCall rhs_ { inherit pkgs; };
18     in
19     lib.recursiveUpdate lhs rhs //
20     lib.optionalAttrs (lhs ? packageOverrides) {
21       packageOverrides = pkgs:
22         optCall lhs.packageOverrides pkgs //
23         optCall (lib.attrByPath [ "packageOverrides" ] { } rhs) pkgs;
24     } //
25     lib.optionalAttrs (lhs ? perlPackageOverrides) {
26       perlPackageOverrides = pkgs:
27         optCall lhs.perlPackageOverrides pkgs //
28         optCall (lib.attrByPath [ "perlPackageOverrides" ] { } rhs) pkgs;
29     };
31   configType = lib.mkOptionType {
32     name = "nixpkgs-config";
33     description = "nixpkgs config";
34     check = x:
35       let traceXIfNot = c:
36             if c x then true
37             else lib.traceSeqN 1 x false;
38       in traceXIfNot isConfig;
39     merge = args: lib.foldr (def: mergeConfig def.value) {};
40   };
42   overlayType = lib.mkOptionType {
43     name = "nixpkgs-overlay";
44     description = "nixpkgs overlay";
45     check = lib.isFunction;
46     merge = lib.mergeOneOption;
47   };
49   pkgsType = lib.types.pkgs // {
50     # This type is only used by itself, so let's elaborate the description a bit
51     # for the purpose of documentation.
52     description = "An evaluation of Nixpkgs; the top level attribute set of packages";
53   };
55   hasBuildPlatform = opt.buildPlatform.highestPrio < (lib.mkOptionDefault {}).priority;
56   hasHostPlatform = opt.hostPlatform.isDefined;
57   hasPlatform = hasHostPlatform || hasBuildPlatform;
59   # Context for messages
60   hostPlatformLine = lib.optionalString hasHostPlatform "${lib.showOptionWithDefLocs opt.hostPlatform}";
61   buildPlatformLine = lib.optionalString hasBuildPlatform "${lib.showOptionWithDefLocs opt.buildPlatform}";
63   legacyOptionsDefined =
64     lib.optional (opt.localSystem.highestPrio < (lib.mkDefault {}).priority) opt.system
65     ++ lib.optional (opt.localSystem.highestPrio < (lib.mkOptionDefault {}).priority) opt.localSystem
66     ++ lib.optional (opt.crossSystem.highestPrio < (lib.mkOptionDefault {}).priority) opt.crossSystem
67     ;
69   defaultPkgs =
70     if opt.hostPlatform.isDefined
71     then
72       let isCross = cfg.buildPlatform != cfg.hostPlatform;
73           systemArgs =
74             if isCross
75             then {
76               localSystem = cfg.buildPlatform;
77               crossSystem = cfg.hostPlatform;
78             }
79             else {
80               localSystem = cfg.hostPlatform;
81             };
82       in
83       import ../../.. ({
84         inherit (cfg) config overlays;
85       } // systemArgs)
86     else
87       import ../../.. {
88         inherit (cfg) config overlays localSystem crossSystem;
89       };
91   finalPkgs = if opt.pkgs.isDefined then cfg.pkgs.appendOverlays cfg.overlays else defaultPkgs;
96   imports = [
97     ./assertions.nix
98     ./meta.nix
99     (lib.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.")
100   ];
102   options.nixpkgs = {
104     pkgs = lib.mkOption {
105       defaultText = lib.literalExpression ''
106         import "''${nixos}/.." {
107           inherit (cfg) config overlays localSystem crossSystem;
108         }
109       '';
110       type = pkgsType;
111       example = lib.literalExpression "import <nixpkgs> {}";
112       description = ''
113         If set, the pkgs argument to all NixOS modules is the value of
114         this option, extended with `nixpkgs.overlays`, if
115         that is also set. Either `nixpkgs.crossSystem` or
116         `nixpkgs.localSystem` will be used in an assertion
117         to check that the NixOS and Nixpkgs architectures match. Any
118         other options in `nixpkgs.*`, notably `config`,
119         will be ignored.
121         If unset, the pkgs argument to all NixOS modules is determined
122         as shown in the default value for this option.
124         The default value imports the Nixpkgs source files
125         relative to the location of this NixOS module, because
126         NixOS and Nixpkgs are distributed together for consistency,
127         so the `nixos` in the default value is in fact a
128         relative path. The `config`, `overlays`,
129         `localSystem`, and `crossSystem` come
130         from this option's siblings.
132         This option can be used by applications like NixOps to increase
133         the performance of evaluation, or to create packages that depend
134         on a container that should be built with the exact same evaluation
135         of Nixpkgs, for example. Applications like this should set
136         their default value using `lib.mkDefault`, so
137         user-provided configuration can override it without using
138         `lib`.
140         Note that using a distinct version of Nixpkgs with NixOS may
141         be an unexpected source of problems. Use this option with care.
142       '';
143     };
145     config = lib.mkOption {
146       default = {};
147       example = lib.literalExpression
148         ''
149           { allowBroken = true; allowUnfree = true; }
150         '';
151       type = configType;
152       description = ''
153         Global configuration for Nixpkgs.
154         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).
156         Ignored when {option}`nixpkgs.pkgs` is set.
157       '';
158     };
160     overlays = lib.mkOption {
161       default = [];
162       example = lib.literalExpression
163         ''
164           [
165             (self: super: {
166               openssh = super.openssh.override {
167                 hpnSupport = true;
168                 kerberos = self.libkrb5;
169               };
170             })
171           ]
172         '';
173       type = lib.types.listOf overlayType;
174       description = ''
175         List of overlays to apply to Nixpkgs.
176         This option allows modifying the Nixpkgs package set accessed through the `pkgs` module argument.
178         For details, see the [Overlays chapter in the Nixpkgs manual](https://nixos.org/manual/nixpkgs/stable/#chap-overlays).
180         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`.
181       '';
182     };
184     hostPlatform = lib.mkOption {
185       type = lib.types.either lib.types.str lib.types.attrs; # TODO utilize lib.systems.parsedPlatform
186       example = { system = "aarch64-linux"; };
187       # Make sure that the final value has all fields for sake of other modules
188       # referring to this. TODO make `lib.systems` itself use the module system.
189       apply = lib.systems.elaborate;
190       defaultText = lib.literalExpression
191         ''(import "''${nixos}/../lib").lib.systems.examples.aarch64-multiplatform'';
192       description = ''
193         Specifies the platform where the NixOS configuration will run.
195         To cross-compile, set also `nixpkgs.buildPlatform`.
197         Ignored when `nixpkgs.pkgs` is set.
198       '';
199     };
201     buildPlatform = lib.mkOption {
202       type = lib.types.either lib.types.str lib.types.attrs; # TODO utilize lib.systems.parsedPlatform
203       default = cfg.hostPlatform;
204       example = { system = "x86_64-linux"; };
205       # Make sure that the final value has all fields for sake of other modules
206       # referring to this.
207       apply = inputBuildPlatform:
208         let elaborated = lib.systems.elaborate inputBuildPlatform;
209         in if lib.systems.equals elaborated cfg.hostPlatform
210           then cfg.hostPlatform  # make identical, so that `==` equality works; see https://github.com/NixOS/nixpkgs/issues/278001
211           else elaborated;
212       defaultText = lib.literalExpression
213         ''config.nixpkgs.hostPlatform'';
214       description = ''
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.
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.
224         Ignored when `nixpkgs.pkgs` is set.
225       '';
226     };
228     localSystem = lib.mkOption {
229       type = lib.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 = lib.literalExpression
236         ''(import "''${nixos}/../lib").lib.systems.examples.aarch64-multiplatform'';
237       description = ''
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`.
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.
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.
255         Ignored when `nixpkgs.pkgs` or `hostPlatform` is set.
256       '';
257     };
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 = lib.mkOption {
263       type = lib.types.nullOr lib.types.attrs; # TODO utilize lib.systems.parsedPlatform
264       default = null;
265       example = { system = "aarch64-linux"; };
266       description = ''
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.
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.
279         Ignored when `nixpkgs.pkgs` or `hostPlatform` is set.
280       '';
281     };
283     system = lib.mkOption {
284       type = lib.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 = ''
306         This option does not need to be specified for NixOS configurations
307         with a recently generated `hardware-configuration.nix`.
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.
324         Ignored when `nixpkgs.pkgs`, `nixpkgs.localSystem` or `nixpkgs.hostPlatform` is set.
325       '';
326     };
327   };
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     };
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${lib.optionalString hasBuildPlatform "s"}:
373           ${hostPlatformLine
374           }${buildPlatformLine
375           }
376           However, it also defines the legacy options:
377           ${lib.concatMapStrings lib.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.
388           Current value:
389           ${lib.generators.toPretty { multiline = true; } cfg.config}
391           Defined in:
392           ${lib.concatMapStringsSep "\n" (file: "  - ${file}") opt.config.files}
393         '';
394       }
395     ];
396   };
398   # needs a full nixpkgs path to import nixpkgs
399   meta.buildDocsInSandbox = false;