Skip to content
This repository has been archived by the owner on Feb 24, 2023. It is now read-only.

Commit

Permalink
Build against the new unified toolchain in NDK r19
Browse files Browse the repository at this point in the history
  • Loading branch information
Chih-Hsuan Yen authored and Chih-Hsuan Yen committed Dec 8, 2018
1 parent 4095136 commit c8cc5a5
Show file tree
Hide file tree
Showing 6 changed files with 260 additions and 76 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Prerequisites
Building requires:

1. Linux or macOS. Arch Linux and macOS High Sierra tested.
2. Android NDK r17b installed and environment variable ``$ANDROID_NDK`` points to its root directory. NDK r14 to r16 may work yet not fully tested. NDk r13 or below is not supported.
2. Android NDK r19 beta 1 or newer installed and environment variable ``$ANDROID_NDK`` points to its root directory. NDk r18 or below is not supported.
3. git and python3.8 in $PATH. It's recommended to use the latest git-master to build python3.8. Here are some ways to install the python3.8:
* For Arch Linux users, install [python-git](https://aur.archlinux.org/packages/python-git) package from AUR
* For Homebrew users, run ```brew install python3 --HEAD```
Expand Down
230 changes: 230 additions & 0 deletions mk/openssl/android.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
diff --git a/Configurations/15-android.conf b/Configurations/15-android.conf
index 10342ed5e3..9c9ceb64df 100644
--- a/Configurations/15-android.conf
+++ b/Configurations/15-android.conf
@@ -3,147 +3,6 @@
# See NOTES.ANDROID for details, and don't miss platform-specific
# comments below...

-{
- use File::Spec::Functions;
-
- my $android_ndk = {};
- my %triplet = (
- arm => "arm-linux-androideabi",
- arm64 => "aarch64-linux-android",
- mips => "mipsel-linux-android",
- mips64 => "mips64el-linux-android",
- x86 => "i686-linux-android",
- x86_64 => "x86_64-linux-android",
- );
-
- sub android_ndk {
- unless (%$android_ndk) {
- if ($now_printing =~ m|^android|) {
- return $android_ndk = { bn_ops => "BN_AUTO" };
- }
-
- my $ndk = $ENV{ANDROID_NDK};
- die "\$ANDROID_NDK is not defined" if (!$ndk);
- if (!-d "$ndk/platforms" && !-f "$ndk/AndroidVersion.txt") {
- # $ndk/platforms is traditional "all-inclusive" NDK, while
- # $ndk/AndroidVersion.txt is so-called standalone toolchain
- # tailored for specific target down to API level.
- die "\$ANDROID_NDK=$ndk is invalid";
- }
- $ndk = canonpath($ndk);
-
- my $ndkver = undef;
-
- if (open my $fh, "<$ndk/source.properties") {
- local $_;
- while(<$fh>) {
- if (m|Pkg\.Revision\s*=\s*([0-9]+)|) {
- $ndkver = $1;
- last;
- }
- }
- close $fh;
- }
-
- my ($sysroot, $api, $arch);
-
- $config{target} =~ m|[^-]+-([^-]+)$|; # split on dash
- $arch = $1;
-
- if ($sysroot = $ENV{CROSS_SYSROOT}) {
- $sysroot =~ m|/android-([0-9]+)/arch-(\w+)/?$|;
- ($api, $arch) = ($1, $2);
- } elsif (-f "$ndk/AndroidVersion.txt") {
- $sysroot = "$ndk/sysroot";
- } else {
- $api = "*";
-
- # see if user passed -D__ANDROID_API__=N
- foreach (@{$useradd{CPPDEFINES}}, @{$user{CPPFLAGS}}) {
- if (m|__ANDROID_API__=([0-9]+)|) {
- $api = $1;
- last;
- }
- }
-
- # list available platforms (numerically)
- my @platforms = sort { $a =~ m/-([0-9]+)$/; my $aa = $1;
- $b =~ m/-([0-9]+)$/; $aa <=> $1;
- } glob("$ndk/platforms/android-$api");
- die "no $ndk/platforms/android-$api" if ($#platforms < 0);
-
- $sysroot = "@platforms[$#platforms]/arch-$arch";
- $sysroot =~ m|/android-([0-9]+)/arch-$arch|;
- $api = $1;
- }
- die "no sysroot=$sysroot" if (!-d $sysroot);
-
- my $triarch = $triplet{$arch};
- my $cflags;
- my $cppflags;
-
- # see if there is NDK clang on $PATH, "universal" or "standalone"
- if (which("clang") =~ m|^$ndk/.*/prebuilt/([^/]+)/|) {
- my $host=$1;
- # harmonize with gcc default
- my $arm = $ndkver > 16 ? "armv7a" : "armv5te";
- (my $tridefault = $triarch) =~ s/^arm-/$arm-/;
- (my $tritools = $triarch) =~ s/(?:x|i6)86(_64)?-.*/x86$1/;
- $cflags .= " -target $tridefault "
- . "-gcc-toolchain \$(ANDROID_NDK)/toolchains"
- . "/$tritools-4.9/prebuilt/$host";
- $user{CC} = "clang" if ($user{CC} !~ m|clang|);
- $user{CROSS_COMPILE} = undef;
- if (which("llvm-ar") =~ m|^$ndk/.*/prebuilt/([^/]+)/|) {
- $user{AR} = "llvm-ar";
- $user{ARFLAGS} = [ "rs" ];
- $user{RANLIB} = ":";
- }
- } elsif (-f "$ndk/AndroidVersion.txt") { #"standalone toolchain"
- my $cc = $user{CC} // "clang";
- # One can probably argue that both clang and gcc should be
- # probed, but support for "standalone toolchain" was added
- # *after* announcement that gcc is being phased out, so
- # favouring clang is considered adequate. Those who insist
- # have option to enforce test for gcc with CC=gcc.
- if (which("$triarch-$cc") !~ m|^$ndk|) {
- die "no NDK $triarch-$cc on \$PATH";
- }
- $user{CC} = $cc;
- $user{CROSS_COMPILE} = "$triarch-";
- } elsif ($user{CC} eq "clang") {
- die "no NDK clang on \$PATH";
- } else {
- if (which("$triarch-gcc") !~ m|^$ndk/.*/prebuilt/([^/]+)/|) {
- die "no NDK $triarch-gcc on \$PATH";
- }
- $cflags .= " -mandroid";
- $user{CROSS_COMPILE} = "$triarch-";
- }
-
- if (!-d "$sysroot/usr/include") {
- my $incroot = "$ndk/sysroot/usr/include";
- die "no $incroot" if (!-d $incroot);
- die "no $incroot/$triarch" if (!-d "$incroot/$triarch");
- $incroot =~ s|^$ndk/||;
- $cppflags = "-D__ANDROID_API__=$api";
- $cppflags .= " -isystem \$(ANDROID_NDK)/$incroot/$triarch";
- $cppflags .= " -isystem \$(ANDROID_NDK)/$incroot";
- }
-
- $sysroot =~ s|^$ndk/||;
- $android_ndk = {
- cflags => "$cflags --sysroot=\$(ANDROID_NDK)/$sysroot",
- cppflags => $cppflags,
- bn_ops => $arch =~ m/64$/ ? "SIXTY_FOUR_BIT_LONG"
- : "BN_LLONG",
- };
- }
-
- return $android_ndk;
- }
-}
-
my %targets = (
"android" => {
inherit_from => [ "linux-generic32" ],
@@ -158,10 +17,6 @@ my %targets = (
# systems are perfectly capable of executing binaries targeting
# Froyo. Keep in mind that in the nutshell Android builds are
# about JNI, i.e. shared libraries, not applications.
- cflags => add(sub { android_ndk()->{cflags} }),
- cppflags => add(sub { android_ndk()->{cppflags} }),
- cxxflags => add(sub { android_ndk()->{cflags} }),
- bn_ops => sub { android_ndk()->{bn_ops} },
bin_cflags => "-pie",
enable => [ ],
},
@@ -194,62 +49,23 @@ my %targets = (
# Newer NDK versions reportedly require additional -latomic.
#
inherit_from => [ "android", asm("armv4_asm") ],
- bn_ops => add("RC4_CHAR"),
+ bn_ops => "BN_LLONG RC4_CHAR",
},
"android-arm64" => {
inherit_from => [ "android", asm("aarch64_asm") ],
- bn_ops => add("RC4_CHAR"),
+ bn_ops => "SIXTY_FOUR_BIT_LONG RC4_CHAR",
perlasm_scheme => "linux64",
},

- "android-mips" => {
- inherit_from => [ "android", asm("mips32_asm") ],
- bn_ops => add("RC4_CHAR"),
- perlasm_scheme => "o32",
- },
- "android-mips64" => {
- ################################################################
- # You are more than likely have to specify target processor
- # on ./Configure command line. Trouble is that toolchain's
- # default is MIPS64r6 (at least in r10d), but there are no
- # such processors around (or they are too rare to spot one).
- # Actual problem is that MIPS64r6 is binary incompatible
- # with previous MIPS ISA versions, in sense that unlike
- # prior versions original MIPS binary code will fail.
- #
- inherit_from => [ "android", asm("mips64_asm") ],
- bn_ops => add("RC4_CHAR"),
- perlasm_scheme => "64",
- },
-
"android-x86" => {
inherit_from => [ "android", asm("x86_asm") ],
CFLAGS => add(picker(release => "-fomit-frame-pointer")),
- bn_ops => add("RC4_INT"),
+ bn_ops => "BN_LLONG RC4_INT",
perlasm_scheme => "android",
},
"android-x86_64" => {
inherit_from => [ "android", asm("x86_64_asm") ],
- bn_ops => add("RC4_INT"),
+ bn_ops => "SIXTY_FOUR_BIT_LONG RC4_INT",
perlasm_scheme => "elf",
},
-
- ####################################################################
- # Backward compatible targets, (might) requre $CROSS_SYSROOT
- #
- "android-armeabi" => {
- inherit_from => [ "android-arm" ],
- },
- "android64" => {
- inherit_from => [ "android" ],
- },
- "android64-aarch64" => {
- inherit_from => [ "android-arm64" ],
- },
- "android64-x86_64" => {
- inherit_from => [ "android-x86_64" ],
- },
- "android64-mips64" => {
- inherit_from => [ "android-mips64" ],
- },
);
21 changes: 7 additions & 14 deletions pybuild/arch.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,26 @@
class Arch:
ANDROID_COMPILER = '4.9'
ANDROID_TARGET: str
LLVM_TARGET: str
ANDROID_TOOLCHAIN_PREFIX: str

@property
def ANDROID_TOOLCHAIN(self) -> str:
return self.ANDROID_TOOLCHAIN_PREFIX + self.ANDROID_COMPILER
def binutils_prefix(self):
return self.ANDROID_TARGET


class arm(Arch):
ANDROID_TARGET = 'arm-linux-androideabi'
LLVM_TARGET = 'armv7-none-linux-androideabi'
ANDROID_TOOLCHAIN_PREFIX = 'arm-linux-androideabi-'
ANDROID_TARGET = 'armv7a-linux-androideabi'

@property
def binutils_prefix(self):
return 'arm-linux-androideabi'


class arm64(Arch):
ANDROID_TARGET = 'aarch64-linux-android'
LLVM_TARGET = 'aarch64-none-linux-android'
ANDROID_TOOLCHAIN_PREFIX = 'aarch64-linux-android-'


class x86(Arch):
ANDROID_TARGET = 'i686-linux-android'
LLVM_TARGET = 'i686-none-linux-android'
ANDROID_TOOLCHAIN_PREFIX = 'x86-'


class x86_64(Arch):
ANDROID_TARGET = 'x86_64-linux-android'
LLVM_TARGET = 'x86_64-none-linux-android'
ANDROID_TOOLCHAIN_PREFIX = 'x86_64-'
2 changes: 1 addition & 1 deletion pybuild/env.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
target_arch = 'arm64'
target_arch = 'arm'
android_api_level = 21

# Python optional modules.
Expand Down
56 changes: 17 additions & 39 deletions pybuild/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,54 +69,25 @@ def init_build_env(self) -> bool:
if self.env:
return False

HOST_OS = os.uname().sysname.lower()

if HOST_OS not in ('linux', 'darwin'):
raise Exception(f'Unsupported system {HOST_OS}')

self.TOOL_PREFIX = (self.ndk / 'toolchains' /
target_arch().ANDROID_TOOLCHAIN /
'prebuilt' / f'{HOST_OS}-x86_64')
CLANG_PREFIX = (self.ndk / 'toolchains' /
'llvm' / 'prebuilt' / f'{HOST_OS}-x86_64')

LLVM_BASE_FLAGS = [
'-target', target_arch().LLVM_TARGET,
'-gcc-toolchain', self.TOOL_PREFIX,
]

ARCH_SYSROOT = (self.ndk / 'platforms' /
f'android-{android_api_level()}' /
f'arch-{self.arch}' / 'usr')
UNIFIED_SYSROOT = self.ndk / 'sysroot' / 'usr'
CLANG_PREFIX = (self.unified_toolchain /
f'{target_arch().ANDROID_TARGET}{android_api_level()}')

cflags = ['-fPIC']

self.env.update({
'ANDROID_API_LEVEL': str(android_api_level()),

# Sysroots
'ARCH_SYSROOT': ARCH_SYSROOT,
'UNIFIED_SYSROOT': UNIFIED_SYSROOT,

# Compilers
'CC': f'{CLANG_PREFIX}/bin/clang',
'CXX': f'{CLANG_PREFIX}/bin/clang++',
'CPP': f'{CLANG_PREFIX}/bin/clang -E',
'CC': f'{CLANG_PREFIX}-clang',
'CXX': f'{CLANG_PREFIX}-clang++',
'CPP': f'{CLANG_PREFIX}-clang -E',

# Compiler flags
'CPPFLAGS': LLVM_BASE_FLAGS + [
'CPPFLAGS': [
f'-I{self.SYSROOT}/usr/include',
f'--sysroot={ARCH_SYSROOT}',
'-isystem', f'{UNIFIED_SYSROOT}/include',
'-isystem', f'{UNIFIED_SYSROOT}/include/{target_arch().ANDROID_TARGET}',
f'-D__ANDROID_API__={android_api_level()}',
],
'CFLAGS': cflags,
'CXXFLAGS': cflags,
'LDFLAGS': LLVM_BASE_FLAGS + [
'LDFLAGS': [
f'-L{self.SYSROOT}/usr/lib',
'--sysroot=' + str(ARCH_SYSROOT),
'-pie',
],

Expand All @@ -126,7 +97,7 @@ def init_build_env(self) -> bool:
})

for prog in ('ar', 'as', 'ld', 'objcopy', 'objdump', 'ranlib', 'strip', 'readelf'):
self.env[prog.upper()] = self.TOOL_PREFIX / 'bin' / f'{target_arch().ANDROID_TARGET}-{prog}'
self.env[prog.upper()] = self.unified_toolchain / f'{target_arch().binutils_prefix}-{prog}'

return True

Expand Down Expand Up @@ -156,8 +127,15 @@ def _check_ndk(self) -> None:
raise Exception('Requires environment variable $ANDROID_NDK')
ndk = pathlib.Path(ndk_path)

if not (ndk / 'sysroot').exists():
raise Exception('Requires Android NDK r14 beta1 or above')
HOST_OS = os.uname().sysname.lower()

if HOST_OS not in ('linux', 'darwin'):
raise Exception(f'Unsupported system {HOST_OS}')

self.unified_toolchain = ndk / 'toolchains' / 'llvm' / 'prebuilt' / f'{HOST_OS}-x86_64' / 'bin'

if not self.unified_toolchain.exists():
raise Exception('Requires Android NDK r19 or above')

self._ndk = ndk

Expand Down
Loading

0 comments on commit c8cc5a5

Please sign in to comment.