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