Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 1 | #### Android... |
| 2 | # |
Andy Polyakov | df3a155 | 2018-03-17 10:59:57 +0100 | [diff] [blame] | 3 | # See NOTES.ANDROID for details, and don't miss platform-specific |
Andy Polyakov | f39276f | 2018-03-16 12:14:28 +0100 | [diff] [blame] | 4 | # comments below... |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 5 | |
| 6 | { |
| 7 | my $android_ndk = {}; |
| 8 | my %triplet = ( |
| 9 | arm => "arm-linux-androideabi", |
| 10 | arm64 => "aarch64-linux-android", |
| 11 | mips => "mipsel-linux-android", |
| 12 | mips64 => "mips64el-linux-android", |
| 13 | x86 => "i686-linux-android", |
| 14 | x86_64 => "x86_64-linux-android", |
| 15 | ); |
| 16 | |
| 17 | sub android_ndk { |
| 18 | unless (%$android_ndk) { |
Andy Polyakov | f770d75 | 2018-03-26 12:35:57 +0200 | [diff] [blame] | 19 | if ($now_printing =~ m|^android|) { |
| 20 | return $android_ndk = { bn_ops => "BN_AUTO" }; |
| 21 | } |
| 22 | |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 23 | my $ndk = $ENV{ANDROID_NDK}; |
| 24 | die "\$ANDROID_NDK is not defined" if (!$ndk); |
| 25 | die "\$ANDROID_NDK=$ndk is invalid" if (!-d "$ndk/platforms"); |
| 26 | |
Andy Polyakov | df3a155 | 2018-03-17 10:59:57 +0100 | [diff] [blame] | 27 | my $ndkver = undef; |
| 28 | |
| 29 | if (open my $fh, "<$ndk/source.properties") { |
| 30 | local $_; |
| 31 | while(<$fh>) { |
| 32 | if (m|Pkg\.Revision\s*=\s*([0-9]+)|) { |
| 33 | $ndkver = $1; |
| 34 | last; |
| 35 | } |
| 36 | } |
| 37 | close $fh; |
| 38 | } |
| 39 | |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 40 | my $sysroot; |
| 41 | |
| 42 | if (!($sysroot = $ENV{CROSS_SYSROOT})) { |
| 43 | my $api = "*"; |
| 44 | |
| 45 | # see if user passed -D__ANDROID_API__=N |
Andy Polyakov | df3a155 | 2018-03-17 10:59:57 +0100 | [diff] [blame] | 46 | foreach (@{$useradd{CPPDEFINES}}, @{$user{CPPFLAGS}}) { |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 47 | if (m|__ANDROID_API__=([0-9]+)|) { |
| 48 | $api = $1; |
| 49 | last; |
| 50 | } |
| 51 | } |
| 52 | |
Andy Polyakov | f39276f | 2018-03-16 12:14:28 +0100 | [diff] [blame] | 53 | # list available platforms (numerically) |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 54 | my @platforms = sort { $a =~ m/-([0-9]+)$/; my $aa = $1; |
| 55 | $b =~ m/-([0-9]+)$/; $aa <=> $1; |
| 56 | } glob("$ndk/platforms/android-$api"); |
| 57 | die "no $ndk/platforms/android-$api" if ($#platforms < 0); |
| 58 | |
| 59 | $config{target} =~ m|[^-]+-([^-]+)$|; # split on dash |
| 60 | $sysroot = "@platforms[$#platforms]/arch-$1"; |
| 61 | } |
| 62 | die "no sysroot=$sysroot" if (!-d $sysroot); |
| 63 | |
| 64 | $sysroot =~ m|/android-([0-9]+)/arch-(\w+)/?$|; |
| 65 | my ($api, $arch) = ($1, $2); |
| 66 | |
| 67 | my $triarch = $triplet{$arch}; |
Andy Polyakov | 0ad4078 | 2018-05-04 14:06:44 +0200 | [diff] [blame] | 68 | my $cflags; |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 69 | my $cppflags; |
| 70 | |
Andy Polyakov | df3a155 | 2018-03-17 10:59:57 +0100 | [diff] [blame] | 71 | # see if there is NDK clang on $PATH |
| 72 | if (which("clang") =~ m|^$ndk/.*/prebuilt/([^/]+)/|) { |
Andy Polyakov | f41c867 | 2018-03-14 09:45:31 +0100 | [diff] [blame] | 73 | my $host=$1; |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 74 | # harmonize with gcc default |
Andy Polyakov | df3a155 | 2018-03-17 10:59:57 +0100 | [diff] [blame] | 75 | my $arm = $ndkver > 16 ? "armv7a" : "armv5te"; |
| 76 | (my $tridefault = $triarch) =~ s/^arm-/$arm-/; |
Andy Polyakov | f41c867 | 2018-03-14 09:45:31 +0100 | [diff] [blame] | 77 | (my $tritools = $triarch) =~ s/(?:x|i6)86(_64)?-.*/x86$1/; |
| 78 | $cflags .= " -target $tridefault " |
| 79 | . "-gcc-toolchain \$(ANDROID_NDK)/toolchains" |
| 80 | . "/$tritools-4.9/prebuilt/$host"; |
Andy Polyakov | df3a155 | 2018-03-17 10:59:57 +0100 | [diff] [blame] | 81 | $user{CC} = "clang" if ($user{CC} !~ m|clang|); |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 82 | $user{CROSS_COMPILE} = undef; |
Andy Polyakov | df3a155 | 2018-03-17 10:59:57 +0100 | [diff] [blame] | 83 | } elsif ($user{CC} eq "clang") { |
| 84 | die "no NDK clang on \$PATH"; |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 85 | } else { |
Andy Polyakov | df3a155 | 2018-03-17 10:59:57 +0100 | [diff] [blame] | 86 | if (which("$triarch-gcc") !~ m|^$ndk/.*/prebuilt/([^/]+)/|) { |
| 87 | die "no NDK $triarch-gcc on \$PATH"; |
| 88 | } |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 89 | $cflags .= " -mandroid"; |
| 90 | $user{CROSS_COMPILE} = "$triarch-"; |
| 91 | } |
| 92 | |
| 93 | if (!-d "$sysroot/usr/include") { |
| 94 | my $incroot = "$ndk/sysroot/usr/include"; |
| 95 | die "no $incroot" if (!-d $incroot); |
| 96 | die "no $incroot/$triarch" if (!-d "$incroot/$triarch"); |
| 97 | $incroot =~ s|^$ndk/||; |
| 98 | $cppflags = "-D__ANDROID_API__=$api"; |
| 99 | $cppflags .= " -isystem \$(ANDROID_NDK)/$incroot/$triarch"; |
| 100 | $cppflags .= " -isystem \$(ANDROID_NDK)/$incroot"; |
| 101 | } |
| 102 | |
| 103 | $sysroot =~ s|^$ndk/||; |
| 104 | $android_ndk = { |
| 105 | cflags => "$cflags --sysroot=\$(ANDROID_NDK)/$sysroot", |
| 106 | cppflags => $cppflags, |
| 107 | bn_ops => $arch =~ m/64$/ ? "SIXTY_FOUR_BIT_LONG" |
| 108 | : "BN_LLONG", |
| 109 | }; |
| 110 | } |
| 111 | |
| 112 | return $android_ndk; |
| 113 | } |
| 114 | } |
| 115 | |
| 116 | my %targets = ( |
| 117 | "android" => { |
| 118 | inherit_from => [ "linux-generic32" ], |
| 119 | template => 1, |
| 120 | ################################################################ |
| 121 | # Special note about -pie. The underlying reason is that |
| 122 | # Lollipop refuses to run non-PIE. But what about older systems |
| 123 | # and NDKs? -fPIC was never problem, so the only concern is -pie. |
| 124 | # Older toolchains, e.g. r4, appear to handle it and binaries |
| 125 | # turn out mostly functional. "Mostly" means that oldest |
| 126 | # Androids, such as Froyo, fail to handle executable, but newer |
| 127 | # systems are perfectly capable of executing binaries targeting |
| 128 | # Froyo. Keep in mind that in the nutshell Android builds are |
| 129 | # about JNI, i.e. shared libraries, not applications. |
| 130 | cflags => add(sub { android_ndk()->{cflags} }), |
| 131 | cppflags => add(sub { android_ndk()->{cppflags} }), |
| 132 | cxxflags => add(sub { android_ndk()->{cflags} }), |
| 133 | bn_ops => sub { android_ndk()->{bn_ops} }, |
| 134 | bin_cflags => "-pie", |
Matt Caswell | ac98d38 | 2018-04-23 15:37:03 +0100 | [diff] [blame] | 135 | enable => [ ], |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 136 | }, |
| 137 | "android-arm" => { |
| 138 | ################################################################ |
| 139 | # Contemporary Android applications can provide multiple JNI |
| 140 | # providers in .apk, targeting multiple architectures. Among |
| 141 | # them there is "place" for two ARM flavours: generic eabi and |
| 142 | # armv7-a/hard-float. However, it should be noted that OpenSSL's |
| 143 | # ability to engage NEON is not constrained by ABI choice, nor |
| 144 | # is your ability to call OpenSSL from your application code |
| 145 | # compiled with floating-point ABI other than default 'soft'. |
Andy Polyakov | f39276f | 2018-03-16 12:14:28 +0100 | [diff] [blame] | 146 | # (Latter thanks to __attribute__((pcs("aapcs"))) declaration.) |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 147 | # This means that choice of ARM libraries you provide in .apk |
| 148 | # is driven by application needs. For example if application |
| 149 | # itself benefits from NEON or is floating-point intensive, then |
| 150 | # it might be appropriate to provide both libraries. Otherwise |
| 151 | # just generic eabi would do. But in latter case it would be |
| 152 | # appropriate to |
| 153 | # |
| 154 | # ./Configure android-arm -D__ARM_MAX_ARCH__=8 |
| 155 | # |
| 156 | # in order to build "universal" binary and allow OpenSSL take |
| 157 | # advantage of NEON when it's available. |
| 158 | # |
Andy Polyakov | f39276f | 2018-03-16 12:14:28 +0100 | [diff] [blame] | 159 | # Keep in mind that (just like with linux-armv4) we rely on |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 160 | # compiler defaults, which is not necessarily what you had |
| 161 | # in mind, in which case you would have to pass additional |
| 162 | # -march and/or -mfloat-abi flags. NDK defaults to armv5te. |
Andy Polyakov | df3a155 | 2018-03-17 10:59:57 +0100 | [diff] [blame] | 163 | # Newer NDK versions reportedly require additional -latomic. |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 164 | # |
| 165 | inherit_from => [ "android", asm("armv4_asm") ], |
Andy Polyakov | 87ba25e | 2018-03-14 17:30:22 +0100 | [diff] [blame] | 166 | bn_ops => add("RC4_CHAR"), |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 167 | }, |
| 168 | "android-arm64" => { |
| 169 | inherit_from => [ "android", asm("aarch64_asm") ], |
Andy Polyakov | 87ba25e | 2018-03-14 17:30:22 +0100 | [diff] [blame] | 170 | bn_ops => add("RC4_CHAR"), |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 171 | perlasm_scheme => "linux64", |
| 172 | }, |
| 173 | |
| 174 | "android-mips" => { |
| 175 | inherit_from => [ "android", asm("mips32_asm") ], |
Andy Polyakov | 87ba25e | 2018-03-14 17:30:22 +0100 | [diff] [blame] | 176 | bn_ops => add("RC4_CHAR"), |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 177 | perlasm_scheme => "o32", |
| 178 | }, |
| 179 | "android-mips64" => { |
| 180 | ################################################################ |
| 181 | # You are more than likely have to specify target processor |
| 182 | # on ./Configure command line. Trouble is that toolchain's |
| 183 | # default is MIPS64r6 (at least in r10d), but there are no |
| 184 | # such processors around (or they are too rare to spot one). |
| 185 | # Actual problem is that MIPS64r6 is binary incompatible |
| 186 | # with previous MIPS ISA versions, in sense that unlike |
| 187 | # prior versions original MIPS binary code will fail. |
| 188 | # |
| 189 | inherit_from => [ "android", asm("mips64_asm") ], |
Andy Polyakov | 87ba25e | 2018-03-14 17:30:22 +0100 | [diff] [blame] | 190 | bn_ops => add("RC4_CHAR"), |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 191 | perlasm_scheme => "64", |
| 192 | }, |
| 193 | |
| 194 | "android-x86" => { |
| 195 | inherit_from => [ "android", asm("x86_asm") ], |
| 196 | CFLAGS => add(picker(release => "-fomit-frame-pointer")), |
| 197 | bn_ops => add("RC4_INT"), |
| 198 | perlasm_scheme => "android", |
| 199 | }, |
| 200 | "android-x86_64" => { |
| 201 | inherit_from => [ "android", asm("x86_64_asm") ], |
| 202 | bn_ops => add("RC4_INT"), |
| 203 | perlasm_scheme => "elf", |
| 204 | }, |
| 205 | |
| 206 | #################################################################### |
Andy Polyakov | f39276f | 2018-03-16 12:14:28 +0100 | [diff] [blame] | 207 | # Backward compatible targets, (might) requre $CROSS_SYSROOT |
Andy Polyakov | ebea0f3 | 2018-03-11 19:08:56 +0100 | [diff] [blame] | 208 | # |
| 209 | "android-armeabi" => { |
| 210 | inherit_from => [ "android-arm" ], |
| 211 | }, |
| 212 | "android64" => { |
| 213 | inherit_from => [ "android" ], |
| 214 | }, |
| 215 | "android64-aarch64" => { |
| 216 | inherit_from => [ "android-arm64" ], |
| 217 | }, |
| 218 | "android64-x86_64" => { |
| 219 | inherit_from => [ "android-x86_64" ], |
| 220 | }, |
| 221 | "android64-mips64" => { |
| 222 | inherit_from => [ "android-mips64" ], |
| 223 | }, |
| 224 | ); |