From 902387e4807460f54db977a9c22ad20e5519f8de Mon Sep 17 00:00:00 2001 From: danakj Date: Fri, 13 Oct 2023 16:32:50 -0400 Subject: [PATCH 1/3] Allow the library consumer to specify the Android API level The build.rs script will use the C preprocessor to pull the API level out of C headers by default. But for build systems that wish to control each build step, and rely on remote compilation, this presents problems. Remove the requirement to run the C preprocessor if the API level is specified via `--cfg`: * android_api_at_least_0: No minimum API level is guaranteed. * android_api_at_least_21: The API level will be at least 21. --- build.rs | 59 ++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/build.rs b/build.rs index ed4e07a8..536c6ce5 100644 --- a/build.rs +++ b/build.rs @@ -1,5 +1,3 @@ -extern crate cc; - use std::env; use std::path::Path; @@ -11,14 +9,17 @@ pub fn main() { } } -// Used to detect the value of the `__ANDROID_API__` -// builtin #define -const MARKER: &str = "BACKTRACE_RS_ANDROID_APIVERSION"; -const ANDROID_API_C: &str = " +#[cfg(not(any(android_api_at_least_0, android_api_at_least_21)))] +fn android_version_from_c_headers() -> Option { + extern crate cc; + + // Used to detect the value of the `__ANDROID_API__` + // builtin #define + const MARKER: &str = "BACKTRACE_RS_ANDROID_APIVERSION"; + const ANDROID_API_C: &str = " BACKTRACE_RS_ANDROID_APIVERSION __ANDROID_API__ "; -fn build_android() { // Create `android-api.c` on demand. // Required to support calling this from the `std` build script. let out_dir = env::var_os("OUT_DIR").unwrap(); @@ -32,27 +33,55 @@ fn build_android() { "warning: android version detection failed while running C compiler: {}", e ); - return; + return None; } }; let expansion = match std::str::from_utf8(&expansion) { Ok(s) => s, - Err(_) => return, + Err(_) => return None, }; eprintln!("expanded android version detection:\n{}", expansion); let i = match expansion.find(MARKER) { Some(i) => i, - None => return, + None => return None, }; let version = match expansion[i + MARKER.len() + 1..].split_whitespace().next() { Some(s) => s, - None => return, + None => return None, }; - let version = match version.parse::() { - Ok(n) => n, - Err(_) => return, + match version.parse::() { + Ok(n) => Some(n), + Err(_) => None, + } +} + +/// Sets cfgs that depend on the Android API level. +/// +/// This depends on the use of a C preprocessor to find the API level in system +/// headers. For build systems that do not want to use a C processor inside the +/// execution of build scripts, the build system can specify the API level +/// through a `--cfg` flag. If any is set, the C preprocessor will not be used: +/// * android_api_at_least_0: No minimum API level is guaranteed. +/// * android_api_at_least_21: The API level will be at least 21. +fn build_android() { + let at_least_21; + #[cfg(android_api_at_least_0)] + { + at_least_21 = false; + } + #[cfg(android_api_at_least_21)] + { + at_least_21 = true; + } + #[cfg(not(any(android_api_at_least_0, android_api_at_least_21)))] + { + at_least_21 = { + let version = android_version_from_c_headers().unwrap_or_default(); + version >= 21 + } }; - if version >= 21 { + + if at_least_21 { println!("cargo:rustc-cfg=feature=\"dl_iterate_phdr\""); } } From c972b9e069175a0b34fd2b5d2fbd6d2855a8267f Mon Sep 17 00:00:00 2001 From: danakj Date: Fri, 13 Oct 2023 18:47:08 -0400 Subject: [PATCH 2/3] Use __ANDROID_API__ env var to communicate the API version The 'no_cc' cfg var controls whether cc is used or the env var. --- build.rs | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/build.rs b/build.rs index 536c6ce5..a8f3087a 100644 --- a/build.rs +++ b/build.rs @@ -9,7 +9,7 @@ pub fn main() { } } -#[cfg(not(any(android_api_at_least_0, android_api_at_least_21)))] +#[cfg(not(no_cc))] fn android_version_from_c_headers() -> Option { extern crate cc; @@ -29,10 +29,7 @@ BACKTRACE_RS_ANDROID_APIVERSION __ANDROID_API__ let expansion = match cc::Build::new().file(&android_api_c).try_expand() { Ok(result) => result, Err(e) => { - eprintln!( - "warning: android version detection failed while running C compiler: {}", - e - ); + eprintln!("warning: android version detection failed while running C compiler: {}", e); return None; } }; @@ -64,24 +61,21 @@ BACKTRACE_RS_ANDROID_APIVERSION __ANDROID_API__ /// * android_api_at_least_0: No minimum API level is guaranteed. /// * android_api_at_least_21: The API level will be at least 21. fn build_android() { - let at_least_21; - #[cfg(android_api_at_least_0)] - { - at_least_21 = false; - } - #[cfg(android_api_at_least_21)] - { - at_least_21 = true; - } - #[cfg(not(any(android_api_at_least_0, android_api_at_least_21)))] - { - at_least_21 = { - let version = android_version_from_c_headers().unwrap_or_default(); - version >= 21 + let version = { + #[cfg(no_cc)] + { + std::env::var("__ANDROID_API__") + .expect("__ANDROID_API__ must be set when building with `--cfg=no_cc`") + .parse::() + .expect("__ANDROID_API__ must be a number") + } + #[cfg(not(no_cc))] + { + android_version_from_c_headers().unwrap_or_default() } }; - if at_least_21 { + if version >= 21 { println!("cargo:rustc-cfg=feature=\"dl_iterate_phdr\""); } } From 73188ffb9b309e7edf1d1fa02a1fa34cb0989066 Mon Sep 17 00:00:00 2001 From: danakj Date: Fri, 13 Oct 2023 18:51:56 -0400 Subject: [PATCH 3/3] Update comment --- build.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/build.rs b/build.rs index a8f3087a..23cce3f1 100644 --- a/build.rs +++ b/build.rs @@ -29,7 +29,10 @@ BACKTRACE_RS_ANDROID_APIVERSION __ANDROID_API__ let expansion = match cc::Build::new().file(&android_api_c).try_expand() { Ok(result) => result, Err(e) => { - eprintln!("warning: android version detection failed while running C compiler: {}", e); + eprintln!( + "warning: android version detection failed while running C compiler: {}", + e + ); return None; } }; @@ -57,9 +60,8 @@ BACKTRACE_RS_ANDROID_APIVERSION __ANDROID_API__ /// This depends on the use of a C preprocessor to find the API level in system /// headers. For build systems that do not want to use a C processor inside the /// execution of build scripts, the build system can specify the API level -/// through a `--cfg` flag. If any is set, the C preprocessor will not be used: -/// * android_api_at_least_0: No minimum API level is guaranteed. -/// * android_api_at_least_21: The API level will be at least 21. +/// through the `__ANDROID_API__` environment variable. When `--cfg=no_cc` is +/// specified, the environment variable is used instead. fn build_android() { let version = { #[cfg(no_cc)]