0c18551c93
Since we keep the source in the kernel build anyway, no space is wasted by having a separate store path for the unpacked source. The upside is that the same source can be used to build the kernel multiple times, or generate configurations for later kernel builds, without going through the (fairly long) unpack and patch process multiple times.
175 lines
4.7 KiB
Nix
175 lines
4.7 KiB
Nix
{ stdenv, runCommand, nettools, perl, kmod, writeTextFile }:
|
|
|
|
with stdenv.lib;
|
|
|
|
let
|
|
|
|
# Function to parse the config file into a nix expression
|
|
readConfig = configFile:
|
|
let
|
|
configAttrs = import "${runCommand "config.nix" {} ''
|
|
(. ${configFile}
|
|
echo "{"
|
|
for var in `set`; do
|
|
if [[ "$var" =~ ^CONFIG_ ]]; then
|
|
IFS="="
|
|
set -- $var
|
|
echo "\"$1\" = \"''${*:2}\";"
|
|
fi
|
|
done
|
|
echo "}") > $out
|
|
''}";
|
|
|
|
config = configAttrs // rec {
|
|
attrName = attr: "CONFIG_" + attr;
|
|
|
|
isSet = attr: hasAttr (attrName attr) config;
|
|
|
|
getValue = attr: if isSet attr then getAttr (attrName attr) config else null;
|
|
|
|
isYes = attr: (isSet attr) && ((getValue attr) == "y");
|
|
|
|
isNo = attr: (isSet attr) && ((getValue attr) == "n");
|
|
|
|
isModule = attr: (isSet attr) && ((getValue attr) == "m");
|
|
|
|
isEnabled = attr: (isModule attr) || (isYes attr);
|
|
|
|
isDisabled = attr: (!(isSet attr)) || (isNo attr);
|
|
};
|
|
in
|
|
config;
|
|
|
|
in
|
|
|
|
{
|
|
# The kernel version
|
|
version,
|
|
# The version of the kernel module directory
|
|
modDirVersion ? version,
|
|
# The kernel source (tarball, git checkout, etc.)
|
|
src,
|
|
# Any patches
|
|
kernelPatches ? [],
|
|
# The kernel .config file
|
|
configfile,
|
|
# Manually specified nixexpr representing the config
|
|
# If unspecified, this will be autodetected from the .config
|
|
config ? optionalAttrs allowImportFromDerivation (readConfig configfile),
|
|
# Whether to utilize the controversial import-from-derivation feature to parse the config
|
|
allowImportFromDerivation ? false
|
|
}:
|
|
|
|
let
|
|
installkernel = name: writeTextFile { name = "installkernel"; executable=true; text = ''
|
|
#!/bin/sh
|
|
mkdir $4
|
|
cp -av $2 $4/${name}
|
|
cp -av $3 $4
|
|
'';};
|
|
|
|
isModular = config.isYes "MODULES";
|
|
|
|
installsFirmware = (config.isEnabled "FW_LOADER") &&
|
|
(isModular || (config.isDisabled "FIRMWARE_IN_KERNEL"));
|
|
|
|
commonMakeFlags = [
|
|
"O=$(buildRoot)"
|
|
"INSTALL_PATH=$(out)"
|
|
] ++ (optional isModular "INSTALL_MOD_PATH=$(out)")
|
|
++ optional installsFirmware "INSTALL_FW_PATH=$(out)/lib/firmware";
|
|
in
|
|
|
|
let self = stdenv.mkDerivation {
|
|
name = "linux-${version}";
|
|
|
|
enableParallelBuilding = true;
|
|
|
|
passthru = {
|
|
inherit version modDirVersion config kernelPatches src;
|
|
|
|
source = stdenv.mkDerivation {
|
|
name = "linux-${version}-source";
|
|
|
|
inherit src;
|
|
|
|
patches = map (p: p.patch) kernelPatches;
|
|
|
|
phases = [ "unpackPhase" "patchPhase" "installPhase" ];
|
|
|
|
prePatch = ''
|
|
for mf in $(find -name Makefile -o -name Makefile.include -o -name install.sh); do
|
|
echo "stripping FHS paths in \`$mf'..."
|
|
sed -i "$mf" -e 's|/usr/bin/||g ; s|/bin/||g ; s|/sbin/||g'
|
|
done
|
|
sed -i Makefile -e 's|= depmod|= ${kmod}/sbin/depmod|'
|
|
'';
|
|
|
|
installPhase = ''
|
|
cd ..
|
|
mv $sourceRoot $out
|
|
'';
|
|
};
|
|
};
|
|
|
|
unpackPhase = ''
|
|
ln -sv ${self.source} src
|
|
export sourceRoot="$(pwd)/src"
|
|
mkdir build
|
|
export buildRoot="$(pwd)/build"
|
|
cd $sourceRoot
|
|
'';
|
|
|
|
configurePhase = ''
|
|
runHook preConfigure
|
|
make $makeFlags "''${makeFlagsArray[@]}" mrproper
|
|
ln -sv ${configfile} $buildRoot/.config
|
|
make $makeFlags "''${makeFlagsArray[@]}" oldconfig
|
|
rm $buildRoot/.config.old
|
|
runHook postConfigure
|
|
'';
|
|
|
|
buildNativeInputs = [ perl nettools ];
|
|
|
|
makeFlags = commonMakeFlags ++ [
|
|
"INSTALLKERNEL=${installkernel stdenv.platform.kernelTarget}"
|
|
];
|
|
|
|
crossAttrs = {
|
|
makeFlags = commonMakeFlags ++ [
|
|
"INSTALLKERNEL=${installkernel stdenv.cross.platform.kernelTarget}"
|
|
];
|
|
};
|
|
|
|
postInstall = optionalString installsFirmware ''
|
|
mkdir -p $out/lib/firmware
|
|
'' + (if isModular then ''
|
|
make modules_install $makeFlags "''${makeFlagsArray[@]}" \
|
|
$installFlags "''${installFlagsArray[@]}"
|
|
rm -f $out/lib/modules/${modDirVersion}/{build,source}
|
|
cd ..
|
|
mv $sourceRoot $out/lib/modules/${modDirVersion}/source
|
|
mv $buildRoot $out/lib/modules/${modDirVersion}/build
|
|
unlink $out/lib/modules/${modDirVersion}/build/source
|
|
ln -sv ${self.source} $out/lib/modules/${modDirVersion}/build/source
|
|
'' else optionalString installsFirmware ''
|
|
make firmware_install $makeFlags "''${makeFlagsArray[@]}" \
|
|
$installFlags "''${installFlagsArray[@]}"
|
|
'');
|
|
|
|
postFixup = optionalString isModular ''
|
|
if [ -z "$dontStrip" ]; then
|
|
find $out -name "*.ko" -print0 | xargs -0 -r strip -S
|
|
fi
|
|
'';
|
|
|
|
meta = {
|
|
description = "The Linux kernel";
|
|
license = "GPLv2";
|
|
homepage = http://www.kernel.org/;
|
|
maintainers = [
|
|
maintainers.shlevy
|
|
];
|
|
platforms = lib.platforms.linux;
|
|
};
|
|
}; in self
|