at master 14 kB view raw
1{ 2 buildPackages, 3 pkgsBuildBuild, 4 callPackage, 5 perl, 6 bison ? null, 7 flex ? null, 8 gmp ? null, 9 libmpc ? null, 10 mpfr ? null, 11 pahole, 12 lib, 13 stdenv, 14 rustc-unwrapped, 15 rustPlatform, 16 rust-bindgen-unwrapped, 17 # testing 18 emptyFile, 19 nixos, 20 nixosTests, 21}@args': 22 23let 24 overridableKernel = lib.makeOverridable ( 25 # The kernel source tarball. 26 { 27 src, 28 29 # The kernel version. 30 version, 31 32 # Allows overriding the default defconfig 33 defconfig ? null, 34 35 # Legacy overrides to the intermediate kernel config, as string 36 extraConfig ? "", 37 38 # Additional make flags passed to kbuild 39 extraMakeFlags ? [ ], 40 41 # enables the options in ./common-config.nix and lib/systems/platform.nix; 42 # if `false` then only `structuredExtraConfig` is used 43 enableCommonConfig ? true 44 45 , # kernel intermediate config overrides, as a set 46 structuredExtraConfig ? { }, 47 48 # The version number used for the module directory 49 # If unspecified, this is determined automatically from the version. 50 modDirVersion ? null, 51 52 # An attribute set whose attributes express the availability of 53 # certain features in this kernel. E.g. `{ia32Emulation = true;}' 54 # indicates a kernel that provides Intel wireless support. Used in 55 # NixOS to implement kernel-specific behaviour. 56 features ? { }, 57 58 # Custom seed used for CONFIG_GCC_PLUGIN_RANDSTRUCT if enabled. This is 59 # automatically extended with extra per-version and per-config values. 60 randstructSeed ? "", 61 62 # A list of patches to apply to the kernel. Each element of this list 63 # should be an attribute set {name, patch} where `name' is a 64 # symbolic name and `patch' is the actual patch. The patch may 65 # optionally be compressed with gzip or bzip2. 66 kernelPatches ? [ ], 67 ignoreConfigErrors ? 68 !lib.elem stdenv.hostPlatform.linux-kernel.name [ 69 "aarch64-multiplatform" 70 "pc" 71 ], 72 extraMeta ? { }, 73 extraPassthru ? { }, 74 75 isLTS ? false, 76 isZen ? false, 77 isLibre ? false, 78 isHardened ? false, 79 80 # easy overrides to stdenv.hostPlatform.linux-kernel members 81 autoModules ? stdenv.hostPlatform.linux-kernel.autoModules, 82 preferBuiltin ? stdenv.hostPlatform.linux-kernel.preferBuiltin or false, 83 kernelArch ? stdenv.hostPlatform.linuxArch, 84 kernelTests ? { }, 85 86 stdenv ? args'.stdenv, 87 buildPackages ? args'.buildPackages, 88 pkgsBuildBuild ? args'.pkgsBuildBuild, 89 90 ... 91 }@args: 92 93 # Note: this package is used for bootstrapping fetchurl, and thus 94 # cannot use fetchpatch! All mutable patches (generated by GitHub or 95 # cgit) that are needed here should be included directly in Nixpkgs as 96 # files. 97 98 let 99 # Dirty hack to make sure that `version` & `src` have 100 # `<nixpkgs/pkgs/os-specific/linux/kernel/linux-x.y.nix>` as position 101 # when using `builtins.unsafeGetAttrPos`. 102 # 103 # This is to make sure that ofborg actually detects changes in the kernel derivation 104 # and pings all maintainers. 105 # 106 # For further context, see https://github.com/NixOS/nixpkgs/pull/143113#issuecomment-953319957 107 basicArgs = builtins.removeAttrs args ( 108 lib.filter ( 109 x: 110 !(builtins.elem x [ 111 "version" 112 "pname" 113 "src" 114 ]) 115 ) (lib.attrNames args) 116 ); 117 118 # Combine the `features' attribute sets of all the kernel patches. 119 kernelFeatures = lib.foldr (x: y: (x.features or { }) // y) ( 120 { 121 efiBootStub = true; 122 netfilterRPFilter = true; 123 ia32Emulation = true; 124 } 125 // features 126 ) kernelPatches; 127 128 commonStructuredConfig = import ./common-config.nix { 129 inherit lib stdenv version; 130 rustAvailable = lib.meta.availableOn stdenv.hostPlatform rustc-unwrapped; 131 132 features = kernelFeatures; # Ensure we know of all extra patches, etc. 133 }; 134 135 intermediateNixConfig = 136 configfile.moduleStructuredConfig.intermediateNixConfig 137 # extra config in legacy string format 138 + extraConfig 139 # need the 'or ""' at the end in case enableCommonConfig = true and extraConfig is not present 140 + lib.optionalString enableCommonConfig stdenv.hostPlatform.linux-kernel.extraConfig or ""; 141 142 structuredConfigFromPatches = map ( 143 { 144 structuredExtraConfig ? { }, 145 ... 146 }@args: 147 if args ? extraStructuredConfig then 148 throw '' 149 Passing `extraStructuredConfig` to the Linux kernel (e.g. 150 via `boot.kernelPatches` in NixOS) is not supported anymore. Use 151 `structuredExtraConfig` instead. 152 '' 153 else 154 { 155 settings = structuredExtraConfig; 156 } 157 ) kernelPatches; 158 159 # appends kernel patches extraConfig 160 kernelConfigFun = 161 baseConfigStr: 162 let 163 configFromPatches = map ( 164 { 165 extraConfig ? "", 166 ... 167 }: 168 extraConfig 169 ) kernelPatches; 170 in 171 lib.concatStringsSep "\n" ([ baseConfigStr ] ++ configFromPatches); 172 173 withRust = ((configfile.moduleStructuredConfig.settings.RUST or { }).tristate or null) == "y"; 174 175 configfile = stdenv.mkDerivation { 176 inherit 177 ignoreConfigErrors 178 autoModules 179 preferBuiltin 180 kernelArch 181 extraMakeFlags 182 ; 183 pname = "linux-config"; 184 inherit version; 185 186 generateConfig = ./generate-config.pl; 187 188 kernelConfig = kernelConfigFun intermediateNixConfig; 189 passAsFile = [ "kernelConfig" ]; 190 191 depsBuildBuild = [ buildPackages.stdenv.cc ]; 192 nativeBuildInputs = [ 193 perl 194 gmp 195 libmpc 196 mpfr 197 bison 198 flex 199 ] 200 ++ lib.optional (lib.versionAtLeast version "5.2") pahole 201 ++ lib.optionals withRust [ 202 rust-bindgen-unwrapped 203 rustc-unwrapped 204 ]; 205 206 RUST_LIB_SRC = lib.optionalString withRust rustPlatform.rustLibSrc; 207 208 platformName = stdenv.hostPlatform.linux-kernel.name; 209 # e.g. "defconfig" 210 kernelBaseConfig = 211 if defconfig != null then defconfig else stdenv.hostPlatform.linux-kernel.baseConfig; 212 213 makeFlags = import ./common-flags.nix { 214 inherit 215 lib 216 stdenv 217 buildPackages 218 extraMakeFlags 219 ; 220 }; 221 222 postPatch = kernel.postPatch + '' 223 # Patch kconfig to print "###" after every question so that 224 # generate-config.pl from the generic builder can answer them. 225 sed -e '/fflush(stdout);/i\printf("###");' -i scripts/kconfig/conf.c 226 ''; 227 228 preUnpack = kernel.preUnpack or ""; 229 230 inherit (kernel) src patches; 231 232 buildPhase = '' 233 export buildRoot="''${buildRoot:-build}" 234 235 # Get a basic config file for later refinement with $generateConfig. 236 make $makeFlags \ 237 -C . O="$buildRoot" $kernelBaseConfig \ 238 ARCH=$kernelArch CROSS_COMPILE=${stdenv.cc.targetPrefix} \ 239 $makeFlags 240 241 # Create the config file. 242 echo "generating kernel configuration..." 243 ln -s "$kernelConfigPath" "$buildRoot/kernel-config" 244 DEBUG=1 ARCH=$kernelArch CROSS_COMPILE=${stdenv.cc.targetPrefix} \ 245 KERNEL_CONFIG="$buildRoot/kernel-config" AUTO_MODULES=$autoModules \ 246 PREFER_BUILTIN=$preferBuiltin BUILD_ROOT="$buildRoot" SRC=. MAKE_FLAGS="$makeFlags" \ 247 perl -w $generateConfig 248 '' 249 + lib.optionalString stdenv.cc.isClang '' 250 if ! grep -Fq CONFIG_CC_IS_CLANG=y $buildRoot/.config; then 251 echo "Kernel config didn't recognize the clang compiler?" 252 exit 1 253 fi 254 '' 255 + lib.optionalString stdenv.cc.bintools.isLLVM '' 256 if ! grep -Fq CONFIG_LD_IS_LLD=y $buildRoot/.config; then 257 echo "Kernel config didn't recognize the LLVM linker?" 258 exit 1 259 fi 260 '' 261 + lib.optionalString withRust '' 262 if ! grep -Fq CONFIG_RUST_IS_AVAILABLE=y $buildRoot/.config; then 263 echo "Kernel config didn't find Rust toolchain?" 264 exit 1 265 fi 266 ''; 267 268 installPhase = "mv $buildRoot/.config $out"; 269 270 enableParallelBuilding = true; 271 272 passthru = rec { 273 module = import ../../../../nixos/modules/system/boot/kernel_config.nix; 274 # used also in apache 275 # { modules = [ { options = res.options; config = svc.config or svc; } ]; 276 # check = false; 277 # The result is a set of two attributes 278 moduleStructuredConfig = 279 (lib.evalModules { 280 modules = [ 281 module 282 ] 283 ++ lib.optionals enableCommonConfig [ 284 { 285 settings = commonStructuredConfig; 286 _file = "pkgs/os-specific/linux/kernel/common-config.nix"; 287 } 288 ] 289 ++ [ 290 { 291 settings = structuredExtraConfig; 292 _file = "structuredExtraConfig"; 293 } 294 ] 295 ++ structuredConfigFromPatches; 296 }).config; 297 298 structuredConfig = moduleStructuredConfig.settings; 299 }; 300 }; # end of configfile derivation 301 302 kernel = (callPackage ./manual-config.nix { inherit lib stdenv buildPackages; }) ( 303 basicArgs 304 // { 305 inherit 306 kernelPatches 307 randstructSeed 308 extraMakeFlags 309 extraMeta 310 configfile 311 modDirVersion 312 ; 313 pos = builtins.unsafeGetAttrPos "version" args; 314 315 config = { 316 CONFIG_MODULES = "y"; 317 CONFIG_FW_LOADER = "y"; 318 CONFIG_RUST = if withRust then "y" else "n"; 319 }; 320 } 321 ); 322 323 in 324 kernel.overrideAttrs ( 325 finalAttrs: previousAttrs: { 326 327 passthru = 328 previousAttrs.passthru or { } 329 // extraPassthru 330 // basicArgs 331 // { 332 features = kernelFeatures; 333 inherit 334 commonStructuredConfig 335 structuredExtraConfig 336 extraMakeFlags 337 isLTS 338 isZen 339 isHardened 340 isLibre 341 ; 342 isXen = lib.warn "The isXen attribute is deprecated. All Nixpkgs kernels that support it now have Xen enabled." true; 343 344 # Adds dependencies needed to edit the config: 345 # nix-shell '<nixpkgs>' -A linux.configEnv --command 'make nconfig' 346 configEnv = finalAttrs.finalPackage.overrideAttrs (previousAttrs: { 347 depsBuildBuild = 348 previousAttrs.depsBuildBuild or [ ] 349 ++ (with pkgsBuildBuild; [ 350 pkg-config 351 ncurses 352 ]); 353 }); 354 355 tests = 356 let 357 overridableKernel = finalAttrs.finalPackage // { 358 override = 359 args: 360 lib.warn ( 361 "override is stubbed for NixOS kernel tests, not applying changes these arguments: " 362 + toString (lib.attrNames (lib.toFunction args { })) 363 ) overridableKernel; 364 }; 365 /* 366 Certain arguments must be evaluated lazily; so that only the output(s) depend on them. 367 Original reproducer / simplified use case: 368 */ 369 versionDoesNotDependOnPatchesEtcNixOS = 370 builtins.seq 371 (nixos ( 372 { config, pkgs, ... }: 373 { 374 boot.kernelPatches = [ 375 (builtins.seq config.boot.kernelPackages.kernel.version { patch = pkgs.emptyFile; }) 376 ]; 377 } 378 )).config.boot.kernelPackages.kernel.outPath 379 emptyFile; 380 versionDoesNotDependOnPatchesEtc = 381 builtins.seq 382 (import ./generic.nix args' ( 383 args 384 // ( 385 let 386 explain = attrName: '' 387 The ${attrName} attribute must be able to access the kernel.version attribute without an infinite recursion. 388 That means that the kernel attrset (attrNames) and the kernel.version attribute must not depend on the ${attrName} argument. 389 The fact that this exception is raised shows that such a dependency does exist. 390 This is a problem for the configurability of ${attrName} in version-aware logic such as that in NixOS. 391 Strictness can creep in through optional attributes, or assertions and warnings that run as part of code that shouldn't access what is checked. 392 ''; 393 in 394 { 395 kernelPatches = throw (explain "kernelPatches"); 396 structuredExtraConfig = throw (explain "structuredExtraConfig"); 397 modDirVersion = throw (explain "modDirVersion"); 398 } 399 ) 400 )).version 401 emptyFile; 402 in 403 { 404 inherit versionDoesNotDependOnPatchesEtc; 405 testsForKernel = nixosTests.kernel-generic.passthru.testsForKernel overridableKernel; 406 # Disabled by default, because the infinite recursion is hard to understand. The other test's error is better and produces a shorter trace. 407 # inherit versionDoesNotDependOnPatchesEtcNixOS; 408 } 409 // kernelTests; 410 }; 411 412 } 413 ) 414 ); 415in 416overridableKernel