speed up kernel build

by having two separate derivations for patching the kernel source tree
and building it, we have to copy said source trees from one store
location to another which takes non-neglible time on spinning rust
(literally minutes on my machine). Replace with a single derivation
that can do more things on one tree in-place
This commit is contained in:
Daniel Barlow 2022-10-19 17:34:22 +01:00
parent d1dda7bf74
commit f1b7780537
7 changed files with 77 additions and 101 deletions

View file

@ -17,20 +17,31 @@ let
(if phram then ./modules/phram.nix else (args: {})) (if phram then ./modules/phram.nix else (args: {}))
] nixpkgs; ] nixpkgs;
squashfs = liminix.builders.squashfs config.filesystem.contents; squashfs = liminix.builders.squashfs config.filesystem.contents;
kernel = callPackage ./kernel {
inherit (config.kernel) config checkedConfig; openwrt = fetchFromGitHub {
name = "openwrt-source";
repo = "openwrt";
owner = "openwrt";
rev = "a5265497a4f6da158e95d6a450cb2cb6dc085cab";
hash = "sha256-YYi4gkpLjbOK7bM2MGQjAyEBuXJ9JNXoz/JEmYf8xE8=";
}; };
outputs = rec { outputs = rec {
inherit squashfs kernel; inherit squashfs;
dtb = kernel.dtb { kernel = nixpkgs.kernel.override {
dts = "qca9531_glinet_gl-ar750.dts"; inherit (config.kernel) config checkedConfig;
}; };
uimage = kernel.uimage { dtb = (callPackage ./kernel/dtb.nix {}) {
dts = "${openwrt}/target/linux/ath79/dts/qca9531_glinet_gl-ar750.dts";
includes = [
"${openwrt}/target/linux/ath79/dts"
"${kernel.headers}/include"
];
};
uimage = (callPackage ./kernel/uimage.nix {}) {
commandLine = concatStringsSep " " config.boot.commandLine; commandLine = concatStringsSep " " config.boot.commandLine;
inherit (device.boot) loadAddress entryPoint; inherit (device.boot) loadAddress entryPoint;
inherit (kernel) vmlinux; inherit kernel;
inherit dtb; inherit dtb;
}; };
combined-image = nixpkgs.runCommand "firmware.bin" { combined-image = nixpkgs.runCommand "firmware.bin" {
@ -60,9 +71,9 @@ let
mkdir $out mkdir $out
cd $out cd $out
ln -s ${squashfs} squashfs ln -s ${squashfs} squashfs
ln -s ${kernel.vmlinux} vmlinux ln -s ${kernel} vmlinux
ln -s ${manifest} manifest ln -s ${manifest} manifest
ln -s ${kernel.vmlinux.modulesupport} build ln -s ${kernel.headers} build
'' + '' +
(if device ? boot then '' (if device ? boot then ''
ln -s ${uimage} uimage ln -s ${uimage} uimage

View file

@ -32,36 +32,21 @@
overlay = final: prev: overlay = final: prev:
let let
inherit (final) fetchFromGitHub fetchgit stdenvNoCC; openwrt = final.fetchFromGitHub {
openwrt = fetchFromGitHub {
name = "openwrt-source"; name = "openwrt-source";
repo = "openwrt"; repo = "openwrt";
owner = "openwrt"; owner = "openwrt";
rev = "a5265497a4f6da158e95d6a450cb2cb6dc085cab"; rev = "a5265497a4f6da158e95d6a450cb2cb6dc085cab";
hash = "sha256-YYi4gkpLjbOK7bM2MGQjAyEBuXJ9JNXoz/JEmYf8xE8="; hash = "sha256-YYi4gkpLjbOK7bM2MGQjAyEBuXJ9JNXoz/JEmYf8xE8=";
}; };
mainline = fetchFromGitHub {
name = "kernel-source";
owner = "torvalds";
repo = "linux";
rev = "90c7e9b400c751dbd73885f494f421f90ca69721";
hash = "sha256-pq6QNa0PJVeheaZkuvAPD0rLuEeKrViKk65dz+y4kqo=";
};
in { in {
sources = { kernel = prev.kernel.override {
inherit openwrt; src = final.fetchurl {
kernel = stdenvNoCC.mkDerivation { name = "linux.tar.gz";
name = "spindled-kernel-tree"; url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.71.tar.gz";
src = mainline; hash = "sha256-yhO2cXIeIgUxkSZf/4aAsF11uxyh+UUZu6D1h92vCD8=";
phases = [ };
"unpackPhase" "patchPhase" "openWrtPatchPhase" extraPatchPhase = ''
"patchScripts" "installPhase"
];
patches = [ ../../kernel/random.patch ];
patchScripts = ''
patchShebangs scripts/
'';
openWrtPatchPhase = ''
cp -av ${openwrt}/target/linux/generic/files/* . cp -av ${openwrt}/target/linux/generic/files/* .
chmod -R u+w . chmod -R u+w .
cp -av ${openwrt}/target/linux/ath79/files/* . cp -av ${openwrt}/target/linux/ath79/files/* .
@ -74,11 +59,6 @@
patches ${openwrt}/target/linux/generic/hack-5.15/*.patch patches ${openwrt}/target/linux/generic/hack-5.15/*.patch
patches ${openwrt}/target/linux/ath79/patches-5.15/*.patch patches ${openwrt}/target/linux/ath79/patches-5.15/*.patch
''; '';
installPhase = ''
mkdir -p $out
cp -a . $out
'';
};
}; };
}; };
kernel = rec { kernel = rec {
@ -88,8 +68,6 @@
USE_OF = "y"; USE_OF = "y";
ATH79 = "y"; ATH79 = "y";
LIMINIX = "y";
SERIAL_8250_CONSOLE = "y"; SERIAL_8250_CONSOLE = "y";
SERIAL_8250 = "y"; SERIAL_8250 = "y";
SERIAL_CORE_CONSOLE = "y"; SERIAL_CORE_CONSOLE = "y";
@ -118,9 +96,10 @@
AG71XX = "y"; # ethernet (qca,qca9530-eth) AG71XX = "y"; # ethernet (qca,qca9530-eth)
MFD_SYSCON = "y"; # ethernet (compatible "syscon") MFD_SYSCON = "y"; # ethernet (compatible "syscon")
AR8216_PHY = "y"; # eth1 is behind a switch AR8216_PHY = "y"; # eth1 is behind a switch
};
config = { MTD = "y";
CPU_LITTLE_ENDIAN= "n"; MTD_CMDLINE_PARTS = "y";
MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_devs
CPU_BIG_ENDIAN= "y"; CPU_BIG_ENDIAN= "y";
# this is all copied from nixwrt ath79 config. Clearly not all # this is all copied from nixwrt ath79 config. Clearly not all
@ -128,7 +107,6 @@
# installation method config or ... # installation method config or ...
"CMDLINE_PARTITION" = "y"; "CMDLINE_PARTITION" = "y";
"DEBUG_INFO" = "y";
"EARLY_PRINTK" = "y"; "EARLY_PRINTK" = "y";
"FW_LOADER" = "y"; "FW_LOADER" = "y";
# we don't have a user helper, so we get multiple 60s pauses # we don't have a user helper, so we get multiple 60s pauses
@ -136,7 +114,7 @@
"FW_LOADER_USER_HELPER" = "n"; "FW_LOADER_USER_HELPER" = "n";
"MODULE_SIG" = "y"; "MODULE_SIG" = "y";
"MTD_CMDLINE_PARTS" = "y";
"PARTITION_ADVANCED" = "y"; "PARTITION_ADVANCED" = "y";
"PRINTK_TIME" = "y"; "PRINTK_TIME" = "y";
"SQUASHFS" = "y"; "SQUASHFS" = "y";

View file

@ -16,30 +16,14 @@
overlay = final: prev: overlay = final: prev:
let inherit (final) stdenvNoCC fetchFromGitHub; let inherit (final) stdenvNoCC fetchFromGitHub;
in { in {
sources = { kernel = prev.kernel.override {
kernel = # using fetchurl not fetchzip because it doesn't unpack, and
let src = fetchFromGitHub { # copying 6GB of data from one store location to another
name = "kernel-source"; # takes an absolute bloody age
owner = "torvalds"; src = final.fetchurl {
repo = "linux"; name = "linux.tar.gz";
rev = "3d7cb6b04c3f3115719235cc6866b10326de34cd"; # v5.19 url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.19.16.tar.gz";
hash = "sha256-OVsIRScAnrPleW1vbczRAj5L/SGGht2+GnvZJClMUu4="; hash = "sha256-m4NeoEsCEK0HSIKTZ6zYTgk1fD3W0PSOMXN6fyHpkP8=";
};
in stdenvNoCC.mkDerivation {
name = "spindled-kernel-tree";
inherit src;
phases = [
"unpackPhase"
"patchScripts" "installPhase"
];
patchScripts = ''
patchShebangs scripts/
'';
installPhase = ''
mkdir -p $out
cp -a . $out
'';
}; };
}; };
}; };

View file

@ -1,15 +1,10 @@
{ {
stdenv stdenv
, openwrt
, dtc , dtc
, kernel
}: }:
{ dts { dts
, includes
}:let }:let
includes = [
"${openwrt}/target/linux/ath79/dts"
"${kernel}/include"
];
cppDtSearchFlags = builtins.concatStringsSep " " (map (f: "-I${f}") includes); cppDtSearchFlags = builtins.concatStringsSep " " (map (f: "-I${f}") includes);
dtcSearchFlags = builtins.concatStringsSep " " (map (f: "-i${f}") includes); dtcSearchFlags = builtins.concatStringsSep " " (map (f: "-i${f}") includes);
in stdenv.mkDerivation { in stdenv.mkDerivation {
@ -17,7 +12,7 @@ in stdenv.mkDerivation {
phases = [ "buildPhase" ]; phases = [ "buildPhase" ];
nativeBuildInputs = [ dtc ]; nativeBuildInputs = [ dtc ];
buildPhase = '' buildPhase = ''
${stdenv.cc.targetPrefix}cpp -nostdinc -x assembler-with-cpp ${cppDtSearchFlags} -undef -D__DTS__ -o dtb.tmp ${openwrt}/target/linux/ath79/dts/${dts} ${stdenv.cc.targetPrefix}cpp -nostdinc -x assembler-with-cpp ${cppDtSearchFlags} -undef -D__DTS__ -o dtb.tmp ${dts}
dtc ${dtcSearchFlags} -I dts -O dtb -o $out dtb.tmp dtc ${dtcSearchFlags} -I dts -O dtb -o $out dtb.tmp
test -e $out test -e $out
''; '';

View file

@ -7,7 +7,7 @@
let let
objcopy = "${stdenv.cc.bintools.targetPrefix}objcopy"; objcopy = "${stdenv.cc.bintools.targetPrefix}objcopy";
in { in {
vmlinux kernel
, commandLine , commandLine
, entryPoint , entryPoint
, extraName ? "" # e.g. socFamily , extraName ? "" # e.g. socFamily
@ -28,7 +28,7 @@ stdenv.mkDerivation {
ubootTools ubootTools
]; ];
preparePhase = '' preparePhase = ''
cp ${vmlinux} vmlinux.elf; chmod +w vmlinux.elf cp ${kernel} vmlinux.elf; chmod +w vmlinux.elf
''; '';
dtbPhase = '' dtbPhase = ''
dtc -I dtb -O dts -o tmp.dts ${dtb} dtc -I dtb -O dts -o tmp.dts ${dtb}

View file

@ -12,6 +12,7 @@ final: prev: {
s6-init-bin = final.callPackage ./pkgs/s6-init-bin {}; s6-init-bin = final.callPackage ./pkgs/s6-init-bin {};
s6-rc-database = final.callPackage ./pkgs/s6-rc-database {}; s6-rc-database = final.callPackage ./pkgs/s6-rc-database {};
kernel = final.callPackage ./pkgs/kernel {};
dnsmasq = dnsmasq =
let d = prev.dnsmasq.overrideAttrs(o: { let d = prev.dnsmasq.overrideAttrs(o: {

View file

@ -6,7 +6,8 @@
, config , config
, checkedConfig ? {} , checkedConfig ? {}
, tree , src
, extraPatchPhase ? "true"
} : } :
let writeConfig = name : config: writeText name let writeConfig = name : config: writeText name
(builtins.concatStringsSep (builtins.concatStringsSep
@ -30,8 +31,8 @@ let writeConfig = name : config: writeText name
checkedConfigFile = writeConfig "checked_kconfig" checkedConfig ; checkedConfigFile = writeConfig "checked_kconfig" checkedConfig ;
inherit lib; in inherit lib; in
stdenv.mkDerivation rec { stdenv.mkDerivation rec {
name = "vmlinux"; name = "kernel";
inherit src extraPatchPhase;
hardeningDisable = ["all"]; hardeningDisable = ["all"];
nativeBuildInputs = [buildPackages.stdenv.cc] ++ nativeBuildInputs = [buildPackages.stdenv.cc] ++
(with buildPackages.pkgs; (with buildPackages.pkgs;
@ -44,11 +45,16 @@ stdenv.mkDerivation rec {
PKG_CONFIG_PATH = "./pkgconfig"; PKG_CONFIG_PATH = "./pkgconfig";
CROSS_COMPILE = stdenv.cc.bintools.targetPrefix; CROSS_COMPILE = stdenv.cc.bintools.targetPrefix;
ARCH = "mips"; # kernel uses "mips" here for both mips and mipsel ARCH = "mips"; # kernel uses "mips" here for both mips and mipsel
KBUILD_BUILD_HOST = "liminix.builder";
dontStrip = true; dontStrip = true;
dontPatchELF = true; dontPatchELF = true;
outputs = ["out" "modulesupport"]; outputs = ["out" "headers"];
phases = [ phases = [
"unpackPhase"
"butcherPkgconfig" "butcherPkgconfig"
"extraPatchPhase"
"patchScripts"
"configurePhase" "configurePhase"
"checkConfigurationPhase" "checkConfigurationPhase"
"buildPhase" "buildPhase"
@ -67,12 +73,16 @@ stdenv.mkDerivation rec {
for i in pkgconfig/*.pc; do test -f $i && sed -i 's/^Libs:/Libs: -L''${libdir} /' $i;done for i in pkgconfig/*.pc; do test -f $i && sed -i 's/^Libs:/Libs: -L''${libdir} /' $i;done
''; '';
patchScripts = ''
patchShebangs scripts/
'';
configurePhase = '' configurePhase = ''
export KBUILD_OUTPUT=`pwd` export KBUILD_OUTPUT=`pwd`
cp ${kconfigFile} .config cp ${kconfigFile} .config
cp ${kconfigFile} .config.orig cp ${kconfigFile} .config.orig
cp ${kconfigLocal} Kconfig.local cp ${kconfigLocal} Kconfig.local
( cd ${tree} && make V=1 olddefconfig ) make V=1 olddefconfig
''; '';
checkConfigurationPhase = '' checkConfigurationPhase = ''
@ -84,18 +94,15 @@ stdenv.mkDerivation rec {
echo "OK" echo "OK"
''; '';
KBUILD_BUILD_HOST = "liminix.builder";
buildPhase = '' buildPhase = ''
make -C ${tree} vmlinux modules_prepare make vmlinux modules_prepare
''; '';
installPhase = '' installPhase = ''
${CROSS_COMPILE}strip -d vmlinux ${CROSS_COMPILE}strip -d vmlinux
cp vmlinux $out cp vmlinux $out
mkdir -p $modulesupport mkdir -p $headers
cp .config $modulesupport/config cp -a include .config $headers/
make clean
cp -a . $modulesupport
''; '';
} }