@@ -1370,6 +1370,12 @@ impl Build {
13701370 cmd. push_opt_unless_duplicate ( format ! ( "-O{}" , opt_level) . into ( ) ) ;
13711371 }
13721372
1373+ if cmd. family == ToolFamily :: Clang && target. contains ( "android" ) {
1374+ for arg in defines_for_android_compiler ( & cmd. path ) . into_iter ( ) {
1375+ cmd. push_cc_arg ( arg. into ( ) ) ;
1376+ }
1377+ }
1378+
13731379 if !target. contains ( "-ios" ) {
13741380 cmd. push_cc_arg ( "-ffunction-sections" . into ( ) ) ;
13751381 cmd. push_cc_arg ( "-fdata-sections" . into ( ) ) ;
@@ -1974,29 +1980,7 @@ impl Build {
19741980 format ! ( "{}.exe" , gnu)
19751981 }
19761982 } else if target. contains ( "android" ) {
1977- let target = target
1978- . replace ( "armv7neon" , "arm" )
1979- . replace ( "armv7" , "arm" )
1980- . replace ( "thumbv7neon" , "arm" )
1981- . replace ( "thumbv7" , "arm" ) ;
1982- let gnu_compiler = format ! ( "{}-{}" , target, gnu) ;
1983- let clang_compiler = format ! ( "{}-{}" , target, clang) ;
1984- // On Windows, the Android clang compiler is provided as a `.cmd` file instead
1985- // of a `.exe` file. `std::process::Command` won't run `.cmd` files unless the
1986- // `.cmd` is explicitly appended to the command name, so we do that here.
1987- let clang_compiler_cmd = format ! ( "{}-{}.cmd" , target, clang) ;
1988-
1989- // Check if gnu compiler is present
1990- // if not, use clang
1991- if Command :: new ( & gnu_compiler) . output ( ) . is_ok ( ) {
1992- gnu_compiler
1993- } else if host. contains ( "windows" )
1994- && Command :: new ( & clang_compiler_cmd) . output ( ) . is_ok ( )
1995- {
1996- clang_compiler_cmd
1997- } else {
1998- clang_compiler
1999- }
1983+ autodetect_android_compiler ( & target, & host, gnu, clang)
20001984 } else if target. contains ( "cloudabi" ) {
20011985 format ! ( "{}-{}" , target, traditional)
20021986 } else if target == "wasm32-wasi"
@@ -2722,3 +2706,79 @@ fn command_add_output_file(
27222706 cmd. arg ( "-o" ) . arg ( & dst) ;
27232707 }
27242708}
2709+
2710+ static NEW_STANDALONE_ANDROID_COMPILERS : [ & str ; 4 ] = [
2711+ "aarch64-linux-android21-clang" ,
2712+ "armv7a-linux-androideabi16-clang" ,
2713+ "i686-linux-android16-clang" ,
2714+ "x86_64-linux-android21-clang" ,
2715+ ] ;
2716+
2717+ fn defines_for_android_compiler ( clang_path : & Path ) -> Vec < & ' static str > {
2718+ match NEW_STANDALONE_ANDROID_COMPILERS . iter ( ) . find ( |x| {
2719+ let x: & OsStr = x. as_ref ( ) ;
2720+ x == clang_path. as_os_str ( )
2721+ } ) {
2722+ Some ( new_clang) => {
2723+ let mut ret = Vec :: with_capacity ( 2 ) ;
2724+ ret. push ( "-DANDROID" ) ;
2725+ if new_clang. contains ( "android21" ) {
2726+ ret. push ( "-D__ANDROID_API__=21" ) ;
2727+ } else if new_clang. contains ( "android16" ) || new_clang. contains ( "androideabi16" ) {
2728+ ret. push ( "-D__ANDROID_API__=16" ) ;
2729+ } else {
2730+ unreachable ! ( "Internal error: can not detect Android API level from compiler name" ) ;
2731+ }
2732+
2733+ ret
2734+ }
2735+ None => Vec :: new ( ) ,
2736+ }
2737+ }
2738+
2739+ fn autodetect_android_compiler ( target : & str , host : & str , gnu : & str , clang : & str ) -> String {
2740+ let new_clang_key = match target {
2741+ "aarch64-linux-android" => Some ( "aarch64" ) ,
2742+ "armv7-linux-androideabi" => Some ( "armv7a" ) ,
2743+ "i686-linux-android" => Some ( "i686" ) ,
2744+ "x86_64-linux-android" => Some ( "x86_64" ) ,
2745+ _ => None ,
2746+ } ;
2747+
2748+ let new_clang = new_clang_key
2749+ . map ( |key| {
2750+ NEW_STANDALONE_ANDROID_COMPILERS
2751+ . iter ( )
2752+ . find ( |x| x. starts_with ( key) )
2753+ } )
2754+ . unwrap_or ( None ) ;
2755+
2756+ if let Some ( new_clang) = new_clang {
2757+ if Command :: new ( new_clang) . output ( ) . is_ok ( ) {
2758+ return ( * new_clang) . into ( ) ;
2759+ }
2760+ }
2761+
2762+ let target = target
2763+ . replace ( "armv7neon" , "arm" )
2764+ . replace ( "armv7" , "arm" )
2765+ . replace ( "thumbv7neon" , "arm" )
2766+ . replace ( "thumbv7" , "arm" ) ;
2767+ let gnu_compiler = format ! ( "{}-{}" , target, gnu) ;
2768+ let clang_compiler = format ! ( "{}-{}" , target, clang) ;
2769+
2770+ // On Windows, the Android clang compiler is provided as a `.cmd` file instead
2771+ // of a `.exe` file. `std::process::Command` won't run `.cmd` files unless the
2772+ // `.cmd` is explicitly appended to the command name, so we do that here.
2773+ let clang_compiler_cmd = format ! ( "{}-{}.cmd" , target, clang) ;
2774+
2775+ // Check if gnu compiler is present
2776+ // if not, use clang
2777+ if Command :: new ( & gnu_compiler) . output ( ) . is_ok ( ) {
2778+ gnu_compiler
2779+ } else if host. contains ( "windows" ) && Command :: new ( & clang_compiler_cmd) . output ( ) . is_ok ( ) {
2780+ clang_compiler_cmd
2781+ } else {
2782+ clang_compiler
2783+ }
2784+ }
0 commit comments