diff --git a/nixos/modules/misc/nixpkgs.nix b/nixos/modules/misc/nixpkgs.nix index a9e49a2a26cd..dcb05e349197 100644 --- a/nixos/modules/misc/nixpkgs.nix +++ b/nixos/modules/misc/nixpkgs.nix @@ -2,12 +2,51 @@ config, options, lib, + pkgs, ... }: let cfg = config.nixpkgs; opt = options.nixpkgs; + isConfig = x: builtins.isAttrs x || lib.isFunction x; + + optCall = f: x: if lib.isFunction f then f x else f; + + mergeConfig = + lhs_: rhs_: + let + lhs = optCall lhs_ { inherit lib pkgs; }; + rhs = optCall rhs_ { inherit lib pkgs; }; + in + lib.recursiveUpdate lhs rhs + // lib.optionalAttrs (lhs ? allowUnfreePackages) { + allowUnfreePackages = lhs.allowUnfreePackages ++ (lib.attrByPath [ "allowUnfreePackages" ] [ ] rhs); + } + // lib.optionalAttrs (lhs ? packageOverrides) { + packageOverrides = + pkgs: + optCall lhs.packageOverrides pkgs // optCall (lib.attrByPath [ "packageOverrides" ] { } rhs) pkgs; + } + // lib.optionalAttrs (lhs ? perlPackageOverrides) { + perlPackageOverrides = + pkgs: + optCall lhs.perlPackageOverrides pkgs + // optCall (lib.attrByPath [ "perlPackageOverrides" ] { } rhs) pkgs; + }; + + configType = lib.mkOptionType { + name = "nixpkgs-config"; + description = "nixpkgs config"; + check = + x: + let + traceXIfNot = c: if c x then true else lib.traceSeqN 1 x false; + in + traceXIfNot isConfig; + merge = args: lib.foldr (def: mergeConfig def.value) { }; + }; + overlayType = lib.mkOptionType { name = "nixpkgs-overlay"; description = "nixpkgs overlay"; @@ -34,8 +73,6 @@ let ++ lib.optional (opt.localSystem.highestPrio < (lib.mkOptionDefault { }).priority) opt.localSystem ++ lib.optional (opt.crossSystem.highestPrio < (lib.mkOptionDefault { }).priority) opt.crossSystem; - _configDefinitions = opt.config.definitionsWithLocations; - defaultPkgs = if opt.hostPlatform.isDefined then let @@ -53,15 +90,14 @@ let in import ../../.. ( { - inherit _configDefinitions; - inherit (cfg) overlays; + inherit (cfg) config overlays; } // systemArgs ) else import ../../.. { - inherit _configDefinitions; inherit (cfg) + config overlays localSystem crossSystem @@ -129,15 +165,7 @@ in example = lib.literalExpression '' { allowBroken = true; allowUnfree = true; } ''; - type = lib.types.deferredModuleWith { - staticModules = [ - { _module.args.docPrefix = "https://nixos.org/manual/nixpkgs/unstable/"; } - ../../../pkgs/top-level/config.nix - ]; - }; - # Returns pkgs.config instead of nixpkgs.config - # This shadows the deferredModule to make it look like a submodule - apply = _: finalPkgs.config; + type = configType; description = '' Global configuration for Nixpkgs. 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). @@ -378,7 +406,7 @@ in ''; } { - assertion = opt.pkgs.isDefined -> opt.config.highestPrio == (lib.mkOptionDefault null).priority; + assertion = opt.pkgs.isDefined -> cfg.config == { }; message = '' Your system configures nixpkgs with an externally created instance. `nixpkgs.config` options should be passed when creating the instance instead. diff --git a/pkgs/test/config-nix-unit.nix b/pkgs/test/config-nix-unit.nix deleted file mode 100644 index cd16d5ca1c43..000000000000 --- a/pkgs/test/config-nix-unit.nix +++ /dev/null @@ -1,117 +0,0 @@ -# Tests for nixpkgs config forwarding from NixOS modules. -# -# Run with: -# nix-unit pkgs/test/config-nix-unit.nix -# or -# nix-build -A tests.config-nix-unit -# -{ - nixpkgsPath ? ../.., - pkgs ? import nixpkgsPath { }, -}: -let - lib = pkgs.lib; - - # Test helper - evalNixos = - modules: - import (nixpkgsPath + "/nixos/lib/eval-config.nix") { - modules = [ { nixpkgs.hostPlatform = "x86_64-linux"; } ] ++ modules; - }; -in -{ - # Basic: a single config option is forwarded correctly. - testSingleConfigOption = { - expr = (evalNixos [ { nixpkgs.config.allowUnfree = true; } ]).config.nixpkgs.config.allowUnfree; - expected = true; - }; - - # Multiple config definitions from separate modules are merged. - testMultipleModulesMerge = { - expr = - let - eval = evalNixos [ - { nixpkgs.config.allowUnfree = true; } - { nixpkgs.config.allowBroken = true; } - ]; - in - { - inherit (eval.config.nixpkgs.config) allowUnfree allowBroken; - }; - expected = { - allowUnfree = true; - allowBroken = true; - }; - }; - - # mkForce works. Also covers other properties - testMkForce = { - expr = - (evalNixos [ - { nixpkgs.config.allowUnfree = true; } - { nixpkgs.config.allowUnfree = lib.mkForce false; } - ]).config.nixpkgs.config.allowUnfree; - expected = false; - }; - - testDefaults = { - expr = (evalNixos [ ]).config.nixpkgs.config.allowUnfree; - expected = false; - }; - - # Standalone nixpkgs (i.e. import { ... }) - testStandaloneConfig = { - expr = (import nixpkgsPath { config.allowUnfree = true; }).config.allowUnfree; - expected = true; - }; - - # Standalone nixpkgs with a function (i.e. import ({pkgs, lib, ...}: { ... }) - testStandaloneConfigFunctionPkgs = { - expr = - (import nixpkgsPath { - config = - { pkgs, lib, ... }: - { - allowUnfree = lib.isAttrs pkgs; - }; - }).config.allowUnfree; - expected = true; - }; - - # NixOS module sets nixpkgs.config as a function - testNixosConfigFunction = { - expr = - (evalNixos [ - { - nixpkgs.config = - { lib, ... }: - { - allowUnfree = lib.isFunction lib.id; - }; - } - ]).config.nixpkgs.config.allowUnfree; - expected = true; - }; - - # Passing both config and _configDefinitions is not allowed - testConfigAndDefinitionsMutuallyExclusive = { - expr = - (import nixpkgsPath { - config = { - allowUnfree = true; - }; - _configDefinitions = [ - { - file = "test"; - value = { - allowBroken = true; - }; - } - ]; - }).config.allowUnfree; - expectedError = { - type = "ThrownError"; - msg = ".*_configDefinitions.*internal.*must not be combined.*"; - }; - }; -} diff --git a/pkgs/test/default.nix b/pkgs/test/default.nix index 50a5cf2527ed..63e8e2b32aae 100644 --- a/pkgs/test/default.nix +++ b/pkgs/test/default.nix @@ -128,26 +128,6 @@ in config = callPackage ./config.nix { }; - # Technically nix-unit binds to a fixed nix version - # We have tests in lib to test the module system itself against different nix-versions - # Based on this assumption (transitivity of correctness) this test should therefore also cover all tested nix-versions - config-nix-unit = - pkgs.runCommand "config-nix-unit" - { - nativeBuildInputs = [ pkgs.nix-unit ]; - } - '' - export HOME=$TMPDIR - nix-unit --eval-store "$HOME" ${./config-nix-unit.nix} \ - --arg nixpkgsPath "${ - builtins.path { - path = pkgs.path; - name = "source"; - } - }" - mkdir $out - ''; - top-level = callPackage ./top-level { }; haskell = callPackage ./haskell { }; diff --git a/pkgs/top-level/config.nix b/pkgs/top-level/config.nix index a92dd200ccf6..526dd4182702 100644 --- a/pkgs/top-level/config.nix +++ b/pkgs/top-level/config.nix @@ -6,12 +6,7 @@ # nix-build -A tests.config # -{ - config, - lib, - docPrefix, - ... -}: +{ config, lib, ... }: let inherit (lib) @@ -120,13 +115,13 @@ let gitConfig = mkOption { type = types.attrsOf (types.attrsOf types.anything); description = '' - The default [git configuration](https://git-scm.com/docs/git-config#_variables) for all [`pkgs.fetchgit`](${docPrefix}#fetchgit) calls. + The default [git configuration](https://git-scm.com/docs/git-config#_variables) for all [`pkgs.fetchgit`](#fetchgit) calls. Among many other potential uses, this can be used to override URLs to point to local mirrors. Changing this will not cause any rebuilds because `pkgs.fetchgit` produces a [fixed-output derivation](https://nix.dev/manual/nix/stable/glossary.html?highlight=fixed-output%20derivation#gloss-fixed-output-derivation). - To set the configuration file directly, use the [`gitConfigFile`](${docPrefix}#opt-gitConfigFile) option instead. + To set the configuration file directly, use the [`gitConfigFile`](#opt-gitConfigFile) option instead. To set the configuration file for individual calls, use `fetchgit { gitConfigFile = "..."; }`. ''; @@ -140,9 +135,9 @@ let gitConfigFile = mkOption { type = types.nullOr types.path; description = '' - A path to a [git configuration](https://git-scm.com/docs/git-config#_variables) file, to be used for all [`pkgs.fetchgit`](${docPrefix}#fetchgit) calls. + A path to a [git configuration](https://git-scm.com/docs/git-config#_variables) file, to be used for all [`pkgs.fetchgit`](#fetchgit) calls. - This overrides the [`gitConfig`](${docPrefix}#opt-gitConfig) option, see its documentation for more details. + This overrides the [`gitConfig`](#opt-gitConfig) option, see its documentation for more details. ''; default = if config.gitConfig != { } then @@ -160,7 +155,7 @@ let For example, an override like `"registry.npmjs.org" = "my-mirror.local/registry.npmjs.org"` will replace a URL like `https://registry.npmjs.org/foo.tar.gz` with `https://my-mirror.local/registry.npmjs.org/foo.tar.gz`. - To set the string directly, see [`npmRegistryOverridesString`](${docPrefix}#opt-npmRegistryOverridesString). + To set the string directly, see [`npmRegistryOverridesString`](#opt-npmRegistryOverridesString). ''; default = { }; example = { @@ -179,7 +174,7 @@ let description = '' A string containing a string with a JSON representation of npm registry overrides for `fetchNpmDeps`. - This overrides the [`npmRegistryOverrides`](${docPrefix}#opt-npmRegistryOverrides) option, see its documentation for more details. + This overrides the [`npmRegistryOverrides`](#opt-npmRegistryOverrides) option, see its documentation for more details. ''; default = builtins.toJSON config.npmRegistryOverrides; }; @@ -417,7 +412,7 @@ let type = types.listOf types.str; default = [ "https://tarballs.nixos.org" ]; description = '' - The set of content-addressed/hashed mirror URLs used by [`pkgs.fetchurl`](${docPrefix}#sec-pkgs-fetchers-fetchurl). + The set of content-addressed/hashed mirror URLs used by [`pkgs.fetchurl`](#sec-pkgs-fetchers-fetchurl). In case `pkgs.fetchurl` can't download from the given URLs, it will try the hashed mirrors based on the expected output hash. @@ -471,27 +466,11 @@ let Silence the warning for the upcoming deprecation of the `x86_64-darwin` platform in Nixpkgs 26.11. - See the [release notes](${docPrefix}#x86_64-darwin-26.05) for more + See the [release notes](#x86_64-darwin-26.05) for more information. ''; }; - packageOverrides = mkOption { - type = types.functionTo types.attrs; - default = pkgs: { }; - description = '' - A function to replace or add packages in `pkgs` expects an attrset to be returned when called. - ''; - }; - - perlPackageOverrides = mkOption { - type = types.functionTo types.attrs; - default = pkgs: { }; - description = '' - The same as `packageOverrides` but for packages in the perl package set. - ''; - }; - problems = (import ../stdenv/generic/problems.nix { inherit lib; }).configOptions; }; @@ -515,7 +494,6 @@ in inherit options; config = { - _module.args.docPrefix = lib.mkDefault ""; warnings = optionals config.warnUndeclaredOptions ( mapAttrsToList (k: v: "undeclared Nixpkgs option set: config.${k}") config._undeclared or { } diff --git a/pkgs/top-level/default.nix b/pkgs/top-level/default.nix index 12fdbed08197..521745d67ec9 100644 --- a/pkgs/top-level/default.nix +++ b/pkgs/top-level/default.nix @@ -64,11 +64,6 @@ in # list it returns. stdenvStages ? import ../stdenv, - # Temporary parameter to unify nixpkgs/pkgs evaluation - # Internal, do not use this manually! - # Will be removed again within the next releases - _configDefinitions ? null, - # Ignore unexpected args. ... }@args: @@ -114,13 +109,7 @@ let then x86_64DarwinDeprecationWarning else - x: - x throwIfNot (lib.all lib.isFunction crossOverlays) - "All crossOverlays passed to nixpkgs must be functions." - ) - ( - throwIfNot (_configDefinitions == null || config0 == { }) - "The `_configDefinitions` argument is an internal interface and must not be combined with `config`." + x: x ); localSystem = lib.systems.elaborate args.localSystem; @@ -145,24 +134,20 @@ let # Allow both: # { /* the config */ } and - # { lib, pkgs, ... } : { /* the config */ } + # { pkgs, ... } : { /* the config */ } config1 = if lib.isFunction config0 then config0 { inherit lib pkgs; } else config0; configEval = lib.evalModules { modules = [ ./config.nix - ] - ++ ( - if _configDefinitions != null then - map (def: lib.modules.setDefaultModuleLocation def.file def.value) _configDefinitions - else - [ - { - _file = "nixpkgs.config"; - config = config1; - } - ] - ); + ( + { options, ... }: + { + _file = "nixpkgs.config"; + config = config1; + } + ) + ]; class = "nixpkgsConfig"; };