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':
20
21let overridableKernel =
22lib.makeOverridable ({ # The kernel source tarball.
23 src
24
25, # The kernel version.
26 version
27
28, # Allows overriding the default defconfig
29 defconfig ? null
30
31, # Legacy overrides to the intermediate kernel config, as string
32 extraConfig ? ""
33
34 # Additional make flags passed to kbuild
35, extraMakeFlags ? []
36
37, # enables the options in ./common-config.nix; if `false` then only
38 # `structuredExtraConfig` is used
39 enableCommonConfig ? true
40
41, # kernel intermediate config overrides, as a set
42 structuredExtraConfig ? {}
43
44, # The version number used for the module directory
45 # If unspecified, this is determined automatically from the version.
46 modDirVersion ? null
47
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 ? {}
53
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 ? ""
57
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 ? {}
65
66, isZen ? false
67, isLibre ? false
68, isHardened ? false
69
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 ? []
75
76, stdenv ? args'.stdenv
77, buildPackages ? args'.buildPackages
78
79, ...
80}@args:
81
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.
86
87assert stdenv.isLinux;
88
89let
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));
101
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;
108
109 commonStructuredConfig = import ./common-config.nix {
110 inherit lib stdenv version;
111
112 features = kernelFeatures; # Ensure we know of all extra patches, etc.
113 };
114
115 intermediateNixConfig = configfile.moduleStructuredConfig.intermediateNixConfig
116 # extra config in legacy string format
117 + extraConfig
118 + stdenv.hostPlatform.linux-kernel.extraConfig or "";
119
120 structuredConfigFromPatches =
121 map ({extraStructuredConfig ? {}, ...}: {settings=extraStructuredConfig;}) kernelPatches;
122
123 # appends kernel patches extraConfig
124 kernelConfigFun = baseConfigStr:
125 let
126 configFromPatches =
127 map ({extraConfig ? "", ...}: extraConfig) kernelPatches;
128 in lib.concatStringsSep "\n" ([baseConfigStr] ++ configFromPatches);
129
130 withRust = ((configfile.moduleStructuredConfig.settings.RUST or {}).tristate or null) == "y";
131
132 configfile = stdenv.mkDerivation {
133 inherit ignoreConfigErrors autoModules preferBuiltin kernelArch extraMakeFlags;
134 pname = "linux-config";
135 inherit version;
136
137 generateConfig = ./generate-config.pl;
138
139 kernelConfig = kernelConfigFun intermediateNixConfig;
140 passAsFile = [ "kernelConfig" ];
141
142 depsBuildBuild = [ buildPackages.stdenv.cc ];
143 nativeBuildInputs = [ perl gmp libmpc mpfr bison flex ]
144 ++ lib.optional (lib.versionAtLeast version "5.2") pahole
145 ++ lib.optionals withRust [ rust-bindgen rustc ]
146 ;
147
148 RUST_LIB_SRC = lib.optionalString withRust rustPlatform.rustLibSrc;
149
150 platformName = stdenv.hostPlatform.linux-kernel.name;
151 # e.g. "defconfig"
152 kernelBaseConfig = if defconfig != null then defconfig else stdenv.hostPlatform.linux-kernel.baseConfig;
153
154 makeFlags = lib.optionals (stdenv.hostPlatform.linux-kernel ? makeFlags) stdenv.hostPlatform.linux-kernel.makeFlags
155 ++ extraMakeFlags;
156
157 postPatch = kernel.postPatch + ''
158 # Patch kconfig to print "###" after every question so that
159 # generate-config.pl from the generic builder can answer them.
160 sed -e '/fflush(stdout);/i\printf("###");' -i scripts/kconfig/conf.c
161 '';
162
163 preUnpack = kernel.preUnpack or "";
164
165 inherit (kernel) src patches;
166
167 buildPhase = ''
168 export buildRoot="''${buildRoot:-build}"
169 export HOSTCC=$CC_FOR_BUILD
170 export HOSTCXX=$CXX_FOR_BUILD
171 export HOSTAR=$AR_FOR_BUILD
172 export HOSTLD=$LD_FOR_BUILD
173
174 # Get a basic config file for later refinement with $generateConfig.
175 make $makeFlags \
176 -C . O="$buildRoot" $kernelBaseConfig \
177 ARCH=$kernelArch \
178 HOSTCC=$HOSTCC HOSTCXX=$HOSTCXX HOSTAR=$HOSTAR HOSTLD=$HOSTLD \
179 CC=$CC OBJCOPY=$OBJCOPY OBJDUMP=$OBJDUMP READELF=$READELF \
180 $makeFlags
181
182 # Create the config file.
183 echo "generating kernel configuration..."
184 ln -s "$kernelConfigPath" "$buildRoot/kernel-config"
185 DEBUG=1 ARCH=$kernelArch KERNEL_CONFIG="$buildRoot/kernel-config" AUTO_MODULES=$autoModules \
186 PREFER_BUILTIN=$preferBuiltin BUILD_ROOT="$buildRoot" SRC=. MAKE_FLAGS="$makeFlags" \
187 perl -w $generateConfig
188 '';
189
190 installPhase = "mv $buildRoot/.config $out";
191
192 enableParallelBuilding = true;
193
194 passthru = rec {
195 module = import ../../../../nixos/modules/system/boot/kernel_config.nix;
196 # used also in apache
197 # { modules = [ { options = res.options; config = svc.config or svc; } ];
198 # check = false;
199 # The result is a set of two attributes
200 moduleStructuredConfig = (lib.evalModules {
201 modules = [
202 module
203 ] ++ lib.optionals enableCommonConfig [
204 { settings = commonStructuredConfig; _file = "pkgs/os-specific/linux/kernel/common-config.nix"; }
205 ] ++ [
206 { settings = structuredExtraConfig; _file = "structuredExtraConfig"; }
207 ]
208 ++ structuredConfigFromPatches
209 ;
210 }).config;
211
212 structuredConfig = moduleStructuredConfig.settings;
213 };
214 }; # end of configfile derivation
215
216 kernel = (callPackage ./manual-config.nix { inherit lib stdenv buildPackages; }) (basicArgs // {
217 inherit kernelPatches randstructSeed extraMakeFlags extraMeta configfile modDirVersion;
218 pos = builtins.unsafeGetAttrPos "version" args;
219
220 config = {
221 CONFIG_MODULES = "y";
222 CONFIG_FW_LOADER = "y";
223 CONFIG_RUST = if withRust then "y" else "n";
224 };
225 });
226
227in
228kernel.overrideAttrs (finalAttrs: previousAttrs: {
229
230 passthru = previousAttrs.passthru or { } // basicArgs // {
231 features = kernelFeatures;
232 inherit commonStructuredConfig structuredExtraConfig extraMakeFlags isZen isHardened isLibre;
233 isXen = lib.warn "The isXen attribute is deprecated. All Nixpkgs kernels that support it now have Xen enabled." true;
234
235 # Adds dependencies needed to edit the config:
236 # nix-shell '<nixpkgs>' -A linux.configEnv --command 'make nconfig'
237 configEnv = kernel.overrideAttrs (old: {
238 nativeBuildInputs = old.nativeBuildInputs or [] ++ (with buildPackages; [
239 pkg-config ncurses
240 ]);
241 });
242
243 tests = let
244 overridableKernel = finalAttrs.finalPackage // {
245 override = args:
246 lib.warn (
247 "override is stubbed for NixOS kernel tests, not applying changes these arguments: "
248 + toString (lib.attrNames (lib.toFunction args { }))
249 ) overridableKernel;
250 };
251 /* Certain arguments must be evaluated lazily; so that only the output(s) depend on them.
252 Original reproducer / simplified use case:
253 */
254 versionDoesNotDependOnPatchesEtcNixOS =
255 builtins.seq
256 (nixos ({ config, pkgs, ... }: {
257 boot.kernelPatches = [
258 (builtins.seq config.boot.kernelPackages.kernel.version { patch = pkgs.emptyFile; })
259 ];
260 })).config.boot.kernelPackages.kernel.outPath
261 emptyFile;
262 versionDoesNotDependOnPatchesEtc =
263 builtins.seq
264 (import ./generic.nix args' (args // (
265 let explain = attrName:
266 ''
267 The ${attrName} attribute must be able to access the kernel.version attribute without an infinite recursion.
268 That means that the kernel attrset (attrNames) and the kernel.version attribute must not depend on the ${attrName} argument.
269 The fact that this exception is raised shows that such a dependency does exist.
270 This is a problem for the configurability of ${attrName} in version-aware logic such as that in NixOS.
271 Strictness can creep in through optional attributes, or assertions and warnings that run as part of code that shouldn't access what is checked.
272 '';
273 in {
274 kernelPatches = throw (explain "kernelPatches");
275 structuredExtraConfig = throw (explain "structuredExtraConfig");
276 modDirVersion = throw (explain "modDirVersion");
277 }))).version
278 emptyFile;
279 in [
280 (nixosTests.kernel-generic.passthru.testsForKernel overridableKernel)
281 versionDoesNotDependOnPatchesEtc
282 # Disabled by default, because the infinite recursion is hard to understand. The other test's error is better and produces a shorter trace.
283 # versionDoesNotDependOnPatchesEtcNixOS
284 ] ++ kernelTests;
285 };
286
287}));
288in overridableKernel