about summary refs log tree commit diff
path: root/pkgs/os-specific
diff options
context:
space:
mode:
authorShea Levy <shea@shealevy.com>2013-12-31 23:09:42 -0500
committerShea Levy <shea@shealevy.com>2013-12-31 23:09:42 -0500
commita87b1f36e0095956b9b170f2c7071263a36ae155 (patch)
treeea83a4b5d5adfa6c1e7f0a3127218df7711d2e14 /pkgs/os-specific
parent784c6d320c6d48989310e5c68f821d10486b4805 (diff)
downloadnixlib-a87b1f36e0095956b9b170f2c7071263a36ae155.tar
nixlib-a87b1f36e0095956b9b170f2c7071263a36ae155.tar.gz
nixlib-a87b1f36e0095956b9b170f2c7071263a36ae155.tar.bz2
nixlib-a87b1f36e0095956b9b170f2c7071263a36ae155.tar.lz
nixlib-a87b1f36e0095956b9b170f2c7071263a36ae155.tar.xz
nixlib-a87b1f36e0095956b9b170f2c7071263a36ae155.tar.zst
nixlib-a87b1f36e0095956b9b170f2c7071263a36ae155.zip
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>
Diffstat (limited to 'pkgs/os-specific')
-rw-r--r--pkgs/os-specific/linux/kernel/manual-config.nix252
1 files changed, 131 insertions, 121 deletions
diff --git a/pkgs/os-specific/linux/kernel/manual-config.nix b/pkgs/os-specific/linux/kernel/manual-config.nix
index 3219ef0b002b..9c82aea41aa6 100644
--- a/pkgs/os-specific/linux/kernel/manual-config.nix
+++ b/pkgs/os-specific/linux/kernel/manual-config.nix
@@ -19,110 +19,153 @@ in {
   src,
   # Any patches
   kernelPatches ? [],
-  # The kernel .config file
+  # Patches for native compiling only
+  nativeKernelPatches ? [],
+  # Patches for cross compiling only
+  crossKernelPatches ? [],
+  # The native kernel .config file
   configfile,
+  # The cross kernel .config file
+  crossConfigfile ? configfile,
   # Manually specified nixexpr representing the config
   # If unspecified, this will be autodetected from the .config
   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
   allowImportFromDerivation ? false
 }:
 
-let config_ = config; in
-
 let
   inherit (stdenv.lib)
