Release NixOS 23.11
[NixPkgs.git] / nixos / modules / misc / nixpkgs.nix
blobda321a9234493d1514cc7a47646e1af4443fad21
1 { config, options, lib, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.nixpkgs;
7   opt = options.nixpkgs;
9   isConfig = x:
10     builtins.isAttrs x || lib.isFunction x;
12   optCall = f: x:
13     if lib.isFunction f
14     then f x
15     else f;
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     };
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   };
45   overlayType = mkOptionType {
46     name = "nixpkgs-overlay";
47     description = "nixpkgs overlay";
48     check = lib.isFunction;
49     merge = lib.mergeOneOption;
50   };
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   };
58   hasBuildPlatform = opt.buildPlatform.highestPrio < (mkOptionDefault {}).priority;
59   hasHostPlatform = opt.hostPlatform.isDefined;
60   hasPlatform = hasHostPlatform || hasBuildPlatform;
62   # Context for messages
63   hostPlatformLine = optionalString hasHostPlatform "${showOptionWithDefLocs opt.hostPlatform}";
64   buildPlatformLine = optionalString hasBuildPlatform "${showOptionWithDefLocs opt.buildPlatform}";
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     ;
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       };
94   finalPkgs = if opt.pkgs.isDefined then cfg.pkgs.appendOverlays cfg.overlays else defaultPkgs;
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   ];
105   options.nixpkgs = {
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.
124         If unset, the pkgs argument to all NixOS modules is determined
125         as shown in the default value for this option.
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.
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`.
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     };
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.
160         Ignored when `nixpkgs.pkgs` is set.
161       '';
162     };
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.
182         For details, see the [Overlays chapter in the Nixpkgs manual](https://nixos.org/manual/nixpkgs/stable/#chap-overlays).
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     };
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.
199         To cross-compile, set also `nixpkgs.buildPlatform`.
201         Ignored when `nixpkgs.pkgs` is set.
202       '';
203     };
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.
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 = 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`.
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 = 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.
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 = 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`.
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${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.
388           Current value:
389           ${lib.generators.toPretty { multiline = true; } opt.config}
390         '';
391       }
392     ];
393   };
395   # needs a full nixpkgs path to import nixpkgs
396   meta.buildDocsInSandbox = false;