manual-config: Fully general cross-compiling

In the most general case, the cross and native kernel may differ in
patches and configuration file as well as architecture, kernel target,
etc. It's probably overkill to support that case, but since it was
doable without much duplication and it will make integrating with the
existing cross-compilation support in the generic kernel I decided to
implement it anyway.

Signed-off-by: Shea Levy <shea@shealevy.com>
This commit is contained in:
Shea Levy 2013-12-31 23:09:42 -05:00
parent 784c6d320c
commit a87b1f36e0

View File

@ -19,21 +19,40 @@ in {
src, src,
# Any patches # Any patches
kernelPatches ? [], kernelPatches ? [],
# The kernel .config file # Patches for native compiling only
nativeKernelPatches ? [],
# Patches for cross compiling only
crossKernelPatches ? [],
# The native kernel .config file
configfile, configfile,
# The cross kernel .config file
crossConfigfile ? configfile,
# Manually specified nixexpr representing the config # Manually specified nixexpr representing the config
# If unspecified, this will be autodetected from the .config # If unspecified, this will be autodetected from the .config
config ? stdenv.lib.optionalAttrs allowImportFromDerivation (readConfig configfile), config ? stdenv.lib.optionalAttrs allowImportFromDerivation (readConfig configfile),
# Cross-compiling config
crossConfig ? if allowImportFromDerivation then (readConfig crossConfigfile) else config,
# Whether to utilize the controversial import-from-derivation feature to parse the config # Whether to utilize the controversial import-from-derivation feature to parse the config
allowImportFromDerivation ? false allowImportFromDerivation ? false
}: }:
let config_ = config; in
let let
inherit (stdenv.lib) inherit (stdenv.lib)
hasAttr getAttr optionalAttrs optional optionalString maintainers platforms; hasAttr getAttr optional optionalString maintainers platforms;
installkernel = writeTextFile { name = "installkernel"; executable=true; text = ''
#!${stdenv.shell} -e
mkdir -p $4
cp -av $2 $4
cp -av $3 $4
''; };
commonMakeFlags = [
"O=$(buildRoot)"
];
drvAttrs = config_: platform: kernelPatches: configfile:
let
config = let attrName = attr: "CONFIG_" + attr; in { config = let attrName = attr: "CONFIG_" + attr; in {
isSet = attr: hasAttr (attrName attr) config; isSet = attr: hasAttr (attrName attr) config;
@ -50,25 +69,11 @@ let
isDisabled = attr: (!(config.isSet attr)) || (config.isNo attr); isDisabled = attr: (!(config.isSet attr)) || (config.isNo attr);
} // config_; } // config_;
installkernel = writeTextFile { name = "installkernel"; executable=true; text = ''
#!${stdenv.shell} -e
mkdir -p $4
cp -av $2 $4
cp -av $3 $4
'';};
isModular = config.isYes "MODULES"; isModular = config.isYes "MODULES";
installsFirmware = (config.isEnabled "FW_LOADER") && installsFirmware = (config.isEnabled "FW_LOADER") &&
(isModular || (config.isDisabled "FIRMWARE_IN_KERNEL")); (isModular || (config.isDisabled "FIRMWARE_IN_KERNEL"));
commonMakeFlags = [
"O=$(buildRoot)"
];
# Some image types need special install targets (e.g. uImage is installed with make uinstall)
installTarget = target: [ (if target == "uImage" then "uinstall" else "install") ];
sourceRoot = stdenv.mkDerivation { sourceRoot = stdenv.mkDerivation {
name = "linux-source-${version}"; name = "linux-source-${version}";
@ -83,7 +88,9 @@ let
echo "stripping FHS paths in \`$mf'..." echo "stripping FHS paths in \`$mf'..."
sed -i "$mf" -e 's|/usr/bin/||g ; s|/bin/||g ; s|/sbin/||g' sed -i "$mf" -e 's|/usr/bin/||g ; s|/bin/||g ; s|/sbin/||g'
done done
sed -i Makefile -e 's|= depmod|= ${kmod}/sbin/depmod|' sed -i Makefile -e 's|= depmod|= ${kmod}/sbin/depmod|'
# Patch kconfig to print "###" after every question so that # Patch kconfig to print "###" after every question so that
# generate-config.pl from the generic builder can answer them. # generate-config.pl from the generic builder can answer them.
# This only affects oldaskconfig. # This only affects oldaskconfig.
@ -95,13 +102,7 @@ let
mv $sourceRoot $out mv $sourceRoot $out
''; '';
}; };
in in {
stdenv.mkDerivation {
name = "linux-${version}";
enableParallelBuilding = true;
outputs = if isModular then [ "out" "dev" ] else null; outputs = if isModular then [ "out" "dev" ] else null;
passthru = { passthru = {
@ -123,13 +124,6 @@ stdenv.mkDerivation {
runHook postConfigure runHook postConfigure
''; '';
nativeBuildInputs = [ perl bc nettools ] ++ optional (stdenv.platform.uboot != null)
(ubootChooser stdenv.platform.uboot);
makeFlags = commonMakeFlags ++ [
"ARCH=${stdenv.platform.kernelArch}"
];
buildFlags = [ stdenv.platform.kernelTarget ] ++ optional isModular "modules"; buildFlags = [ stdenv.platform.kernelTarget ] ++ optional isModular "modules";
installFlags = [ installFlags = [
@ -138,20 +132,8 @@ stdenv.mkDerivation {
] ++ (optional isModular "INSTALL_MOD_PATH=$(out)") ] ++ (optional isModular "INSTALL_MOD_PATH=$(out)")
++ optional installsFirmware "INSTALL_FW_PATH=$(out)/lib/firmware"; ++ optional installsFirmware "INSTALL_FW_PATH=$(out)/lib/firmware";
installTargets = installTarget stdenv.platform.kernelTarget; # Some image types need special install targets (e.g. uImage is installed with make uinstall)
installTargets = [ (if platform.kernelTarget == "uImage" then "uinstall" else "install") ];
crossAttrs = let cp = stdenv.cross.platform; in {
buildFlags = [ cp.kernelTarget ] ++ optional isModular "modules";
makeFlags = commonMakeFlags ++ [
"ARCH=${cp.kernelArch}"
"CROSS_COMPILE=$(crossConfig)-"
];
installTargets = installTarget cp.kernelTarget;
buildInputs = optional (cp.uboot != null) (ubootChooser cp.uboot).crossDrv;
};
postInstall = optionalString installsFirmware '' postInstall = optionalString installsFirmware ''
mkdir -p $out/lib/firmware mkdir -p $out/lib/firmware
@ -176,6 +158,34 @@ stdenv.mkDerivation {
"s|${sourceRoot}|$NIX_STORE/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${sourceRoot.name}|g" "s|${sourceRoot}|$NIX_STORE/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${sourceRoot.name}|g"
fi fi
'' else null; '' else null;
};
in
stdenv.mkDerivation ((drvAttrs config stdenv.platform (kernelPatches ++ nativeKernelPatches) configfile) // {
name = "linux-${version}";
enableParallelBuilding = true;
nativeBuildInputs = [ perl bc nettools ] ++ optional (stdenv.platform.uboot != null)
(ubootChooser stdenv.platform.uboot);
makeFlags = commonMakeFlags ++ [
"ARCH=${stdenv.platform.kernelArch}"
];
crossAttrs = let cp = stdenv.cross.platform; in {
(drvAttrs crossConfig cp (kernelPatches ++ crossKernelPatches) crossConfigfile) // {
makeFlags = commonMakeFlags ++ [
"ARCH=${cp.kernelArch}"
"CROSS_COMPILE=$(crossConfig)-"
];
# !!! uboot has messed up cross-compiling, nativeDrv builds arm tools on x86,
# crossDrv builds x86 tools on x86 (but arm uboot). If this is fixed, uboot
# can just go into buildInputs (but not nativeBuildInputs since cp.uboot
# may be different from stdenv.platform.uboot)
buildInputs = optional (cp.uboot != null) (ubootChooser cp.uboot).crossDrv;
};
meta = { meta = {
description = "The Linux kernel"; description = "The Linux kernel";
@ -186,4 +196,4 @@ stdenv.mkDerivation {
]; ];
platforms = platforms.linux; platforms = platforms.linux;
}; };
} })