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" "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 ]
144 ++ lib.optionals (lib.versionAtLeast version "4.16") [ bison flex ]
145 ++ lib.optional (lib.versionAtLeast version "5.2") pahole
146 ++ lib.optionals withRust [ rust-bindgen rustc ]
147 ;
148
149 RUST_LIB_SRC = lib.optionalString withRust rustPlatform.rustLibSrc;
150
151 platformName = stdenv.hostPlatform.linux-kernel.name;
152 # e.g. "defconfig"
153 kernelBaseConfig = if defconfig != null then defconfig else stdenv.hostPlatform.linux-kernel.baseConfig;
154
155 makeFlags = lib.optionals (stdenv.hostPlatform.linux-kernel ? makeFlags) stdenv.hostPlatform.linux-kernel.makeFlags
156 ++ extraMakeFlags;
157
158 postPatch = kernel.postPatch + ''
159 # Patch kconfig to print "###" after every question so that
160 # generate-config.pl from the generic builder can answer them.
161 sed -e '/fflush(stdout);/i\printf("###");' -i scripts/kconfig/conf.c
162 '';
163
164 preUnpack = kernel.preUnpack or "";
165
166 inherit (kernel) src patches;
167
168 buildPhase = ''
169 export buildRoot="''${buildRoot:-build}"
170 export HOSTCC=$CC_FOR_BUILD
171 export HOSTCXX=$CXX_FOR_BUILD
172 export HOSTAR=$AR_FOR_BUILD
173 export HOSTLD=$LD_FOR_BUILD
174
175 # Get a basic config file for later refinement with $generateConfig.
176 make $makeFlags \
177 -C . O="$buildRoot" $kernelBaseConfig \
178 ARCH=$kernelArch \
179 HOSTCC=$HOSTCC HOSTCXX=$HOSTCXX HOSTAR=$HOSTAR HOSTLD=$HOSTLD \
180 CC=$CC OBJCOPY=$OBJCOPY OBJDUMP=$OBJDUMP READELF=$READELF \
181 $makeFlags
182
183 # Create the config file.
184 echo "generating kernel configuration..."
185 ln -s "$kernelConfigPath" "$buildRoot/kernel-config"
186 DEBUG=1 ARCH=$kernelArch KERNEL_CONFIG="$buildRoot/kernel-config" AUTO_MODULES=$autoModules \
187 PREFER_BUILTIN=$preferBuiltin BUILD_ROOT="$buildRoot" SRC=. MAKE_FLAGS="$makeFlags" \
188 perl -w $generateConfig
189 '';
190
191 installPhase = "mv $buildRoot/.config $out";
192
193 enableParallelBuilding = true;
194
195 passthru = rec {
196 module = import ../../../../nixos/modules/system/boot/kernel_config.nix;
197 # used also in apache
198 # { modules = [ { options = res.options; config = svc.config or svc; } ];
199 # check = false;
200 # The result is a set of two attributes
201 moduleStructuredConfig = (lib.evalModules {
202 modules = [
203 module
204 ] ++ lib.optionals enableCommonConfig [
205 { settings = commonStructuredConfig; _file = "pkgs/os-specific/linux/kernel/common-config.nix"; }
206 ] ++ [
207 { settings = structuredExtraConfig; _file = "structuredExtraConfig"; }
208 ]
209 ++ structuredConfigFromPatches
210 ;
211 }).config;
212
213 structuredConfig = moduleStructuredConfig.settings;
214 };
215 }; # end of configfile derivation
216
217 kernel = (callPackage ./manual-config.nix { inherit lib stdenv buildPackages; }) (basicArgs // {
218 inherit kernelPatches randstructSeed extraMakeFlags extraMeta configfile modDirVersion;
219 pos = builtins.unsafeGetAttrPos "version" args;
220
221 config = {
222 CONFIG_MODULES = "y";
223 CONFIG_FW_LOADER = "m";
224 CONFIG_RUST = if withRust then "y" else "n";
225 };
226 });
227
228in
229kernel.overrideAttrs (finalAttrs: previousAttrs: {
230
231 passthru = previousAttrs.passthru or { } // basicArgs // {
232 features = kernelFeatures;
233 inherit commonStructuredConfig structuredExtraConfig extraMakeFlags isZen isHardened isLibre;
234 isXen = lib.warn "The isXen attribute is deprecated. All Nixpkgs kernels that support it now have Xen enabled." true;
235
236 # Adds dependencies needed to edit the config:
237 # nix-shell '<nixpkgs>' -A linux.configEnv --command 'make nconfig'
238 configEnv = kernel.overrideAttrs (old: {
239 nativeBuildInputs = old.nativeBuildInputs or [] ++ (with buildPackages; [
240 pkg-config ncurses
241 ]);
242 });
243
244 tests = let
245 overridableKernel = finalAttrs.finalPackage // {
246 override = args:
247 lib.warn (
248 "override is stubbed for NixOS kernel tests, not applying changes these arguments: "
249 + toString (lib.attrNames (lib.toFunction args { }))
250 ) overridableKernel;
251 };
252 /* Certain arguments must be evaluated lazily; so that only the output(s) depend on them.
253 Original reproducer / simplified use case:
254 */
255 versionDoesNotDependOnPatchesEtcNixOS =
256 builtins.seq
257 (nixos ({ config, pkgs, ... }: {
258 boot.kernelPatches = [
259 (builtins.seq config.boot.kernelPackages.kernel.version { patch = pkgs.emptyFile; })
260 ];
261 })).config.boot.kernelPackages.kernel.outPath
262 emptyFile;
263 versionDoesNotDependOnPatchesEtc =
264 builtins.seq
265 (import ./generic.nix args' (args // (
266 let explain = attrName:
267 ''
268 The ${attrName} attribute must be able to access the kernel.version attribute without an infinite recursion.
269 That means that the kernel attrset (attrNames) and the kernel.version attribute must not depend on the ${attrName} argument.
270 The fact that this exception is raised shows that such a dependency does exist.
271 This is a problem for the configurability of ${attrName} in version-aware logic such as that in NixOS.
272 Strictness can creep in through optional attributes, or assertions and warnings that run as part of code that shouldn't access what is checked.
273 '';
274 in {
275 kernelPatches = throw (explain "kernelPatches");
276 structuredExtraConfig = throw (explain "structuredExtraConfig");
277 modDirVersion = throw (explain "modDirVersion");
278 }))).version
279 emptyFile;
280 in [
281 (nixosTests.kernel-generic.passthru.testsForKernel overridableKernel)
282 versionDoesNotDependOnPatchesEtc
283 # Disabled by default, because the infinite recursion is hard to understand. The other test's error is better and produces a shorter trace.
284 # versionDoesNotDependOnPatchesEtcNixOS
285 ] ++ kernelTests;
286 };
287
288}));
289in overridableKernel