Merge pull request #35451 from obsidiansystems/android-cross

Android Cross compilation
This commit is contained in:
John Ericson 2018-02-27 18:21:55 -05:00 committed by GitHub
commit d31fb808af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 137 additions and 11 deletions

View File

@ -23,10 +23,12 @@ rec {
config = parse.tripleFromSystem final.parsed; config = parse.tripleFromSystem final.parsed;
# Just a guess, based on `system` # Just a guess, based on `system`
platform = platforms.selectBySystem final.system; platform = platforms.selectBySystem final.system;
# Derived meta-data
libc = libc =
/**/ if final.isDarwin then "libSystem" /**/ if final.isDarwin then "libSystem"
else if final.isMinGW then "msvcrt" else if final.isMinGW then "msvcrt"
else if final.isMusl then "musl" else if final.isMusl then "musl"
else if final.isAndroid then "bionic"
else if final.isLinux /* default */ then "glibc" else if final.isLinux /* default */ then "glibc"
# TODO(@Ericson2314) think more about other operating systems # TODO(@Ericson2314) think more about other operating systems
else "native/impure"; else "native/impure";
@ -39,7 +41,10 @@ rec {
/**/ if final.isWindows then ".exe" /**/ if final.isWindows then ".exe"
else ""; else "";
}; };
# Misc boolean options
useAndroidPrebuilt = false;
} // mapAttrs (n: v: v final.parsed) inspect.predicates } // mapAttrs (n: v: v final.parsed) inspect.predicates
// args; // args;
in final; in assert final.useAndroidPrebuilt -> final.isAndroid;
final;
} }

View File

@ -38,6 +38,13 @@ rec {
platform = platforms.aarch64-multiplatform; platform = platforms.aarch64-multiplatform;
}; };
aarch64-android-prebuilt = rec {
config = "aarch64-unknown-linux-android";
arch = "aarch64";
platform = platforms.aarch64-multiplatform;
useAndroidPrebuilt = true;
};
scaleway-c1 = armv7l-hf-multiplatform // rec { scaleway-c1 = armv7l-hf-multiplatform // rec {
platform = platforms.scaleway-c1; platform = platforms.scaleway-c1;
inherit (platform.gcc) fpu; inherit (platform.gcc) fpu;

View File

