liminix

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit f1b77805373c31c2db5a4faa1052136a5e3de94a
parent d1dda7bf74446d4fc62a2cd81c66fbd18542e423
Author: Daniel Barlow <dan@telent.net>
Date:   Wed, 19 Oct 2022 17:34:22 +0100

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

Diffstat:
Mdefault.nix | 31+++++++++++++++++++++----------
Mdevices/gl-ar750/default.nix | 70++++++++++++++++++++++++----------------------------------------------
Mdevices/qemu/default.nix | 34+++++++++-------------------------
Mkernel/dtb.nix | 9++-------
Mkernel/uimage.nix | 4++--
Dkernel/vmlinux.nix | 101-------------------------------------------------------------------------------
Moverlay.nix | 1+
Apkgs/kernel/default.nix | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 167 insertions(+), 191 deletions(-)

diff --git a/default.nix b/default.nix @@ -17,20 +17,31 @@ let (if phram then ./modules/phram.nix else (args: {})) ] nixpkgs; 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 { - inherit squashfs kernel; - dtb = kernel.dtb { - dts = "qca9531_glinet_gl-ar750.dts"; - + inherit squashfs; + kernel = nixpkgs.kernel.override { + inherit (config.kernel) config checkedConfig; + }; + 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 = kernel.uimage { + uimage = (callPackage ./kernel/uimage.nix {}) { commandLine = concatStringsSep " " config.boot.commandLine; inherit (device.boot) loadAddress entryPoint; - inherit (kernel) vmlinux; + inherit kernel; inherit dtb; }; combined-image = nixpkgs.runCommand "firmware.bin" { @@ -60,9 +71,9 @@ let mkdir $out cd $out ln -s ${squashfs} squashfs - ln -s ${kernel.vmlinux} vmlinux + ln -s ${kernel} vmlinux ln -s ${manifest} manifest - ln -s ${kernel.vmlinux.modulesupport} build + ln -s ${kernel.headers} build '' + (if device ? boot then '' ln -s ${uimage} uimage diff --git a/devices/gl-ar750/default.nix b/devices/gl-ar750/default.nix @@ -32,53 +32,33 @@ overlay = final: prev: let - inherit (final) fetchFromGitHub fetchgit stdenvNoCC; - openwrt = fetchFromGitHub { + openwrt = final.fetchFromGitHub { name = "openwrt-source"; repo = "openwrt"; owner = "openwrt"; rev = "a5265497a4f6da158e95d6a450cb2cb6dc085cab"; hash = "sha256-YYi4gkpLjbOK7bM2MGQjAyEBuXJ9JNXoz/JEmYf8xE8="; }; - mainline = fetchFromGitHub { - name = "kernel-source"; - owner = "torvalds"; - repo = "linux"; - rev = "90c7e9b400c751dbd73885f494f421f90ca69721"; - hash = "sha256-pq6QNa0PJVeheaZkuvAPD0rLuEeKrViKk65dz+y4kqo="; - }; in { - sources = { - inherit openwrt; - kernel = stdenvNoCC.mkDerivation { - name = "spindled-kernel-tree"; - src = mainline; - phases = [ - "unpackPhase" "patchPhase" "openWrtPatchPhase" - "patchScripts" "installPhase" - ]; - patches = [ ../../kernel/random.patch ]; - patchScripts = '' - patchShebangs scripts/ - ''; - openWrtPatchPhase = '' - cp -av ${openwrt}/target/linux/generic/files/* . - chmod -R u+w . - cp -av ${openwrt}/target/linux/ath79/files/* . - chmod -R u+w . - patches() { - for i in $* ; do patch --batch --forward -p1 < $i ;done - } - patches ${openwrt}/target/linux/generic/backport-5.15/*.patch - patches ${openwrt}/target/linux/generic/pending-5.15/*.patch - patches ${openwrt}/target/linux/generic/hack-5.15/*.patch - patches ${openwrt}/target/linux/ath79/patches-5.15/*.patch - ''; - installPhase = '' - mkdir -p $out - cp -a . $out - ''; + kernel = prev.kernel.override { + src = final.fetchurl { + name = "linux.tar.gz"; + url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.71.tar.gz"; + hash = "sha256-yhO2cXIeIgUxkSZf/4aAsF11uxyh+UUZu6D1h92vCD8="; }; + extraPatchPhase = '' + cp -av ${openwrt}/target/linux/generic/files/* . + chmod -R u+w . + cp -av ${openwrt}/target/linux/ath79/files/* . + chmod -R u+w . + patches() { + for i in $* ; do patch --batch --forward -p1 < $i ;done + } + patches ${openwrt}/target/linux/generic/backport-5.15/*.patch + patches ${openwrt}/target/linux/generic/pending-5.15/*.patch + patches ${openwrt}/target/linux/generic/hack-5.15/*.patch + patches ${openwrt}/target/linux/ath79/patches-5.15/*.patch + ''; }; }; kernel = rec { @@ -88,8 +68,6 @@ USE_OF = "y"; ATH79 = "y"; - LIMINIX = "y"; - SERIAL_8250_CONSOLE = "y"; SERIAL_8250 = "y"; SERIAL_CORE_CONSOLE = "y"; @@ -118,9 +96,10 @@ AG71XX = "y"; # ethernet (qca,qca9530-eth) MFD_SYSCON = "y"; # ethernet (compatible "syscon") AR8216_PHY = "y"; # eth1 is behind a switch - }; - config = { - CPU_LITTLE_ENDIAN= "n"; + + MTD = "y"; + MTD_CMDLINE_PARTS = "y"; + MTD_BLOCK = "y"; # fix undefined ref to register_mtd_blktrans_devs CPU_BIG_ENDIAN= "y"; # this is all copied from nixwrt ath79 config. Clearly not all @@ -128,7 +107,6 @@ # installation method config or ... "CMDLINE_PARTITION" = "y"; - "DEBUG_INFO" = "y"; "EARLY_PRINTK" = "y"; "FW_LOADER" = "y"; # we don't have a user helper, so we get multiple 60s pauses @@ -136,7 +114,7 @@ "FW_LOADER_USER_HELPER" = "n"; "MODULE_SIG" = "y"; - "MTD_CMDLINE_PARTS" = "y"; + "PARTITION_ADVANCED" = "y"; "PRINTK_TIME" = "y"; "SQUASHFS" = "y"; diff --git a/devices/qemu/default.nix b/devices/qemu/default.nix @@ -16,31 +16,15 @@ overlay = final: prev: let inherit (final) stdenvNoCC fetchFromGitHub; in { - sources = { - kernel = - let src = fetchFromGitHub { - name = "kernel-source"; - owner = "torvalds"; - repo = "linux"; - rev = "3d7cb6b04c3f3115719235cc6866b10326de34cd"; # v5.19 - hash = "sha256-OVsIRScAnrPleW1vbczRAj5L/SGGht2+GnvZJClMUu4="; - }; - in stdenvNoCC.mkDerivation { - name = "spindled-kernel-tree"; - inherit src; - phases = [ - "unpackPhase" - "patchScripts" "installPhase" - ]; - - patchScripts = '' - patchShebangs scripts/ - ''; - installPhase = '' - mkdir -p $out - cp -a . $out - ''; - }; + kernel = prev.kernel.override { + # using fetchurl not fetchzip because it doesn't unpack, and + # copying 6GB of data from one store location to another + # takes an absolute bloody age + src = final.fetchurl { + name = "linux.tar.gz"; + url = "https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.19.16.tar.gz"; + hash = "sha256-m4NeoEsCEK0HSIKTZ6zYTgk1fD3W0PSOMXN6fyHpkP8="; + }; }; }; diff --git a/kernel/dtb.nix b/kernel/dtb.nix @@ -1,15 +1,10 @@ { stdenv -, openwrt , dtc -, kernel }: { dts +, includes }:let - includes = [ - "${openwrt}/target/linux/ath79/dts" - "${kernel}/include" - ]; cppDtSearchFlags = builtins.concatStringsSep " " (map (f: "-I${f}") includes); dtcSearchFlags = builtins.concatStringsSep " " (map (f: "-i${f}") includes); in stdenv.mkDerivation { @@ -17,7 +12,7 @@ in stdenv.mkDerivation { phases = [ "buildPhase" ]; nativeBuildInputs = [ dtc ]; 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 test -e $out ''; diff --git a/kernel/uimage.nix b/kernel/uimage.nix @@ -7,7 +7,7 @@ let objcopy = "${stdenv.cc.bintools.targetPrefix}objcopy"; in { - vmlinux + kernel , commandLine , entryPoint , extraName ? "" # e.g. socFamily @@ -28,7 +28,7 @@ stdenv.mkDerivation { ubootTools ]; preparePhase = '' - cp ${vmlinux} vmlinux.elf; chmod +w vmlinux.elf + cp ${kernel} vmlinux.elf; chmod +w vmlinux.elf ''; dtbPhase = '' dtc -I dtb -O dts -o tmp.dts ${dtb} diff --git a/kernel/vmlinux.nix b/kernel/vmlinux.nix @@ -1,101 +0,0 @@ -{ stdenv - , buildPackages - , runCommand - , writeText - , lib - - , config - , checkedConfig ? {} - , tree -} : -let writeConfig = name : config: writeText name - (builtins.concatStringsSep - "\n" - (lib.mapAttrsToList - (name: value: (if value == "n" then "# CONFIG_${name} is not set" else "CONFIG_${name}=${value}")) - config - )); - kconfigFile = writeConfig "kconfig" (config // checkedConfig); - # KLUDGE FIXME. some symbols we need to enable in some configurations don't - # have a prompt (!), so we can't turn them on just by adding FOO=y and make oldconfig - # - # (!) yes, that was my reaction too - kconfigLocal = writeText "Kconfig.local" '' - config LIMINIX - prompt "Local symbols" - bool - default y - select SOC_QCA955X - ''; - checkedConfigFile = writeConfig "checked_kconfig" checkedConfig ; - inherit lib; in -stdenv.mkDerivation rec { - name = "vmlinux"; - - hardeningDisable = ["all"]; - nativeBuildInputs = [buildPackages.stdenv.cc] ++ - (with buildPackages.pkgs; - [rsync bc bison flex pkgconfig openssl ncurses.all perl]); - CC = "${stdenv.cc.bintools.targetPrefix}gcc"; - HOSTCC = with buildPackages.pkgs; - "gcc -I${openssl}/include -I${ncurses}/include"; - HOST_EXTRACFLAGS = with buildPackages.pkgs; - "-I${openssl.dev}/include -L${openssl.out}/lib -L${ncurses.out}/lib"; - PKG_CONFIG_PATH = "./pkgconfig"; - CROSS_COMPILE = stdenv.cc.bintools.targetPrefix; - ARCH = "mips"; # kernel uses "mips" here for both mips and mipsel - dontStrip = true; - dontPatchELF = true; - outputs = ["out" "modulesupport"]; - phases = [ - "butcherPkgconfig" - "configurePhase" - "checkConfigurationPhase" - "buildPhase" - "installPhase" - ]; - - # this is here to work around what I think is a bug in nixpkgs - # packaging of ncurses: it installs pkg-config data files which - # don't produce any -L options when queried with "pkg-config --lib - # ncurses". For a regular build you'll never even notice, this only - # becomes an issue if you do a nix-shell in this derivation and - # expect "make nconfig" to work. - butcherPkgconfig = '' - cp -r ${buildPackages.pkgs.ncurses.dev}/lib/pkgconfig . - chmod +w pkgconfig pkgconfig/*.pc - for i in pkgconfig/*.pc; do test -f $i && sed -i 's/^Libs:/Libs: -L''${libdir} /' $i;done - ''; - - configurePhase = '' - export KBUILD_OUTPUT=`pwd` - cp ${kconfigFile} .config - cp ${kconfigFile} .config.orig - cp ${kconfigLocal} Kconfig.local - ( cd ${tree} && make V=1 olddefconfig ) - ''; - - checkConfigurationPhase = '' - echo Checking required config items: - if comm -2 -3 <(grep 'CONFIG' ${checkedConfigFile} |sort) <(grep 'CONFIG' .config|sort) |grep '.' ; then - echo -e "^^^ Some configuration lost :-(\nPerhaps you have mutually incompatible settings, or have disabled options on which these depend.\n" - exit 0 - fi - echo "OK" - ''; - - KBUILD_BUILD_HOST = "liminix.builder"; - buildPhase = '' - make -C ${tree} vmlinux modules_prepare - ''; - - installPhase = '' - ${CROSS_COMPILE}strip -d vmlinux - cp vmlinux $out - mkdir -p $modulesupport - cp .config $modulesupport/config - make clean - cp -a . $modulesupport - ''; - -} diff --git a/overlay.nix b/overlay.nix @@ -12,6 +12,7 @@ final: prev: { s6-init-bin = final.callPackage ./pkgs/s6-init-bin {}; s6-rc-database = final.callPackage ./pkgs/s6-rc-database {}; + kernel = final.callPackage ./pkgs/kernel {}; dnsmasq = let d = prev.dnsmasq.overrideAttrs(o: { diff --git a/pkgs/kernel/default.nix b/pkgs/kernel/default.nix @@ -0,0 +1,108 @@ +{ stdenv + , buildPackages + , runCommand + , writeText + , lib + + , config + , checkedConfig ? {} + , src + , extraPatchPhase ? "true" +} : +let writeConfig = name : config: writeText name + (builtins.concatStringsSep + "\n" + (lib.mapAttrsToList + (name: value: (if value == "n" then "# CONFIG_${name} is not set" else "CONFIG_${name}=${value}")) + config + )); + kconfigFile = writeConfig "kconfig" (config // checkedConfig); + # KLUDGE FIXME. some symbols we need to enable in some configurations don't + # have a prompt (!), so we can't turn them on just by adding FOO=y and make oldconfig + # + # (!) yes, that was my reaction too + kconfigLocal = writeText "Kconfig.local" '' + config LIMINIX + prompt "Local symbols" + bool + default y + select SOC_QCA955X + ''; + checkedConfigFile = writeConfig "checked_kconfig" checkedConfig ; + inherit lib; in +stdenv.mkDerivation rec { + name = "kernel"; + inherit src extraPatchPhase; + hardeningDisable = ["all"]; + nativeBuildInputs = [buildPackages.stdenv.cc] ++ + (with buildPackages.pkgs; + [rsync bc bison flex pkgconfig openssl ncurses.all perl]); + CC = "${stdenv.cc.bintools.targetPrefix}gcc"; + HOSTCC = with buildPackages.pkgs; + "gcc -I${openssl}/include -I${ncurses}/include"; + HOST_EXTRACFLAGS = with buildPackages.pkgs; + "-I${openssl.dev}/include -L${openssl.out}/lib -L${ncurses.out}/lib"; + PKG_CONFIG_PATH = "./pkgconfig"; + CROSS_COMPILE = stdenv.cc.bintools.targetPrefix; + ARCH = "mips"; # kernel uses "mips" here for both mips and mipsel + KBUILD_BUILD_HOST = "liminix.builder"; + + dontStrip = true; + dontPatchELF = true; + outputs = ["out" "headers"]; + phases = [ + "unpackPhase" + "butcherPkgconfig" + "extraPatchPhase" + "patchScripts" + "configurePhase" + "checkConfigurationPhase" + "buildPhase" + "installPhase" + ]; + + # this is here to work around what I think is a bug in nixpkgs + # packaging of ncurses: it installs pkg-config data files which + # don't produce any -L options when queried with "pkg-config --lib + # ncurses". For a regular build you'll never even notice, this only + # becomes an issue if you do a nix-shell in this derivation and + # expect "make nconfig" to work. + butcherPkgconfig = '' + cp -r ${buildPackages.pkgs.ncurses.dev}/lib/pkgconfig . + chmod +w pkgconfig pkgconfig/*.pc + for i in pkgconfig/*.pc; do test -f $i && sed -i 's/^Libs:/Libs: -L''${libdir} /' $i;done + ''; + + patchScripts = '' + patchShebangs scripts/ + ''; + + configurePhase = '' + export KBUILD_OUTPUT=`pwd` + cp ${kconfigFile} .config + cp ${kconfigFile} .config.orig + cp ${kconfigLocal} Kconfig.local + make V=1 olddefconfig + ''; + + checkConfigurationPhase = '' + echo Checking required config items: + if comm -2 -3 <(grep 'CONFIG' ${checkedConfigFile} |sort) <(grep 'CONFIG' .config|sort) |grep '.' ; then + echo -e "^^^ Some configuration lost :-(\nPerhaps you have mutually incompatible settings, or have disabled options on which these depend.\n" + exit 0 + fi + echo "OK" + ''; + + buildPhase = '' + make vmlinux modules_prepare + ''; + + installPhase = '' + ${CROSS_COMPILE}strip -d vmlinux + cp vmlinux $out + mkdir -p $headers + cp -a include .config $headers/ + ''; + +}