nixos-conf/custom/modules/kernel.nix

197 lines
6.2 KiB
Nix

{
pkgs,
lib,
kernel-src,
buildLinux,
structuredExtraConfig ? { },
kernelPatches ? [ ],
extraConfig ? "",
sccacheDir ? "/var/cache/sccache/nix-builds/kernel",
sccacheServerUds ? null,
enforceSccache ? true,
features ? { },
randstructSeed ? null,
...
}:
let
makefile = builtins.readFile "${kernel-src}/Makefile";
lines = lib.splitString "\n" makefile;
normalizeKernelPatch = p: p // { patch = p.patch or null; };
kernelPatches' = map normalizeKernelPatch kernelPatches;
get =
name:
let
line = lib.findFirst (
l: lib.hasPrefix "${name} =" (lib.strings.trim l)
) (throw "Makefile missing ${name}") lines;
in
lib.strings.trim (lib.removePrefix "${name} =" (lib.strings.trim line));
V = get "VERSION";
P = get "PATCHLEVEL";
S = get "SUBLEVEL";
E = get "EXTRAVERSION";
kver = "${V}.${P}.${S}${E}";
in
let
args = {
inherit
buildLinux
features
randstructSeed
;
};
llvm = pkgs.llvmPackages_latest;
rust = pkgs.rustc-unwrapped;
buildPkgs = args.buildPackages or pkgs.buildPackages;
buildLlvm = buildPkgs.llvmPackages_latest;
llvmBuildPackages = buildPkgs // {
stdenv = buildLlvm.stdenv;
};
realClang = lib.getExe llvm.clang-unwrapped;
realLd = lib.getExe' llvm.lld "ld.lld";
realAr = lib.getExe' llvm.llvm "llvm-ar";
realNm = lib.getExe' llvm.llvm "llvm-nm";
realStrip = lib.getExe' llvm.llvm "llvm-strip";
realObjcopy = lib.getExe' llvm.llvm "llvm-objcopy";
realObjdump = lib.getExe' llvm.llvm "llvm-objdump";
realReadelf = lib.getExe' llvm.llvm "llvm-readelf";
realHostCC = lib.getExe' buildLlvm.stdenv.cc "${buildLlvm.stdenv.cc.targetPrefix}cc";
realHostCXX = lib.getExe' buildLlvm.stdenv.cc "${buildLlvm.stdenv.cc.targetPrefix}c++";
realHostAr = lib.getExe' buildLlvm.llvm "llvm-ar";
realHostLd = lib.getExe' buildLlvm.lld "ld.lld";
realRustc = lib.getExe' rust "rustc";
realHostRustc = realRustc;
sccacheConfig = pkgs.writeText "kernel-sccache.conf" ''
[cache.disk]
dir = "${sccacheDir}"
size = "100G"
'';
sccacheSetup = lib.optionalString enforceSccache ''
mkdir -p ${lib.escapeShellArg sccacheDir} 2>/dev/null || true
export SCCACHE_CONF=${lib.escapeShellArg sccacheConfig}
${lib.optionalString (sccacheServerUds != null) "export SCCACHE_SERVER_UDS=${lib.escapeShellArg sccacheServerUds}"}
'';
mkSccacheWrapper =
name: compiler:
pkgs.writeShellScriptBin name ''
set -euo pipefail
mkdir -p ${lib.escapeShellArg sccacheDir} 2>/dev/null || true
export SCCACHE_CONF=${lib.escapeShellArg sccacheConfig}
${lib.optionalString (sccacheServerUds != null) "export SCCACHE_SERVER_UDS=${lib.escapeShellArg sccacheServerUds}"}
if [ -n "''${SCCACHE_ENFORCE_MARKER-}" ]; then
: > "''${SCCACHE_ENFORCE_MARKER}"
fi
exec ${pkgs.sccache}/bin/sccache ${compiler} "$@"
'';
clangSccache = mkSccacheWrapper "clang" realClang;
hostccSccache = mkSccacheWrapper "cc" realHostCC;
hostcxxSccache = mkSccacheWrapper "c++" realHostCXX;
rustcSccache = pkgs.writeShellScriptBin "rustc" ''
set -euo pipefail
mkdir -p ${lib.escapeShellArg sccacheDir} 2>/dev/null || true
export SCCACHE_CONF=${lib.escapeShellArg sccacheConfig}
${lib.optionalString (sccacheServerUds != null) "export SCCACHE_SERVER_UDS=${lib.escapeShellArg sccacheServerUds}"}
if [ -n "''${SCCACHE_ENFORCE_MARKER-}" ]; then
: > "''${SCCACHE_ENFORCE_MARKER}"
fi
exec ${pkgs.sccache}/bin/sccache ${realRustc} "$@"
'';
hostrustcSccache = pkgs.writeShellScriptBin "rustc" ''
set -euo pipefail
mkdir -p ${lib.escapeShellArg sccacheDir} 2>/dev/null || true
export SCCACHE_CONF=${lib.escapeShellArg sccacheConfig}
${lib.optionalString (sccacheServerUds != null) "export SCCACHE_SERVER_UDS=${lib.escapeShellArg sccacheServerUds}"}
if [ -n "''${SCCACHE_ENFORCE_MARKER-}" ]; then
: > "''${SCCACHE_ENFORCE_MARKER}"
fi
exec ${pkgs.sccache}/bin/sccache ${realHostRustc} "$@"
'';
structuredExtraConfig' =
(with lib.kernel; {
LTO_CLANG_THIN = yes;
# LTO_CLANG_FULL = no;
# LTO_NONE = no;
})
// structuredExtraConfig;
in
buildLinux (
args
// {
kernelPatches = kernelPatches';
inherit extraConfig;
version = kver;
modDirVersion = kver;
src = kernel-src;
stdenv = llvm.stdenv;
buildPackages = llvmBuildPackages;
extraMakeFlags =
(args.extraMakeFlags or [ ])
++ [
"LLVM=1"
"LLVM_IAS=1"
"CC=${if enforceSccache then lib.getExe clangSccache else realClang}"
"LD=${realLd}"
"AR=${realAr}"
"NM=${realNm}"
"STRIP=${realStrip}"
"OBJCOPY=${realObjcopy}"
"OBJDUMP=${realObjdump}"
"READELF=${realReadelf}"
"HOSTCC=${if enforceSccache then lib.getExe hostccSccache else realHostCC}"
"HOSTCXX=${if enforceSccache then lib.getExe hostcxxSccache else realHostCXX}"
"HOSTAR=${realHostAr}"
"HOSTLD=${realHostLd}"
"RUSTC=${if enforceSccache then lib.getExe rustcSccache else realRustc}"
"HOSTRUSTC=${if enforceSccache then lib.getExe hostrustcSccache else realHostRustc}"
]
;
preConfigure = (args.preConfigure or "") + sccacheSetup;
preBuild = (args.preBuild or "") + sccacheSetup;
buildPhase =
if enforceSccache then
''
runHook preBuild
export SCCACHE_ENFORCE_MARKER="$NIX_BUILD_TOP/.sccache-used"
rm -f "$SCCACHE_ENFORCE_MARKER"
make "''${makeFlags[@]}" "''${buildFlags[@]}"
if [ ! -e "$SCCACHE_ENFORCE_MARKER" ]; then
echo "FATAL: sccache enforcement failed during buildPhase: compiler wrappers were not invoked."
echo "This means the build stage did not use your CC/HOSTCC/HOSTCXX/RUSTC/HOSTRUSTC overrides."
exit 1
fi
${pkgs.sccache}/bin/sccache --show-stats --stats-format text || true
runHook postBuild
''
else
(args.buildPhase or ''
runHook preBuild
make "''${makeFlags[@]}" "''${buildFlags[@]}"
runHook postBuild
'');
postBuild = args.postBuild or "";
structuredExtraConfig = structuredExtraConfig';
ignoreConfigErrors = true;
extraMeta.branch = "${V}.${P}";
}
)