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