131 lines
4 KiB
Nix
131 lines
4 KiB
Nix
{
|
||
pkgs,
|
||
lib,
|
||
kernel-src,
|
||
structuredExtraConfig ? { },
|
||
kernelPatches ? [ ],
|
||
extraConfig ? "",
|
||
sccacheDir ? "/var/cache/sccache",
|
||
enforceSccache ? true,
|
||
}:
|
||
|
||
let
|
||
makefile = builtins.readFile "${kernel-src}/Makefile";
|
||
lines = lib.splitString "\n" makefile;
|
||
|
||
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
|
||
pkgs.callPackage (
|
||
{ buildLinux, ... }@args:
|
||
let
|
||
llvm = pkgs.llvmPackages_latest;
|
||
|
||
# buildLinux uses common-flags.nix which sets CC to the *unwrapped* compiler:
|
||
# CC=${lib.getExe stdenv.cc.cc}
|
||
# and appends extraMakeFlags at the end. :contentReference[oaicite:1]{index=1}
|
||
realClang = lib.getExe llvm.clang-unwrapped;
|
||
|
||
# Host tools are built with buildPackages.stdenv.cc (see common-flags HOSTCC). :contentReference[oaicite:2]{index=2}
|
||
buildPkgs = args.buildPackages or pkgs.buildPackages;
|
||
realHostCC = lib.getExe' buildPkgs.stdenv.cc "${buildPkgs.stdenv.cc.targetPrefix}cc";
|
||
realHostCXX = lib.getExe' buildPkgs.stdenv.cc "${buildPkgs.stdenv.cc.targetPrefix}c++";
|
||
|
||
clangSccache = pkgs.writeShellScriptBin "clang" ''
|
||
set -euo pipefail
|
||
: "''${SCCACHE_ENFORCE_MARKER:?SCCACHE_ENFORCE_MARKER is not set}"
|
||
: > "''${SCCACHE_ENFORCE_MARKER}"
|
||
export SCCACHE_DIR=${lib.escapeShellArg sccacheDir}
|
||
exec ${pkgs.sccache}/bin/sccache ${realClang} "$@"
|
||
'';
|
||
|
||
hostccSccache = pkgs.writeShellScriptBin "cc" ''
|
||
set -euo pipefail
|
||
: "''${SCCACHE_ENFORCE_MARKER:?SCCACHE_ENFORCE_MARKER is not set}"
|
||
: > "''${SCCACHE_ENFORCE_MARKER}"
|
||
export SCCACHE_DIR=${lib.escapeShellArg sccacheDir}
|
||
exec ${pkgs.sccache}/bin/sccache ${realHostCC} "$@"
|
||
'';
|
||
|
||
hostcxxSccache = pkgs.writeShellScriptBin "c++" ''
|
||
set -euo pipefail
|
||
: "''${SCCACHE_ENFORCE_MARKER:?SCCACHE_ENFORCE_MARKER is not set}"
|
||
: > "''${SCCACHE_ENFORCE_MARKER}"
|
||
export SCCACHE_DIR=${lib.escapeShellArg sccacheDir}
|
||
exec ${pkgs.sccache}/bin/sccache ${realHostCXX} "$@"
|
||
'';
|
||
|
||
structuredExtraConfig' =
|
||
(with lib.kernel; {
|
||
LTO_CLANG_THIN = yes;
|
||
# LTO_CLANG_FULL = no;
|
||
# LTO_NONE = no;
|
||
})
|
||
// structuredExtraConfig;
|
||
in
|
||
buildLinux (
|
||
args
|
||
// {
|
||
inherit kernelPatches extraConfig;
|
||
|
||
version = kver;
|
||
modDirVersion = kver;
|
||
src = kernel-src;
|
||
|
||
stdenv = llvm.stdenv;
|
||
|
||
extraMakeFlags =
|
||
(args.extraMakeFlags or [ ])
|
||
++ [
|
||
"LLVM=1"
|
||
"LLVM_IAS=1"
|
||
]
|
||
++ lib.optionals enforceSccache [
|
||
"CC=${lib.getExe clangSccache}"
|
||
"HOSTCC=${lib.getExe hostccSccache}"
|
||
"HOSTCXX=${lib.getExe hostcxxSccache}"
|
||
];
|
||
|
||
# Enforce that the wrappers were actually invoked at least once.
|
||
# sccache is a compiler wrapper; this is the contract we’re enforcing. :contentReference[oaicite:4]{index=4}
|
||
preBuild =
|
||
(args.preBuild or "")
|
||
+ lib.optionalString enforceSccache ''
|
||
export SCCACHE_ENFORCE_MARKER="$NIX_BUILD_TOP/.sccache-used"
|
||
rm -f "$SCCACHE_ENFORCE_MARKER"
|
||
${pkgs.sccache}/bin/sccache --start-server || true
|
||
${pkgs.sccache}/bin/sccache --zero-stats || true
|
||
'';
|
||
|
||
postBuild =
|
||
(args.postBuild or "")
|
||
+ lib.optionalString enforceSccache ''
|
||
if [ ! -e "$SCCACHE_ENFORCE_MARKER" ]; then
|
||
echo "FATAL: sccache enforcement failed: compiler wrappers were not invoked."
|
||
echo "This means buildLinux did not use your CC/HOSTCC overrides."
|
||
exit 1
|
||
fi
|
||
${pkgs.sccache}/bin/sccache --show-stats --stats-format text || true
|
||
'';
|
||
|
||
structuredExtraConfig = structuredExtraConfig';
|
||
|
||
ignoreConfigErrors = true;
|
||
|
||
extraMeta.branch = "${V}.${P}";
|
||
}
|
||
)
|
||
) { }
|