Skip to content

Commit

Permalink
Allow the library consumer to specify the Android API level
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
danakj committed Oct 13, 2023
1 parent 036d490 commit 902387e
Showing 1 changed file with 44 additions and 15 deletions.
59 changes: 44 additions & 15 deletions build.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
extern crate cc;

use std::env;
use std::path::Path;

Expand All @@ -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<u32> {
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();
Expand All @@ -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::<u32>() {
Ok(n) => n,
Err(_) => return,
match version.parse::<u32>() {
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\"");
}
}

0 comments on commit 902387e

Please sign in to comment.