diff --git a/pkgs/os-specific/linux/kernel/generic.nix b/pkgs/os-specific/linux/kernel/generic.nix index 456e9052d5c2..65ba04438ff8 100644 --- a/pkgs/os-specific/linux/kernel/generic.nix +++ b/pkgs/os-specific/linux/kernel/generic.nix @@ -20,378 +20,375 @@ nixosTests, }@args': -let - overridableKernel = lib.makeOverridable ( - # The kernel source tarball. - { - pname ? "linux", +lib.makeOverridable ( + # The kernel source tarball. + { + pname ? "linux", - src, + src, - # The kernel version. - version, + # The kernel version. + version, - # Allows overriding the default defconfig - defconfig ? null, + # Allows overriding the default defconfig + defconfig ? null, - # Legacy overrides to the intermediate kernel config, as string - extraConfig ? "", + # Legacy overrides to the intermediate kernel config, as string + extraConfig ? "", - # Additional make flags passed to kbuild - extraMakeFlags ? [ ], + # Additional make flags passed to kbuild + extraMakeFlags ? [ ], - # enables the options in ./common-config.nix and lib/systems/platform.nix; - # if `false` then only `structuredExtraConfig` is used - enableCommonConfig ? true + # enables the options in ./common-config.nix and lib/systems/platform.nix; + # if `false` then only `structuredExtraConfig` is used + enableCommonConfig ? true - , # kernel intermediate config overrides, as a set - structuredExtraConfig ? { }, + , # kernel intermediate config overrides, as a set + structuredExtraConfig ? { }, - # The version number used for the module directory - # If unspecified, this is determined automatically from the version. - modDirVersion ? null, + # The version number used for the module directory + # If unspecified, this is determined automatically from the version. + modDirVersion ? null, - # An attribute set whose attributes express the availability of - # certain features in this kernel. E.g. `{ia32Emulation = true;}' - # indicates a kernel that provides Intel wireless support. Used in - # NixOS to implement kernel-specific behaviour. - features ? { }, + # An attribute set whose attributes express the availability of + # certain features in this kernel. E.g. `{ia32Emulation = true;}' + # indicates a kernel that provides Intel wireless support. Used in + # NixOS to implement kernel-specific behaviour. + features ? { }, - # Custom seed used for CONFIG_GCC_PLUGIN_RANDSTRUCT if enabled. This is - # automatically extended with extra per-version and per-config values. - randstructSeed ? "", + # Custom seed used for CONFIG_GCC_PLUGIN_RANDSTRUCT if enabled. This is + # automatically extended with extra per-version and per-config values. + randstructSeed ? "", - # A list of patches to apply to the kernel. Each element of this list - # should be an attribute set {name, patch} where `name' is a - # symbolic name and `patch' is the actual patch. The patch may - # optionally be compressed with gzip or bzip2. - kernelPatches ? [ ], - ignoreConfigErrors ? - !lib.elem stdenv.hostPlatform.linux-kernel.name or "" [ - "aarch64-multiplatform" - "pc" - ], - extraMeta ? { }, - extraPassthru ? { }, + # A list of patches to apply to the kernel. Each element of this list + # should be an attribute set {name, patch} where `name' is a + # symbolic name and `patch' is the actual patch. The patch may + # optionally be compressed with gzip or bzip2. + kernelPatches ? [ ], + ignoreConfigErrors ? + !lib.elem stdenv.hostPlatform.linux-kernel.name or "" [ + "aarch64-multiplatform" + "pc" + ], + extraMeta ? { }, + extraPassthru ? { }, - isLTS ? false, - isZen ? false, - isLibre ? false, - isHardened ? false, + isLTS ? false, + isZen ? false, + isLibre ? false, + isHardened ? false, - # easy overrides to stdenv.hostPlatform.linux-kernel members - autoModules ? stdenv.hostPlatform.linux-kernel.autoModules or true, - preferBuiltin ? stdenv.hostPlatform.linux-kernel.preferBuiltin or false, - kernelArch ? stdenv.hostPlatform.linuxArch, - kernelTests ? { }, + # easy overrides to stdenv.hostPlatform.linux-kernel members + autoModules ? stdenv.hostPlatform.linux-kernel.autoModules or true, + preferBuiltin ? stdenv.hostPlatform.linux-kernel.preferBuiltin or false, + kernelArch ? stdenv.hostPlatform.linuxArch, + kernelTests ? { }, - stdenv ? args'.stdenv, - buildPackages ? args'.buildPackages, - pkgsBuildBuild ? args'.pkgsBuildBuild, + stdenv ? args'.stdenv, + buildPackages ? args'.buildPackages, + pkgsBuildBuild ? args'.pkgsBuildBuild, - ... - }@args: + ... + }@args: - # Note: this package is used for bootstrapping fetchurl, and thus - # cannot use fetchpatch! All mutable patches (generated by GitHub or - # cgit) that are needed here should be included directly in Nixpkgs as - # files. - - let - # Combine the `features' attribute sets of all the kernel patches. - kernelFeatures = lib.foldr (x: y: (x.features or { }) // y) ( - { - efiBootStub = true; - netfilterRPFilter = true; - ia32Emulation = true; - } - // features - ) kernelPatches; - - commonStructuredConfig = import ./common-config.nix { - inherit lib stdenv version; - rustAvailable = lib.meta.availableOn stdenv.hostPlatform rustc-unwrapped; - - features = kernelFeatures; # Ensure we know of all extra patches, etc. - }; - - intermediateNixConfig = - configfile.moduleStructuredConfig.intermediateNixConfig - # extra config in legacy string format - + extraConfig - # need the 'or ""' at the end in case enableCommonConfig = true and extraConfig is not present - + lib.optionalString enableCommonConfig stdenv.hostPlatform.linux-kernel.extraConfig or ""; - - structuredConfigFromPatches = map ( - { - structuredExtraConfig ? { }, - ... - }@args: - if args ? extraStructuredConfig then - throw '' - Passing `extraStructuredConfig` to the Linux kernel (e.g. - via `boot.kernelPatches` in NixOS) is not supported anymore. Use - `structuredExtraConfig` instead. - '' - else - { - settings = structuredExtraConfig; - } - ) kernelPatches; - - # appends kernel patches extraConfig - kernelConfigFun = - baseConfigStr: - let - configFromPatches = map ( - { - extraConfig ? "", - ... - }: - extraConfig - ) kernelPatches; - in - lib.concatStringsSep "\n" ([ baseConfigStr ] ++ configFromPatches); - - withRust = ((configfile.moduleStructuredConfig.settings.RUST or { }).tristate or null) == "y"; - - configfile = stdenv.mkDerivation { - inherit - ignoreConfigErrors - autoModules - preferBuiltin - kernelArch - extraMakeFlags - ; - pname = "linux-config"; - inherit version; - - generateConfig = ./generate-config.pl; - - kernelConfig = kernelConfigFun intermediateNixConfig; - passAsFile = [ "kernelConfig" ]; - - depsBuildBuild = [ buildPackages.stdenv.cc ]; - nativeBuildInputs = [ - perl - gmp - libmpc - mpfr - bison - flex - ] - ++ lib.optional (lib.versionAtLeast version "5.2") pahole - ++ lib.optionals withRust [ - rust-bindgen-unwrapped - rustc-unwrapped - ]; - - RUST_LIB_SRC = lib.optionalString withRust rustPlatform.rustLibSrc; - - # e.g. "defconfig" - kernelBaseConfig = - if defconfig != null then defconfig else stdenv.hostPlatform.linux-kernel.baseConfig or "defconfig"; - - makeFlags = import ./common-flags.nix { - inherit - lib - stdenv - buildPackages - extraMakeFlags - ; - }; - - postPatch = kernel.postPatch + '' - # Patch kconfig to print "###" after every question so that - # generate-config.pl from the generic builder can answer them. - sed -e '/fflush(stdout);/i\printf("###");' -i scripts/kconfig/conf.c - ''; - - preUnpack = kernel.preUnpack or ""; - - inherit (kernel) src patches; - - buildPhase = '' - export buildRoot="''${buildRoot:-build}" - - # Get a basic config file for later refinement with $generateConfig. - make $makeFlags \ - -C . O="$buildRoot" $kernelBaseConfig \ - ARCH=$kernelArch CROSS_COMPILE=${stdenv.cc.targetPrefix} \ - $makeFlags - - # Create the config file. - echo "generating kernel configuration..." - ln -s "$kernelConfigPath" "$buildRoot/kernel-config" - DEBUG=1 ARCH=$kernelArch CROSS_COMPILE=${stdenv.cc.targetPrefix} \ - KERNEL_CONFIG="$buildRoot/kernel-config" AUTO_MODULES=$autoModules \ - PREFER_BUILTIN=$preferBuiltin BUILD_ROOT="$buildRoot" SRC=. MAKE_FLAGS="$makeFlags" \ - perl -w $generateConfig - '' - + lib.optionalString stdenv.cc.isClang '' - if ! grep -Fq CONFIG_CC_IS_CLANG=y $buildRoot/.config; then - echo "Kernel config didn't recognize the clang compiler?" - exit 1 - fi - '' - + lib.optionalString stdenv.cc.bintools.isLLVM '' - if ! grep -Fq CONFIG_LD_IS_LLD=y $buildRoot/.config; then - echo "Kernel config didn't recognize the LLVM linker?" - exit 1 - fi - '' - + lib.optionalString withRust '' - if ! grep -Fq CONFIG_RUST_IS_AVAILABLE=y $buildRoot/.config; then - echo "Kernel config didn't find Rust toolchain?" - exit 1 - fi - ''; - - installPhase = "mv $buildRoot/.config $out"; - - enableParallelBuilding = true; - - passthru = rec { - module = import ../../../../nixos/modules/system/boot/kernel_config.nix; - # used also in apache - # { modules = [ { options = res.options; config = svc.config or svc; } ]; - # check = false; - # The result is a set of two attributes - moduleStructuredConfig = - (lib.evalModules { - modules = [ - module - ] - ++ lib.optionals enableCommonConfig [ - { - settings = commonStructuredConfig; - _file = "pkgs/os-specific/linux/kernel/common-config.nix"; - } - ] - ++ [ - { - settings = structuredExtraConfig; - _file = "structuredExtraConfig"; - } - ] - ++ structuredConfigFromPatches; - }).config; - - structuredConfig = moduleStructuredConfig.settings; - }; - }; # end of configfile derivation - - kernel = (callPackage ./build.nix { inherit lib stdenv buildPackages; }) { - inherit - pname - version - src - kernelPatches - randstructSeed - extraMakeFlags - extraMeta - configfile - modDirVersion - ; - pos = builtins.unsafeGetAttrPos "version" args; - - config = { - CONFIG_MODULES = "y"; - CONFIG_FW_LOADER = "y"; - CONFIG_RUST = if withRust then "y" else "n"; - }; - }; - - in - kernel.overrideAttrs ( - finalAttrs: previousAttrs: { - - passthru = - previousAttrs.passthru or { } - // extraPassthru - // { - features = kernelFeatures; - inherit - commonStructuredConfig - structuredExtraConfig - extraMakeFlags - isLTS - isZen - isHardened - isLibre - ; - isXen = lib.warn "The isXen attribute is deprecated. All Nixpkgs kernels that support it now have Xen enabled." true; - - # Adds dependencies needed to edit the config: - # nix-shell '' -A linux.configEnv --command 'make nconfig' - configEnv = finalAttrs.finalPackage.overrideAttrs (previousAttrs: { - depsBuildBuild = - previousAttrs.depsBuildBuild or [ ] - ++ (with pkgsBuildBuild; [ - pkg-config - ncurses - ]); - }); - - tests = - let - overridableKernel = finalAttrs.finalPackage // { - override = - args: - lib.warn ( - "override is stubbed for NixOS kernel tests, not applying changes these arguments: " - + toString (lib.attrNames (lib.toFunction args { })) - ) overridableKernel; - }; - /* - Certain arguments must be evaluated lazily; so that only the output(s) depend on them. - Original reproducer / simplified use case: - */ - versionDoesNotDependOnPatchesEtcNixOS = - builtins.seq - (nixos ( - { config, pkgs, ... }: - { - boot.kernelPatches = [ - (builtins.seq config.boot.kernelPackages.kernel.version { patch = pkgs.emptyFile; }) - ]; - } - )).config.boot.kernelPackages.kernel.outPath - emptyFile; - versionDoesNotDependOnPatchesEtc = - builtins.seq - (import ./generic.nix args' ( - args - // ( - let - explain = attrName: '' - The ${attrName} attribute must be able to access the kernel.version attribute without an infinite recursion. - That means that the kernel attrset (attrNames) and the kernel.version attribute must not depend on the ${attrName} argument. - The fact that this exception is raised shows that such a dependency does exist. - This is a problem for the configurability of ${attrName} in version-aware logic such as that in NixOS. - Strictness can creep in through optional attributes, or assertions and warnings that run as part of code that shouldn't access what is checked. - ''; - in - { - kernelPatches = throw (explain "kernelPatches"); - structuredExtraConfig = throw (explain "structuredExtraConfig"); - modDirVersion = throw (explain "modDirVersion"); - } - ) - )).version - emptyFile; - in - { - inherit versionDoesNotDependOnPatchesEtc; - testsForKernel = nixosTests.kernel-generic.passthru.testsForKernel overridableKernel; - # Disabled by default, because the infinite recursion is hard to understand. The other test's error is better and produces a shorter trace. - # inherit versionDoesNotDependOnPatchesEtcNixOS; - } - // kernelTests; - }; + # Note: this package is used for bootstrapping fetchurl, and thus + # cannot use fetchpatch! All mutable patches (generated by GitHub or + # cgit) that are needed here should be included directly in Nixpkgs as + # files. + let + # Combine the `features' attribute sets of all the kernel patches. + kernelFeatures = lib.foldr (x: y: (x.features or { }) // y) ( + { + efiBootStub = true; + netfilterRPFilter = true; + ia32Emulation = true; } - ) - ); -in -overridableKernel + // features + ) kernelPatches; + + commonStructuredConfig = import ./common-config.nix { + inherit lib stdenv version; + rustAvailable = lib.meta.availableOn stdenv.hostPlatform rustc-unwrapped; + + features = kernelFeatures; # Ensure we know of all extra patches, etc. + }; + + intermediateNixConfig = + configfile.moduleStructuredConfig.intermediateNixConfig + # extra config in legacy string format + + extraConfig + # need the 'or ""' at the end in case enableCommonConfig = true and extraConfig is not present + + lib.optionalString enableCommonConfig stdenv.hostPlatform.linux-kernel.extraConfig or ""; + + structuredConfigFromPatches = map ( + { + structuredExtraConfig ? { }, + ... + }@args: + if args ? extraStructuredConfig then + throw '' + Passing `extraStructuredConfig` to the Linux kernel (e.g. + via `boot.kernelPatches` in NixOS) is not supported anymore. Use + `structuredExtraConfig` instead. + '' + else + { + settings = structuredExtraConfig; + } + ) kernelPatches; + + # appends kernel patches extraConfig + kernelConfigFun = + baseConfigStr: + let + configFromPatches = map ( + { + extraConfig ? "", + ... + }: + extraConfig + ) kernelPatches; + in + lib.concatStringsSep "\n" ([ baseConfigStr ] ++ configFromPatches); + + withRust = ((configfile.moduleStructuredConfig.settings.RUST or { }).tristate or null) == "y"; + + configfile = stdenv.mkDerivation { + inherit + ignoreConfigErrors + autoModules + preferBuiltin + kernelArch + extraMakeFlags + ; + pname = "linux-config"; + inherit version; + + generateConfig = ./generate-config.pl; + + kernelConfig = kernelConfigFun intermediateNixConfig; + passAsFile = [ "kernelConfig" ]; + + depsBuildBuild = [ buildPackages.stdenv.cc ]; + nativeBuildInputs = [ + perl + gmp + libmpc + mpfr + bison + flex + ] + ++ lib.optional (lib.versionAtLeast version "5.2") pahole + ++ lib.optionals withRust [ + rust-bindgen-unwrapped + rustc-unwrapped + ]; + + RUST_LIB_SRC = lib.optionalString withRust rustPlatform.rustLibSrc; + + # e.g. "defconfig" + kernelBaseConfig = + if defconfig != null then defconfig else stdenv.hostPlatform.linux-kernel.baseConfig or "defconfig"; + + makeFlags = import ./common-flags.nix { + inherit + lib + stdenv + buildPackages + extraMakeFlags + ; + }; + + postPatch = kernel.postPatch + '' + # Patch kconfig to print "###" after every question so that + # generate-config.pl from the generic builder can answer them. + sed -e '/fflush(stdout);/i\printf("###");' -i scripts/kconfig/conf.c + ''; + + preUnpack = kernel.preUnpack or ""; + + inherit (kernel) src patches; + + buildPhase = '' + export buildRoot="''${buildRoot:-build}" + + # Get a basic config file for later refinement with $generateConfig. + make $makeFlags \ + -C . O="$buildRoot" $kernelBaseConfig \ + ARCH=$kernelArch CROSS_COMPILE=${stdenv.cc.targetPrefix} \ + $makeFlags + + # Create the config file. + echo "generating kernel configuration..." + ln -s "$kernelConfigPath" "$buildRoot/kernel-config" + DEBUG=1 ARCH=$kernelArch CROSS_COMPILE=${stdenv.cc.targetPrefix} \ + KERNEL_CONFIG="$buildRoot/kernel-config" AUTO_MODULES=$autoModules \ + PREFER_BUILTIN=$preferBuiltin BUILD_ROOT="$buildRoot" SRC=. MAKE_FLAGS="$makeFlags" \ + perl -w $generateConfig + '' + + lib.optionalString stdenv.cc.isClang '' + if ! grep -Fq CONFIG_CC_IS_CLANG=y $buildRoot/.config; then + echo "Kernel config didn't recognize the clang compiler?" + exit 1 + fi + '' + + lib.optionalString stdenv.cc.bintools.isLLVM '' + if ! grep -Fq CONFIG_LD_IS_LLD=y $buildRoot/.config; then + echo "Kernel config didn't recognize the LLVM linker?" + exit 1 + fi + '' + + lib.optionalString withRust '' + if ! grep -Fq CONFIG_RUST_IS_AVAILABLE=y $buildRoot/.config; then + echo "Kernel config didn't find Rust toolchain?" + exit 1 + fi + ''; + + installPhase = "mv $buildRoot/.config $out"; + + enableParallelBuilding = true; + + passthru = rec { + module = import ../../../../nixos/modules/system/boot/kernel_config.nix; + # used also in apache + # { modules = [ { options = res.options; config = svc.config or svc; } ]; + # check = false; + # The result is a set of two attributes + moduleStructuredConfig = + (lib.evalModules { + modules = [ + module + ] + ++ lib.optionals enableCommonConfig [ + { + settings = commonStructuredConfig; + _file = "pkgs/os-specific/linux/kernel/common-config.nix"; + } + ] + ++ [ + { + settings = structuredExtraConfig; + _file = "structuredExtraConfig"; + } + ] + ++ structuredConfigFromPatches; + }).config; + + structuredConfig = moduleStructuredConfig.settings; + }; + }; # end of configfile derivation + + kernel = (callPackage ./build.nix { inherit lib stdenv buildPackages; }) { + inherit + pname + version + src + kernelPatches + randstructSeed + extraMakeFlags + extraMeta + configfile + modDirVersion + ; + pos = builtins.unsafeGetAttrPos "version" args; + + config = { + CONFIG_MODULES = "y"; + CONFIG_FW_LOADER = "y"; + CONFIG_RUST = if withRust then "y" else "n"; + }; + }; + + in + kernel.overrideAttrs ( + finalAttrs: previousAttrs: { + + passthru = + previousAttrs.passthru or { } + // extraPassthru + // { + features = kernelFeatures; + inherit + commonStructuredConfig + structuredExtraConfig + extraMakeFlags + isLTS + isZen + isHardened + isLibre + ; + isXen = lib.warn "The isXen attribute is deprecated. All Nixpkgs kernels that support it now have Xen enabled." true; + + # Adds dependencies needed to edit the config: + # nix-shell '' -A linux.configEnv --command 'make nconfig' + configEnv = finalAttrs.finalPackage.overrideAttrs (previousAttrs: { + depsBuildBuild = + previousAttrs.depsBuildBuild or [ ] + ++ (with pkgsBuildBuild; [ + pkg-config + ncurses + ]); + }); + + tests = + let + overridableKernel = finalAttrs.finalPackage // { + override = + args: + lib.warn ( + "override is stubbed for NixOS kernel tests, not applying changes these arguments: " + + toString (lib.attrNames (lib.toFunction args { })) + ) overridableKernel; + }; + /* + Certain arguments must be evaluated lazily; so that only the output(s) depend on them. + Original reproducer / simplified use case: + */ + versionDoesNotDependOnPatchesEtcNixOS = + builtins.seq + (nixos ( + { config, pkgs, ... }: + { + boot.kernelPatches = [ + (builtins.seq config.boot.kernelPackages.kernel.version { patch = pkgs.emptyFile; }) + ]; + } + )).config.boot.kernelPackages.kernel.outPath + emptyFile; + versionDoesNotDependOnPatchesEtc = + builtins.seq + (import ./generic.nix args' ( + args + // ( + let + explain = attrName: '' + The ${attrName} attribute must be able to access the kernel.version attribute without an infinite recursion. + That means that the kernel attrset (attrNames) and the kernel.version attribute must not depend on the ${attrName} argument. + The fact that this exception is raised shows that such a dependency does exist. + This is a problem for the configurability of ${attrName} in version-aware logic such as that in NixOS. + Strictness can creep in through optional attributes, or assertions and warnings that run as part of code that shouldn't access what is checked. + ''; + in + { + kernelPatches = throw (explain "kernelPatches"); + structuredExtraConfig = throw (explain "structuredExtraConfig"); + modDirVersion = throw (explain "modDirVersion"); + } + ) + )).version + emptyFile; + in + { + inherit versionDoesNotDependOnPatchesEtc; + testsForKernel = nixosTests.kernel-generic.passthru.testsForKernel overridableKernel; + # Disabled by default, because the infinite recursion is hard to understand. The other test's error is better and produces a shorter trace. + # inherit versionDoesNotDependOnPatchesEtcNixOS; + } + // kernelTests; + }; + + } + ) +)