nixos/nixpkgs.config: use deferredModule to avoid double evaluation
Switch the option type to `deferredModuleWith`, which collects definitions without evaluating them. The raw definitions are forwarded to nixpkgs function via a new internal `_configDefinitions` parameter. `apply` on the option returns `finalPkgs.config`, preserving backwards compatibility for external readers of `config.nixpkgs.config`
This commit is contained in:
committed by
jopejoe1
parent
169e69597b
commit
1d1e96211e
@@ -34,6 +34,8 @@ 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
|
||||
@@ -51,14 +53,15 @@ let
|
||||
in
|
||||
import ../../.. (
|
||||
{
|
||||
inherit (cfg) config overlays;
|
||||
inherit _configDefinitions;
|
||||
inherit (cfg) overlays;
|
||||
}
|
||||
// systemArgs
|
||||
)
|
||||
else
|
||||
import ../../.. {
|
||||
inherit _configDefinitions;
|
||||
inherit (cfg)
|
||||
config
|
||||
overlays
|
||||
localSystem
|
||||
crossSystem
|
||||
@@ -126,13 +129,15 @@ in
|
||||
example = lib.literalExpression ''
|
||||
{ allowBroken = true; allowUnfree = true; }
|
||||
'';
|
||||
type = lib.types.submoduleWith {
|
||||
modules = [ ../../../pkgs/top-level/config.nix ];
|
||||
specialArgs = {
|
||||
docPrefix = "https://nixos.org/manual/nixpkgs/unstable/";
|
||||
};
|
||||
shorthandOnlyDefinesConfig = 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;
|
||||
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).
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
# 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 <nixpkgs> { ... })
|
||||
testStandaloneConfig = {
|
||||
expr = (import nixpkgsPath { config.allowUnfree = true; }).config.allowUnfree;
|
||||
expected = true;
|
||||
};
|
||||
|
||||
# Standalone nixpkgs with a function (i.e. import <nixpkgs> ({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.*";
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -128,6 +128,21 @@ 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 "${../..}"
|
||||
mkdir $out
|
||||
'';
|
||||
|
||||
top-level = callPackage ./top-level { };
|
||||
|
||||
haskell = callPackage ./haskell { };
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
docPrefix ? "",
|
||||
...
|
||||
}@args:
|
||||
}:
|
||||
|
||||
let
|
||||
docPrefix = args.docPrefix or "";
|
||||
inherit (lib)
|
||||
literalExpression
|
||||
mapAttrsToList
|
||||
@@ -471,7 +471,7 @@ let
|
||||
Silence the warning for the upcoming deprecation of the
|
||||
`x86_64-darwin` platform in Nixpkgs 26.11.
|
||||
|
||||
See the [release notes](#x86_64-darwin-26.05) for more
|
||||
See the [release notes](${docPrefix}#x86_64-darwin-26.05) for more
|
||||
information.
|
||||
'';
|
||||
};
|
||||
|
||||
+25
-10
@@ -64,6 +64,11 @@ 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:
|
||||
@@ -109,7 +114,13 @@ let
|
||||
then
|
||||
x86_64DarwinDeprecationWarning
|
||||
else
|
||||
x: x
|
||||
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`."
|
||||
);
|
||||
|
||||
localSystem = lib.systems.elaborate args.localSystem;
|
||||
@@ -134,20 +145,24 @@ let
|
||||
|
||||
# Allow both:
|
||||
# { /* the config */ } and
|
||||
# { pkgs, ... } : { /* the config */ }
|
||||
# { lib, pkgs, ... } : { /* the config */ }
|
||||
config1 = if lib.isFunction config0 then config0 { inherit lib pkgs; } else config0;
|
||||
|
||||
configEval = lib.evalModules {
|
||||
modules = [
|
||||
./config.nix
|
||||
(
|
||||
{ options, ... }:
|
||||
{
|
||||
_file = "nixpkgs.config";
|
||||
config = config1;
|
||||
}
|
||||
)
|
||||
];
|
||||
]
|
||||
++ (
|
||||
if _configDefinitions != null then
|
||||
map (def: lib.modules.setDefaultModuleLocation def.file def.value) _configDefinitions
|
||||
else
|
||||
[
|
||||
{
|
||||
_file = "nixpkgs.config";
|
||||
config = config1;
|
||||
}
|
||||
]
|
||||
);
|
||||
class = "nixpkgsConfig";
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user