-    hasAttr getAttr optionalAttrs optional optionalString maintainers platforms;
-
-  config = let attrName = attr: "CONFIG_" + attr; in {
-    isSet = attr: hasAttr (attrName attr) config;
-
-    getValue = attr: if config.isSet attr then getAttr (attrName attr) config else null;
-
-    isYes = attr: (config.getValue attr) == "y";
-
-    isNo = attr: (config.getValue attr) == "n";
-
-    isModule = attr: (config.getValue attr) == "m";
-
-    isEnabled = attr: (config.isModule attr) || (config.isYes attr);
-
-    isDisabled = attr: (!(config.isSet attr)) || (config.isNo attr);
-  } // config_;
+    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
-  '';};
-
-  isModular = config.isYes "MODULES";
-
-  installsFirmware = (config.isEnabled "FW_LOADER") &&
-    (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 {
-    name = "linux-source-${version}";
-
-    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|'
-      # Patch kconfig to print "###" after every question so that
-      # generate-config.pl from the generic builder can answer them.
-      # This only affects oldaskconfig.
-      sed -e '/fflush(stdout);/i\printf("###");' -i scripts/kconfig/conf.c
-    '';
+  drvAttrs = config_: platform: kernelPatches: configfile:
+    let
+      config = let attrName = attr: "CONFIG_" + attr; in {
+        isSet = attr: hasAttr (attrName attr) config;
 
-    installPhase = ''
-      cd ..
-      mv $sourceRoot $out
-    '';
-  };
+        getValue = attr: if config.isSet attr then getAttr (attrName attr) config else null;
+
+        isYes = attr: (config.getValue attr) == "y";
+
+        isNo = attr: (config.getValue attr) == "n";
+
+        isModule = attr: (config.getValue attr) == "m";
+
+        isEnabled = attr: (config.isModule attr) || (config.isYes attr);
+
+        isDisabled = attr: (!(config.isSet attr)) || (config.isNo attr);
+      } // config_;
+
+      isModular = config.isYes "MODULES";
+
+      installsFirmware = (config.isEnabled "FW_LOADER") &&
+        (isModular || (config.isDisabled "FIRMWARE_IN_KERNEL"));
+
+      sourceRoot = stdenv.mkDerivation {
+        name = "linux-source-${version}";
+
+        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|'
+
+          # Patch kconfig to print "###" after every question so that
+          # generate-config.pl from the generic builder can answer them.
+          # This only affects oldaskconfig.
+          sed -e '/fflush(stdout);/i\printf("###");' -i scripts/kconfig/conf.c
+        '';
+
+        installPhase = ''
+          cd ..
+          mv $sourceRoot $out
+        '';
+      };
+    in {
+      outputs = if isModular then [ "out" "dev" ] else null;
+
+      passthru = {
+        inherit version modDirVersion config kernelPatches src;
+      };
+
+      inherit sourceRoot;
+
+      unpackPhase = ''
+        mkdir build
+        export buildRoot="$(pwd)/build"
+        cd ${sourceRoot}
+      '';
+
+      configurePhase = ''
+        runHook preConfigure
+        ln -sv ${configfile} $buildRoot/.config
+        make $makeFlags "''${makeFlagsArray[@]}" oldconfig
+        runHook postConfigure
+      '';
+
+      buildFlags = [ stdenv.platform.kernelTarget ] ++ optional isModular "modules";
+
+      installFlags = [
+        "INSTALLKERNEL=${installkernel}"
+        "INSTALL_PATH=$(out)"
+      ] ++ (optional isModular "INSTALL_MOD_PATH=$(out)")
+      ++ optional installsFirmware "INSTALL_FW_PATH=$(out)/lib/firmware";
+
+      # Some image types need special install targets (e.g. uImage is installed with make uinstall)
+      installTargets = [ (if platform.kernelTarget == "uImage" then "uinstall" else "install") ];
+
+      postInstall = optionalString installsFirmware ''
+        mkdir -p $out/lib/firmware
+      '' + (if isModular then ''
+        make modules_install $makeFlags "''${makeFlagsArray[@]}" \
+          $installFlags "''${installFlagsArray[@]}"
+        unlink $out/lib/modules/${modDirVersion}/build
+        mkdir -p $dev/lib/modules/${modDirVersion}
+        mv $out/lib/modules/${modDirVersion}/source $dev/lib/modules/${modDirVersion}/source
+        mv $buildRoot $dev/lib/modules/${modDirVersion}/build
+      '' else optionalString installsFirmware ''
+        make firmware_install $makeFlags "''${makeFlagsArray[@]}" \
+          $installFlags "''${installFlagsArray[@]}"
+      '');
+
+      postFixup = if isModular then ''
+        if [ -z "$dontStrip" ]; then
+            find $out -name "*.ko" -print0 | xargs -0 -r ''${crossConfig+$crossConfig-}strip -S
+            # Remove all references to the source directory to avoid unneeded
+            # runtime dependencies
+            find $out -name "*.ko" -print0 | xargs -0 -r sed -i \
+              "s|${sourceRoot}|$NIX_STORE/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${sourceRoot.name}|g"
+        fi
+      '' else null;
+    };
 in
 
-stdenv.mkDerivation {
+stdenv.mkDerivation ((drvAttrs config stdenv.platform (kernelPatches ++ nativeKernelPatches) configfile) // {
   name = "linux-${version}";
 
   enableParallelBuilding = true;
 
-  outputs = if isModular then [ "out" "dev" ] else null;
-
-  passthru = {
-    inherit version modDirVersion config kernelPatches src;
-  };
-
-  inherit sourceRoot;
-
-  unpackPhase = ''
-    mkdir build
-    export buildRoot="$(pwd)/build"
-    cd ${sourceRoot}
-  '';
-
-  configurePhase = ''
-    runHook preConfigure
-    ln -sv ${configfile} $buildRoot/.config
-    make $makeFlags "''${makeFlagsArray[@]}" oldconfig
-    runHook postConfigure
-  '';
-
   nativeBuildInputs = [ perl bc nettools ] ++ optional (stdenv.platform.uboot != null)
     (ubootChooser stdenv.platform.uboot);
 
@@ -130,53 +173,20 @@ stdenv.mkDerivation {
     "ARCH=${stdenv.platform.kernelArch}"
   ];
 
-  buildFlags = [ stdenv.platform.kernelTarget ] ++ optional isModular "modules";
-
-  installFlags = [
-    "INSTALLKERNEL=${installkernel}"
-    "INSTALL_PATH=$(out)"
-  ] ++ (optional isModular "INSTALL_MOD_PATH=$(out)")
-  ++ optional installsFirmware "INSTALL_FW_PATH=$(out)/lib/firmware";
-
-  installTargets = installTarget stdenv.platform.kernelTarget;
-
   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;
+    (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;
   };
 
-  postInstall = optionalString installsFirmware ''
-    mkdir -p $out/lib/firmware
-  '' + (if isModular then ''
-    make modules_install $makeFlags "''${makeFlagsArray[@]}" \
-      $installFlags "''${installFlagsArray[@]}"
-    unlink $out/lib/modules/${modDirVersion}/build
-    mkdir -p $dev/lib/modules/${modDirVersion}
-    mv $out/lib/modules/${modDirVersion}/source $dev/lib/modules/${modDirVersion}/source
-    mv $buildRoot $dev/lib/modules/${modDirVersion}/build
-  '' else optionalString installsFirmware ''
-    make firmware_install $makeFlags "''${makeFlagsArray[@]}" \
-      $installFlags "''${installFlagsArray[@]}"
-  '');
-
-  postFixup = if isModular then ''
-    if [ -z "$dontStrip" ]; then
-        find $out -name "*.ko" -print0 | xargs -0 -r ''${crossConfig+$crossConfig-}strip -S
-        # Remove all references to the source directory to avoid unneeded
-        # runtime dependencies
-        find $out -name "*.ko" -print0 | xargs -0 -r sed -i \
-          "s|${sourceRoot}|$NIX_STORE/eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee-${sourceRoot.name}|g"
-    fi
-  '' else null;
-
   meta = {
     description = "The Linux kernel";
     license = "GPLv2";
@@ -186,4 +196,4 @@ stdenv.mkDerivation {
     ];
     platforms = platforms.linux;
   };
-}
+})