11use std:: env;
2+ use std:: path:: Path ;
23
34fn main ( ) {
45 println ! ( "cargo:rerun-if-changed=build.rs" ) ;
@@ -20,7 +21,6 @@ fn main() {
2021
2122 println ! ( "cargo:rustc-check-cfg=cfg(restricted_std)" ) ;
2223 if target_os == "linux"
23- || target_os == "android"
2424 || target_os == "netbsd"
2525 || target_os == "dragonfly"
2626 || target_os == "openbsd"
@@ -58,6 +58,9 @@ fn main() {
5858 || env:: var ( "RUSTC_BOOTSTRAP_SYNTHETIC_TARGET" ) . is_ok ( )
5959 {
6060 // These platforms don't have any special requirements.
61+ } else if target_os == "android" {
62+ // If ANDROID_API >= 21, enable `dl_iterate_phdr` feature.
63+ build_android ( ) ;
6164 } else {
6265 // This is for Cargo's build-std support, to mark std as unstable for
6366 // typically no_std platforms.
@@ -183,3 +186,45 @@ fn main() {
183186 println ! ( "cargo:rustc-cfg=reliable_f128_math" ) ;
184187 }
185188}
189+
190+ fn build_android ( ) {
191+ // Used to detect the value of the `__ANDROID_API__`
192+ // builtin #define
193+ const MARKER : & str = "BACKTRACE_RS_ANDROID_APIVERSION" ;
194+ const ANDROID_API_C : & str = "
195+ BACKTRACE_RS_ANDROID_APIVERSION __ANDROID_API__
196+ " ;
197+
198+ // Create `android-api.c` on demand.
199+ let out_dir = env:: var_os ( "OUT_DIR" ) . unwrap ( ) ;
200+ let android_api_c = Path :: new ( & out_dir) . join ( "android-api.c" ) ;
201+ std:: fs:: write ( & android_api_c, ANDROID_API_C ) . unwrap ( ) ;
202+
203+ let expansion = match cc:: Build :: new ( ) . file ( & android_api_c) . try_expand ( ) {
204+ Ok ( result) => result,
205+ Err ( e) => {
206+ eprintln ! ( "warning: android version detection failed while running C compiler: {e}" ) ;
207+ return ;
208+ }
209+ } ;
210+ let expansion = match std:: str:: from_utf8 ( & expansion) {
211+ Ok ( s) => s,
212+ Err ( _) => return ,
213+ } ;
214+ eprintln ! ( "expanded android version detection:\n {expansion}" ) ;
215+ let i = match expansion. find ( MARKER ) {
216+ Some ( i) => i,
217+ None => return ,
218+ } ;
219+ let version = match expansion[ i + MARKER . len ( ) + 1 ..] . split_whitespace ( ) . next ( ) {
220+ Some ( s) => s,
221+ None => return ,
222+ } ;
223+ let version = match version. parse :: < u32 > ( ) {
224+ Ok ( n) => n,
225+ Err ( _) => return ,
226+ } ;
227+ if version >= 21 {
228+ println ! ( "cargo:rustc-cfg=feature=\" dl_iterate_phdr\" " ) ;
229+ }
230+ }
0 commit comments