test/recipes/90-test_shlibload.t needs $target{shared_extension}
[openssl.git] / Configurations / 15-android.conf
index b5248580771297657f0de078b8fd4daead18cad3..10342ed5e3750d37161515604c22933a957dd5ed 100644 (file)
@@ -1,29 +1,11 @@
 #### Android...
 #
-# It takes *one* prior-set environment variable to make it work:
-#
-# ANDROID_NDK=/some/where/android-ndk-<ver>
-#
-# As well as PATH *adjusted* to cover ${CROSS_COMPILE}gcc and company.
-#
-# Note that it's different from original instructions that required to
-# set CROSS_SYSROOT [to $ANDROID_NDK/platforms/android-<api>/arch-<arch>]
-# and CROSS_COMPILE. CROSS_SYSROOT is still recognized [and even required
-# for some legacy targets], but if not set, it's detected and set to the
-# latest Android platform available with appointed NDK automatically. If
-# you need to target older platform, pass additional -D__ANDROID_API__=N
-# to Configure. For example, to compile for ICS on ARM with NDK 10d:
-#
-# ANDROID_NDK=/some/where/android-ndk-10d
-# PATH=$ANDROID_NDK/toolchains/arm-linux-androideabi-4.8/prebuild/linux-x86_64/bin:$PATH
-# [..]./Configure android-arm -D__ANDROID_API__=14
-#
-# One can engage clang by passing CC=clang to Configure. In such case
-# PATH needs even more adjustments to cover NDK's clang itself, as well
-# as unprefixed, yet target-specific ar and ranlib [or not, if you use
-# binutils-multiarch].
+# 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",
 
     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);
-            die "\$ANDROID_NDK=$ndk is invalid" if (!-d "$ndk/platforms");
+            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 $sysroot;
+            my $ndkver = undef;
 
-            if (!($sysroot = $ENV{CROSS_SYSROOT})) {
-                my $api = "*";
+            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}}) {
+                foreach (@{$useradd{CPPDEFINES}}, @{$user{CPPFLAGS}}) {
                     if (m|__ANDROID_API__=([0-9]+)|) {
                         $api = $1;
                         last;
                     }
                 }
 
-                # list available platforms [numerically]
+                # 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);
 
-                $config{target} =~ m|[^-]+-([^-]+)$|;   # split on dash
-                $sysroot = "@platforms[$#platforms]/arch-$1";
+                $sysroot = "@platforms[$#platforms]/arch-$arch";
+                $sysroot =~ m|/android-([0-9]+)/arch-$arch|;
+                $api = $1;
             }
             die "no sysroot=$sysroot"   if (!-d $sysroot);
 
-            $sysroot =~ m|/android-([0-9]+)/arch-(\w+)/?$|;
-            my ($api, $arch) = ($1, $2);
-
             my $triarch = $triplet{$arch};
-            my $cflags = "-Wa,--noexecstack";
+            my $cflags;
             my $cppflags;
 
-            # see if user passed CC=clang
-            if ($user{CC} eq "clang") {
-                if (which("clang") !~ m|^$ndk/.*/prebuilt/([^/]+)/|) {
-                    die "no NDK clang on \$PATH";
-                }
+            # 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 $tridefault = $triarch) =~ s|^arm-|armv5te-|;
-                $cflags .= " -target $tridefault -gcc-toolchain "
-                        . "\$(ANDROID_NDK)/toolchains/$triarch-4.9/prebuilt/$1";
+                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-";
             }
@@ -128,6 +163,7 @@ my %targets = (
         cxxflags         => add(sub { android_ndk()->{cflags} }),
         bn_ops           => sub { android_ndk()->{bn_ops} },
         bin_cflags       => "-pie",
+        enable           => [ ],
     },
     "android-arm" => {
         ################################################################
@@ -138,7 +174,7 @@ my %targets = (
         # ability to engage NEON is not constrained by ABI choice, nor
         # is your ability to call OpenSSL from your application code
         # compiled with floating-point ABI other than default 'soft'.
-        # [Latter thanks to __attribute__((pcs("aapcs"))) declaration.]
+        # (Latter thanks to __attribute__((pcs("aapcs"))) declaration.)
         # This means that choice of ARM libraries you provide in .apk
         # is driven by application needs. For example if application
         # itself benefits from NEON or is floating-point intensive, then
@@ -151,20 +187,24 @@ my %targets = (
         # in order to build "universal" binary and allow OpenSSL take
         # advantage of NEON when it's available.
         #
-        # Keep in mind that [just like with linux-armv4] we rely on
+        # Keep in mind that (just like with linux-armv4) we rely on
         # compiler defaults, which is not necessarily what you had
         # in mind, in which case you would have to pass additional
         # -march and/or -mfloat-abi flags. NDK defaults to armv5te.
+        # Newer NDK versions reportedly require additional -latomic.
         #
         inherit_from     => [ "android", asm("armv4_asm") ],
+        bn_ops           => add("RC4_CHAR"),
     },
     "android-arm64" => {
         inherit_from     => [ "android", asm("aarch64_asm") ],
+        bn_ops           => add("RC4_CHAR"),
         perlasm_scheme   => "linux64",
     },
 
     "android-mips" => {
         inherit_from     => [ "android", asm("mips32_asm") ],
+        bn_ops           => add("RC4_CHAR"),
         perlasm_scheme   => "o32",
     },
     "android-mips64" => {
@@ -178,6 +218,7 @@ my %targets = (
         # prior versions original MIPS binary code will fail.
         #
         inherit_from     => [ "android", asm("mips64_asm") ],
+        bn_ops           => add("RC4_CHAR"),
         perlasm_scheme   => "64",
     },
 
@@ -194,7 +235,7 @@ my %targets = (
     },
 
     ####################################################################
-    # Backward compatible targets, [might] requre $CROSS_SYSROOT
+    # Backward compatible targets, (might) requre $CROSS_SYSROOT
     #
     "android-armeabi" => {
         inherit_from     => [ "android-arm" ],