@ -34,6 +34,7 @@ rec {
Cygwin = { kernel = kernels.windows; abi = abis.cygnus; }; Cygwin = { kernel = kernels.windows; abi = abis.cygnus; };
MinGW = { kernel = kernels.windows; abi = abis.gnu; }; MinGW = { kernel = kernels.windows; abi = abis.gnu; };
Android = [ { abi = abis.android; } { abi = abis.androideabi; } ];
Musl = with abis; map (a: { abi = a; }) [ musl musleabi musleabihf ]; Musl = with abis; map (a: { abi = a; }) [ musl musleabi musleabihf ];
Kexecable = map (family: { kernel = kernels.linux; cpu.family = family; }) Kexecable = map (family: { kernel = kernels.linux; cpu.family = family; })

View File

@ -176,6 +176,7 @@ rec {
types.abi = enum (attrValues abis); types.abi = enum (attrValues abis);
abis = setTypes types.openAbi { abis = setTypes types.openAbi {
android = {};
cygnus = {}; cygnus = {};
gnu = {}; gnu = {};
msvc = {}; msvc = {};

View File

@ -1,5 +1,6 @@
{ fetchurl, stdenv, lib { fetchurl, stdenv, lib
, buildPlatform, hostPlatform , buildPlatform, hostPlatform
, enableStatic ? stdenv.hostPlatform.useAndroidPrebuilt
}: }:
# assert !stdenv.isLinux || hostPlatform != buildPlatform; # TODO: improve on cross # assert !stdenv.isLinux || hostPlatform != buildPlatform; # TODO: improve on cross
@ -19,8 +20,8 @@ stdenv.mkDerivation rec {
sed '/^_GL_WARN_ON_USE (gets/d' -i srclib/stdio.in.h sed '/^_GL_WARN_ON_USE (gets/d' -i srclib/stdio.in.h
''; '';
configureFlags = configureFlags = lib.optional stdenv.isFreeBSD "--with-pic"
lib.optional stdenv.isFreeBSD "--with-pic"; ++ lib.optional enableStatic "--enable-static";
meta = { meta = {
description = "An iconv(3) implementation"; description = "An iconv(3) implementation";

View File

@ -3,6 +3,8 @@
, abiVersion , abiVersion
, mouseSupport ? false , mouseSupport ? false
, unicode ? true , unicode ? true
, enableStatic ? stdenv.hostPlatform.useAndroidPrebuilt
, withCxx ? !stdenv.hostPlatform.useAndroidPrebuilt
, gpm , gpm
@ -36,6 +38,8 @@ stdenv.mkDerivation rec {
"--enable-pc-files" "--enable-pc-files"
"--enable-symlinks" "--enable-symlinks"
] ++ lib.optional unicode "--enable-widec" ] ++ lib.optional unicode "--enable-widec"
++ lib.optional enableStatic "--enable-static"
++ lib.optional (!withCxx) "--without-cxx"
++ lib.optional (abiVersion == "5") "--with-abi-version=5"; ++ lib.optional (abiVersion == "5") "--with-abi-version=5";
# Only the C compiler, and explicitly not C++ compiler needs this flag on solaris: # Only the C compiler, and explicitly not C++ compiler needs this flag on solaris:

View File

@ -0,0 +1,82 @@
{ lib, hostPlatform, targetPlatform
, makeWrapper
, runCommand, wrapBintoolsWith, wrapCCWith
, buildAndroidndk, androidndk, targetAndroidndkPkgs
}:
let
# Mapping from a platform to information needed to unpack NDK stuff for that
# platform.
#
# N.B. The Android NDK uses slightly different LLVM-style platform triples
# than we do. We don't just use theirs because ours are less ambiguous and
# some builds need that clarity.
ndkInfoFun = { config, ... }: {
"x86_64-unknown-linux-gnu" = {
double = "linux-x86_64";
};
"arm-unknown-linux-androideabi" = {
arch = "arm";
triple = "arm-linux-androideabi";
gccVer = "4.8";
};
"aarch64-unknown-linux-android" = {
arch = "arm64";
triple = "aarch64-linux-android";
gccVer = "4.9";
};
}.${config} or
(throw "Android NDK doesn't support ${config}, as far as we know");
hostInfo = ndkInfoFun hostPlatform;
targetInfo = ndkInfoFun targetPlatform;
in
rec {
# Misc tools
binaries = let
ndkBinDir =
"${androidndk}/libexec/${androidndk.name}/toolchains/${targetInfo.triple}-${targetInfo.gccVer}/prebuilt/${hostInfo.double}/bin";
in runCommand "ndk-gcc-binutils" {
isGNU = true; # for cc-wrapper
nativeBuildInputs = [ makeWrapper ];
propgatedBuildInputs = [ androidndk ];
} ''
mkdir -p $out/bin
for prog in ${ndkBinDir}/${targetInfo.triple}-*; do
prog_suffix=$(basename $prog | sed 's/${targetInfo.triple}-//')
ln -s $prog $out/bin/${targetPlatform.config}-$prog_suffix
done
'';
binutils = wrapBintoolsWith {
bintools = binaries;
libc = targetAndroidndkPkgs.libraries;
};
gcc = wrapCCWith {
cc = binaries;
bintools = binutils;
libc = targetAndroidndkPkgs.libraries;
extraBuildCommands =
# GCC 4.9 is the first relase with "-fstack-protector"
lib.optionalString (lib.versionOlder targetInfo.gccVer "4.9") ''
sed -E \
-i $out/nix-support/add-hardening.sh \
-e 's|(-fstack-protector)-strong|\1|g'
'';
};
# Bionic lib C and other libraries.
#
# We use androidndk from the previous stage, else we waste time or get cycles
# cross-compiling packages to wrap incorrectly wrap binaries we don't include
# anyways.
libraries = {
name = "bionic-prebuilt";
type = "derivation";
outPath = "${buildAndroidndk}/libexec/${buildAndroidndk.name}/platforms/android-21/arch-${hostInfo.arch}/usr/";
drvPath = throw "fake derivation, build ${buildAndroidndk} to use";
};
}

View File

@ -242,4 +242,19 @@ rec {
inherit (pkgs) stdenv; inherit (pkgs) stdenv;
inherit androidsdk; inherit androidsdk;
}; };
androidndkPkgs = import ./androidndk-pkgs.nix {
inherit (buildPackages)
makeWrapper;
inherit (pkgs)
lib hostPlatform targetPlatform
runCommand wrapBintoolsWith wrapCCWith;
# buildPackages.foo rather than buildPackages.buildPackages.foo would work,
# but for splicing messing up on infinite recursion for the variants we
# *dont't* use. Using this workaround, but also making a test to ensure
# these two really are the same.
buildAndroidndk = buildPackages.buildPackages.androidenv.androidndk;
inherit androidndk;
targetAndroidndkPkgs = targetPackages.androidenv.androidndkPkgs;
};
} }

View File

@ -35,6 +35,8 @@ in bootStages ++ [
targetPlatform = crossSystem; targetPlatform = crossSystem;
cc = if crossSystem.useiOSCross or false cc = if crossSystem.useiOSCross or false
then buildPackages.darwin.ios-cross then buildPackages.darwin.ios-cross
else if crossSystem.useAndroidPrebuilt
then buildPackages.androidenv.androidndkPkgs.gcc
else buildPackages.gcc; else buildPackages.gcc;
}; };
}) })

