3838 "x86" : "i686-linux-android" ,
3939}
4040
41+ CLANG_RT_ARCH_TARGETS = {
42+ "armv7" : "arm-android" ,
43+ "armv8" : "aarch64-android" ,
44+ "x86_64" : "x86_64-android" ,
45+ "x86" : "i686-android" ,
46+ }
47+
4148
4249def profile_to_rust_target (platform : str , arch : str , sdk : Optional [str ]) -> str :
4350 if platform == "Android" :
@@ -74,7 +81,7 @@ def get_android_bin_path() -> Path:
7481 tankerci .run (
7582 "conan" ,
7683 "install" ,
77- "android-ndk/r22b @" ,
84+ "android-ndk/r25c @" ,
7885 "--profile:host" ,
7986 "linux-x86_64" ,
8087 "--profile:build" ,
@@ -83,7 +90,7 @@ def get_android_bin_path() -> Path:
8390 _ , out = tankerci .run_captured (
8491 "conan" ,
8592 "info" ,
86- "android-ndk/r22b @" ,
93+ "android-ndk/r25c @" ,
8794 "--profile" ,
8895 "linux-x86_64" ,
8996 "--profile:build" ,
@@ -179,6 +186,65 @@ def _copy_includes(self, package_path: Path, depsConfig: DepsConfig) -> None:
179186 ui .info_2 (header , "->" , header_dest_dir )
180187 shutil .copy (header , header_dest_dir )
181188
189+ # Import only soft float128 builtins from compiler-rt
190+ # This is necessary on 64bit android archs, as Clang doesn't build them by default,
191+ # and Google's NDK distribution doesn't take care of that either...
192+ @staticmethod
193+ def _armerge_soft_float128_compiler_rt_builtins (compiler_rt_lib : Path , output_path : Path , env : dict [str , str ]):
194+ f128_builtins = [
195+ "__addtf3" ,
196+ "__subtf3" ,
197+ "__multf3" ,
198+ "__divtf3" ,
199+ "__negtf2" ,
200+ "__extenddftf2" ,
201+ "__extendsftf2" ,
202+ "__trunctfdf2" ,
203+ "__trunctfsf2" ,
204+ "__fixdfti" ,
205+ "__fixsfti" ,
206+ "__fixunsdfti" ,
207+ "__fixunssfti" ,
208+ "__fixtfdi" ,
209+ "__fixtfsi" ,
210+ "__fixtfti" ,
211+ "__fixunstfdi" ,
212+ "__fixunstfsi" ,
213+ "__fixunstfti" ,
214+ "__floattidf" ,
215+ "__floattisf" ,
216+ "__floatuntidf" ,
217+ "__floatuntisf" ,
218+ "__floatditf" ,
219+ "__floatsitf" ,
220+ "__floattitf" ,
221+ "__floatunditf" ,
222+ "__floatunsitf" ,
223+ "__floatuntitf" ,
224+ "__cmptf2" ,
225+ "__unordtf2" ,
226+ "__eqtf2" ,
227+ "__getf2" ,
228+ "__gttf2" ,
229+ "__letf2" ,
230+ "__lttf2" ,
231+ "__netf2" ,
232+ "__powitf2" ,
233+ "__multc3" ,
234+ "__divtc3" ,
235+ ]
236+ keep_symbol_args = [e for sym_name in f128_builtins for e in ['-k' , sym_name ]]
237+
238+ tankerci .run (
239+ "armerge" ,
240+ * keep_symbol_args ,
241+ "--output" ,
242+ str (output_path .relative_to (Path .cwd ())),
243+ str (compiler_rt_lib ),
244+ shell = False ,
245+ env = env ,
246+ )
247+
182248 def _merge_all_libs (
183249 self , depsConfig : DepsConfig , package_path : Path , native_path : Path
184250 ) -> None :
@@ -202,15 +268,31 @@ def _merge_all_libs(
202268 if self ._is_android_target :
203269 ndk_arch = NDK_ARCH_TARGETS [self .arch ]
204270 android_lib_path = android_bin_path / f"../sysroot/usr/lib/{ ndk_arch } "
271+
272+ # Starting with NDK r23, Google in its infinite wisdom has decided to make things more interesting
273+ # libgcc is gone, and now we use clang's libcxx and compiler-rt.
274+ # Unfortunately, the libcxx_static.a is currently missing soft float128 builtins for 64bit archs
275+ # (See https://reviews.llvm.org/D53608 and https://github.com/llvm/llvm-project/issues/51395)
276+ # It is possible to find those symbols in the separate libclang_rt.builtins libs
277+ # However, we can't pull in all of rt.builtins, or we will have duplicate symbols and fail linking
278+ if self .arch in ['x86_64' , 'armv8' ]:
279+ compiler_rt_arch = CLANG_RT_ARCH_TARGETS [self .arch ]
280+ compiler_rt_dir = android_bin_path / f"../lib64/clang/14.0.7/lib/linux/"
281+ compiler_rt_lib = compiler_rt_dir / f"libclang_rt.builtins-{ compiler_rt_arch } .a"
282+ out_path = cxx_package_libs / f"libclang_rt.builtins.float128-{ compiler_rt_arch } .a"
283+ self ._armerge_soft_float128_compiler_rt_builtins (compiler_rt_lib , out_path , env )
284+
205285 for lib in android_lib_path .glob ("*.a" ):
206286 # Rust already links some (non-C++) NDK libs, skip to avoid duplicate symbols
287+ # Also we already link rt builtins above, so we don't need/can't have these
207288 skipped = [
208289 "libc.a" ,
209290 "libm.a" ,
210291 "libdl.a" ,
211292 "libz.a" ,
212293 "libstdc++.a" ,
213294 "libunwind.a" ,
295+ "libcompiler_rt-extras.a" ,
214296 ]
215297 if lib .is_dir () or lib .name in skipped :
216298 continue
0 commit comments