From 902387e4807460f54db977a9c22ad20e5519f8de Mon Sep 17 00:00:00 2001 From: danakj Date: Fri, 13 Oct 2023 16:32:50 -0400 Subject: [PATCH] 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\""); } }