View File

@ -8332,6 +8332,10 @@ with pkgs;
libopcodes = callPackage ../development/libraries/libopcodes { }; libopcodes = callPackage ../development/libraries/libopcodes { };
# TODO(@Ericson2314): Build bionic libc from source
bionic = assert hostPlatform.useAndroidPrebuilt;
androidenv.androidndkPkgs.libraries;
bobcat = callPackage ../development/libraries/bobcat { }; bobcat = callPackage ../development/libraries/bobcat { };
boehmgc = callPackage ../development/libraries/boehm-gc { }; boehmgc = callPackage ../development/libraries/boehm-gc { };
@ -8868,6 +8872,7 @@ with pkgs;
# libc is hackily often used from the previous stage. This `or` # libc is hackily often used from the previous stage. This `or`
# hack fixes the hack, *sigh*. # hack fixes the hack, *sigh*.
/**/ if name == "glibc" then targetPackages.glibcCross or glibcCross /**/ if name == "glibc" then targetPackages.glibcCross or glibcCross
else if name == "bionic" then targetPackages.bionic
else if name == "uclibc" then uclibcCross else if name == "uclibc" then uclibcCross
else if name == "musl" then targetPackages.muslCross or muslCross else if name == "musl" then targetPackages.muslCross or muslCross
else if name == "msvcrt" then targetPackages.windows.mingw_w64 or windows.mingw_w64 else if name == "msvcrt" then targetPackages.windows.mingw_w64 or windows.mingw_w64

View File

@ -93,6 +93,7 @@ in
mapTestEqual = lib.mapAttrsRecursive testEqual; mapTestEqual = lib.mapAttrsRecursive testEqual;
in mapTestEqual { in mapTestEqual {
androidndk = nativePlatforms;
boehmgc = nativePlatforms; boehmgc = nativePlatforms;
libffi = nativePlatforms; libffi = nativePlatforms;
libiconv = nativePlatforms; libiconv = nativePlatforms;
@ -125,12 +126,14 @@ in
rpi = mapTestOnCross lib.systems.examples.raspberryPi rpiCommon; rpi = mapTestOnCross lib.systems.examples.raspberryPi rpiCommon;
rpi-musl = mapTestOnCross lib.systems.examples.muslpi rpiCommon; rpi-musl = mapTestOnCross lib.systems.examples.muslpi rpiCommon;
/* Linux on Aarch64 (TODO make android for real) */
android = mapTestOnCross lib.systems.examples.aarch64-multiplatform linuxCommon;
aarch64-musl = mapTestOnCross lib.systems.examples.aarch64-multiplatform-musl linuxCommon; aarch64-musl = mapTestOnCross lib.systems.examples.aarch64-multiplatform-musl linuxCommon;
x86_64-musl = mapTestOnCross lib.systems.examples.musl64 linuxCommon; x86_64-musl = mapTestOnCross lib.systems.examples.musl64 linuxCommon;
/* Linux on Aarch64 */
android64 = mapTestOnCross lib.systems.examples.aarch64-android-prebuilt (linuxCommon // {
});
/* Cross-built bootstrap tools for every supported platform */ /* Cross-built bootstrap tools for every supported platform */
bootstrapTools = let bootstrapTools = let
tools = import ../stdenv/linux/make-bootstrap-tools-cross.nix { system = "x86_64-linux"; }; tools = import ../stdenv/linux/make-bootstrap-tools-cross.nix { system = "x86_64-linux"; };