heroic: fix fhsenv version (#359407)
[NixPkgs.git] / pkgs / os-specific / linux / kernel / generic.nix
blob046fb3fe6120262206ac920fbc7fba66d0c88bb9
1 { buildPackages
2 , callPackage
3 , perl
4 , bison ? null
5 , flex ? null
6 , gmp ? null
7 , libmpc ? null
8 , mpfr ? null
9 , pahole
10 , lib
11 , stdenv
12 , rustc
13 , rustPlatform
14 , rust-bindgen
15 # testing
16 , emptyFile
17 , nixos
18 , nixosTests
19 }@args':
21 let overridableKernel =
22 lib.makeOverridable ({ # The kernel source tarball.
23   src
25 , # The kernel version.
26   version
28 , # Allows overriding the default defconfig
29   defconfig ? null
31 , # Legacy overrides to the intermediate kernel config, as string
32   extraConfig ? ""
34   # Additional make flags passed to kbuild
35 , extraMakeFlags ? []
37 , # enables the options in ./common-config.nix; if `false` then only
38   # `structuredExtraConfig` is used
39  enableCommonConfig ? true
41 , # kernel intermediate config overrides, as a set
42  structuredExtraConfig ? {}
44 , # The version number used for the module directory
45   # If unspecified, this is determined automatically from the version.
46   modDirVersion ? null
48 , # An attribute set whose attributes express the availability of
49   # certain features in this kernel.  E.g. `{ia32Emulation = true;}'
50   # indicates a kernel that provides Intel wireless support.  Used in
51   # NixOS to implement kernel-specific behaviour.
52   features ? {}
54 , # Custom seed used for CONFIG_GCC_PLUGIN_RANDSTRUCT if enabled. This is
55   # automatically extended with extra per-version and per-config values.
56   randstructSeed ? ""
58 , # A list of patches to apply to the kernel.  Each element of this list
59   # should be an attribute set {name, patch} where `name' is a
60   # symbolic name and `patch' is the actual patch.  The patch may
61   # optionally be compressed with gzip or bzip2.
62   kernelPatches ? []
63 , ignoreConfigErrors ? stdenv.hostPlatform.linux-kernel.name != "pc"
64 , extraMeta ? {}
66 , isZen      ? false
67 , isLibre    ? false
68 , isHardened ? false
70 # easy overrides to stdenv.hostPlatform.linux-kernel members
71 , autoModules ? stdenv.hostPlatform.linux-kernel.autoModules
72 , preferBuiltin ? stdenv.hostPlatform.linux-kernel.preferBuiltin or false
73 , kernelArch ? stdenv.hostPlatform.linuxArch
74 , kernelTests ? {}
76 , stdenv ? args'.stdenv
77 , buildPackages ? args'.buildPackages
79 , ...
80 }@args:
82 # Note: this package is used for bootstrapping fetchurl, and thus
83 # cannot use fetchpatch! All mutable patches (generated by GitHub or
84 # cgit) that are needed here should be included directly in Nixpkgs as
85 # files.
87 assert stdenv.hostPlatform.isLinux;
89 let
90   # Dirty hack to make sure that `version` & `src` have
91   # `<nixpkgs/pkgs/os-specific/linux/kernel/linux-x.y.nix>` as position
92   # when using `builtins.unsafeGetAttrPos`.
93   #
94   # This is to make sure that ofborg actually detects changes in the kernel derivation
95   # and pings all maintainers.
96   #
97   # For further context, see https://github.com/NixOS/nixpkgs/pull/143113#issuecomment-953319957
98   basicArgs = builtins.removeAttrs
99     args
100     (lib.filter (x: ! (builtins.elem x [ "version" "pname" "src" ])) (lib.attrNames args));
102   # Combine the `features' attribute sets of all the kernel patches.
103   kernelFeatures = lib.foldr (x: y: (x.features or {}) // y) ({
104     efiBootStub = true;
105     netfilterRPFilter = true;
106     ia32Emulation = true;
107   } // features) kernelPatches;
109   commonStructuredConfig = import ./common-config.nix {
110     inherit lib stdenv version;
111     rustAvailable =
112       lib.any (lib.meta.platformMatch stdenv.hostPlatform) rustc.targetPlatforms
113       && lib.all (p: !lib.meta.platformMatch stdenv.hostPlatform p) rustc.badTargetPlatforms
114       # Known to be broken: https://lore.kernel.org/lkml/31885EDD-EF6D-4EF1-94CA-276BA7A340B7@kernel.org/T/
115       && !(stdenv.hostPlatform.isRiscV && stdenv.cc.isGNU);
117     features = kernelFeatures; # Ensure we know of all extra patches, etc.
118   };
120   intermediateNixConfig = configfile.moduleStructuredConfig.intermediateNixConfig
121     # extra config in legacy string format
122     + extraConfig
123     + stdenv.hostPlatform.linux-kernel.extraConfig or "";
125   structuredConfigFromPatches =
126         map ({extraStructuredConfig ? {}, ...}: {settings=extraStructuredConfig;}) kernelPatches;
128   # appends kernel patches extraConfig
129   kernelConfigFun = baseConfigStr:
130     let
131       configFromPatches =
132         map ({extraConfig ? "", ...}: extraConfig) kernelPatches;
133     in lib.concatStringsSep "\n" ([baseConfigStr] ++ configFromPatches);
135   withRust = ((configfile.moduleStructuredConfig.settings.RUST or {}).tristate or null) == "y";
137   configfile = stdenv.mkDerivation {
138     inherit ignoreConfigErrors autoModules preferBuiltin kernelArch extraMakeFlags;
139     pname = "linux-config";
140     inherit version;
142     generateConfig = ./generate-config.pl;
144     kernelConfig = kernelConfigFun intermediateNixConfig;
145     passAsFile = [ "kernelConfig" ];
147     depsBuildBuild = [ buildPackages.stdenv.cc ];
148     nativeBuildInputs = [ perl gmp libmpc mpfr bison flex ]
149       ++ lib.optional (lib.versionAtLeast version "5.2") pahole
150       ++ lib.optionals withRust [ rust-bindgen rustc ]
151     ;
153     RUST_LIB_SRC = lib.optionalString withRust rustPlatform.rustLibSrc;
155     platformName = stdenv.hostPlatform.linux-kernel.name;
156     # e.g. "defconfig"
157     kernelBaseConfig = if defconfig != null then defconfig else stdenv.hostPlatform.linux-kernel.baseConfig;
159     makeFlags = lib.optionals (stdenv.hostPlatform.linux-kernel ? makeFlags) stdenv.hostPlatform.linux-kernel.makeFlags
160       ++ extraMakeFlags;
162     postPatch = kernel.postPatch + ''
163       # Patch kconfig to print "###" after every question so that
164       # generate-config.pl from the generic builder can answer them.
165       sed -e '/fflush(stdout);/i\printf("###");' -i scripts/kconfig/conf.c
166     '';
168     preUnpack = kernel.preUnpack or "";
170     inherit (kernel) src patches;
172     buildPhase = ''
173       export buildRoot="''${buildRoot:-build}"
174       export HOSTCC=$CC_FOR_BUILD
175       export HOSTCXX=$CXX_FOR_BUILD
176       export HOSTAR=$AR_FOR_BUILD
177       export HOSTLD=$LD_FOR_BUILD
179       # Get a basic config file for later refinement with $generateConfig.
180       make $makeFlags \
181           -C . O="$buildRoot" $kernelBaseConfig \
182           ARCH=$kernelArch \
183           HOSTCC=$HOSTCC HOSTCXX=$HOSTCXX HOSTAR=$HOSTAR HOSTLD=$HOSTLD \
184           CC=$CC OBJCOPY=$OBJCOPY OBJDUMP=$OBJDUMP READELF=$READELF \
185           $makeFlags
187       # Create the config file.
188       echo "generating kernel configuration..."
189       ln -s "$kernelConfigPath" "$buildRoot/kernel-config"
190       DEBUG=1 ARCH=$kernelArch KERNEL_CONFIG="$buildRoot/kernel-config" AUTO_MODULES=$autoModules \
191         PREFER_BUILTIN=$preferBuiltin BUILD_ROOT="$buildRoot" SRC=. MAKE_FLAGS="$makeFlags" \
192         perl -w $generateConfig
193     '';
195     installPhase = "mv $buildRoot/.config $out";
197     enableParallelBuilding = true;
199     passthru = rec {
200       module = import ../../../../nixos/modules/system/boot/kernel_config.nix;
201       # used also in apache
202       # { modules = [ { options = res.options; config = svc.config or svc; } ];
203       #   check = false;
204       # The result is a set of two attributes
205       moduleStructuredConfig = (lib.evalModules {
206         modules = [
207           module
208         ] ++ lib.optionals enableCommonConfig [
209           { settings = commonStructuredConfig; _file = "pkgs/os-specific/linux/kernel/common-config.nix"; }
210         ] ++ [
211           { settings = structuredExtraConfig; _file = "structuredExtraConfig"; }
212         ]
213         ++  structuredConfigFromPatches
214         ;
215       }).config;
217       structuredConfig = moduleStructuredConfig.settings;
218     };
219   }; # end of configfile derivation
221   kernel = (callPackage ./manual-config.nix { inherit lib stdenv buildPackages; }) (basicArgs // {
222     inherit kernelPatches randstructSeed extraMakeFlags extraMeta configfile modDirVersion;
223     pos = builtins.unsafeGetAttrPos "version" args;
225     config = {
226       CONFIG_MODULES = "y";
227       CONFIG_FW_LOADER = "y";
228       CONFIG_RUST = if withRust then "y" else "n";
229     };
230   });
233 kernel.overrideAttrs (finalAttrs: previousAttrs: {
235   passthru = previousAttrs.passthru or { } // basicArgs // {
236     features = kernelFeatures;
237     inherit commonStructuredConfig structuredExtraConfig extraMakeFlags isZen isHardened isLibre;
238     isXen = lib.warn "The isXen attribute is deprecated. All Nixpkgs kernels that support it now have Xen enabled." true;
240     # Adds dependencies needed to edit the config:
241     # nix-shell '<nixpkgs>' -A linux.configEnv --command 'make nconfig'
242     configEnv = kernel.overrideAttrs (old: {
243       nativeBuildInputs = old.nativeBuildInputs or [] ++ (with buildPackages; [
244         pkg-config ncurses
245       ]);
246     });
248     tests = let
249       overridableKernel = finalAttrs.finalPackage // {
250         override = args:
251           lib.warn (
252             "override is stubbed for NixOS kernel tests, not applying changes these arguments: "
253             + toString (lib.attrNames (lib.toFunction args { }))
254           ) overridableKernel;
255       };
256       /* Certain arguments must be evaluated lazily; so that only the output(s) depend on them.
257          Original reproducer / simplified use case:
258        */
259       versionDoesNotDependOnPatchesEtcNixOS =
260         builtins.seq
261           (nixos ({ config, pkgs, ... }: {
262               boot.kernelPatches = [
263                 (builtins.seq config.boot.kernelPackages.kernel.version { patch = pkgs.emptyFile; })
264               ];
265           })).config.boot.kernelPackages.kernel.outPath
266           emptyFile;
267       versionDoesNotDependOnPatchesEtc =
268         builtins.seq
269           (import ./generic.nix args' (args // (
270           let explain = attrName:
271             ''
272               The ${attrName} attribute must be able to access the kernel.version attribute without an infinite recursion.
273               That means that the kernel attrset (attrNames) and the kernel.version attribute must not depend on the ${attrName} argument.
274               The fact that this exception is raised shows that such a dependency does exist.
275               This is a problem for the configurability of ${attrName} in version-aware logic such as that in NixOS.
276               Strictness can creep in through optional attributes, or assertions and warnings that run as part of code that shouldn't access what is checked.
277             '';
278           in {
279             kernelPatches = throw (explain "kernelPatches");
280             structuredExtraConfig = throw (explain "structuredExtraConfig");
281             modDirVersion = throw (explain "modDirVersion");
282           }))).version
283           emptyFile;
284     in {
285       inherit versionDoesNotDependOnPatchesEtc;
286       testsForKernel = nixosTests.kernel-generic.passthru.testsForKernel overridableKernel;
287       # Disabled by default, because the infinite recursion is hard to understand. The other test's error is better and produces a shorter trace.
288       # inherit versionDoesNotDependOnPatchesEtcNixOS;
289     } // kernelTests;
290   };
292 }));
293 in overridableKernel