Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 58 additions & 8 deletions src/build_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use ignore::overrides::{Override, OverrideBuilder};
use lddtree::Library;
use normpath::PathExt;
use platform_info::*;
use regex::Regex;
use sha2::{Digest, Sha256};
use std::borrow::Borrow;
use std::collections::{BTreeMap, HashSet};
Expand Down Expand Up @@ -550,16 +551,28 @@ impl BuildContext {
// Linux
(Os::Linux, _) => {
let arch = target.get_platform_arch()?;
let mut platform_tags = platform_tags.to_vec();
platform_tags.sort();
let mut tags = vec![];
for platform_tag in platform_tags {
tags.push(format!("{platform_tag}_{arch}"));
for alias in platform_tag.aliases() {
tags.push(format!("{alias}_{arch}"));
if target.target_triple().contains("android") {
let android_arch = match arch.as_str() {
"armv7l" => "armeabi_v7a",
"aarch64" => "arm64_v8a",
"i686" => "x86",
"x86_64" => "x86_64",
_ => bail!("Unsupported Android architecture: {}", arch),
};
let api_level = find_android_api_level(target.target_triple(), &self.manifest_path)?;
format!("android_{}_{}", api_level, android_arch)
Comment on lines +554 to +563
Copy link

Copilot AI Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Android platform tag generation logic lacks test coverage. The existing test module in this file includes tests for other platform tag generation (e.g., test_macosx_deployment_target, test_iphoneos_deployment_target). Consider adding similar tests for Android platform tags that verify:

  • Correct tag format generation for different architectures (armv7l, aarch64, i686, x86_64)
  • Integration with API level detection
  • Error handling for unsupported architectures

Copilot uses AI. Check for mistakes.
} else {
let mut platform_tags = platform_tags.to_vec();
platform_tags.sort();
let mut tags = vec![];
for platform_tag in platform_tags {
tags.push(format!("{platform_tag}_{arch}"));
for alias in platform_tag.aliases() {
tags.push(format!("{alias}_{arch}"));
}
}
tags.join(".")
}
tags.join(".")
}
// macOS
(Os::Macos, Arch::X86_64) | (Os::Macos, Arch::Aarch64) => {
Expand Down Expand Up @@ -1297,6 +1310,43 @@ fn emcc_version() -> Result<String> {
Ok(trimmed.into())
}

fn find_android_api_level(target_triple: &str, manifest_path: &Path) -> Result<String> {
if let Ok(val) = env::var("ANDROID_API_LEVEL") {
return Ok(val);
}

let mut clues = Vec::new();

// 1. Linker from cargo-config2
if let Some(manifest_dir) = manifest_path.parent() {
if let Ok(config) = cargo_config2::Config::load_with_cwd(manifest_dir) {
if let Ok(Some(linker)) = config.linker(target_triple) {
clues.push(linker.to_string_lossy().into_owned());
}
}
}

// 2. CC env vars
if let Ok(cc) = env::var(format!("CC_{}", target_triple.replace('-', "_"))) {
clues.push(cc);
}
if let Ok(cc) = env::var("CC") {
clues.push(cc);
}

// Search for android(\d+) in clues
let re = Regex::new(r"android(\d+)")?;
Copy link

Copilot AI Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The regex pattern is compiled on every call to find_android_api_level. This function is called during wheel tag generation, and compiling a regex repeatedly is inefficient. Consider using once_cell::sync::Lazy to compile the regex once and reuse it, similar to the pattern used elsewhere in the codebase (e.g., IS_LIBPYTHON in src/auditwheel/audit.rs).

Copilot uses AI. Check for mistakes.
for clue in clues {
if let Some(caps) = re.captures(&clue) {
return Ok(caps[1].to_string());
}
}
Comment on lines +1318 to +1343
Copy link

Copilot AI Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The clues vector is used to collect potential sources for the API level, but if all collection operations fail silently (e.g., manifest_path.parent() returns None, config loading fails, environment variables are not set), the function will always bail with a generic error. Consider adding debug logging to help users understand which detection methods were attempted and why they failed. This would make debugging configuration issues much easier.

Copilot uses AI. Check for mistakes.

bail!(
"Failed to determine Android API level. Please set the ANDROID_API_LEVEL environment variable."
);
}
Comment on lines +1313 to +1348
Copy link

Copilot AI Dec 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new find_android_api_level function lacks test coverage. Given that the codebase has comprehensive tests (as seen in the mod tests section of this file), this function should include tests for:

  • API level detection from ANDROID_API_LEVEL environment variable
  • API level extraction from linker paths
  • API level extraction from CC environment variables
  • Error handling when no API level can be determined
  • Regex matching behavior with various toolchain path formats

Copilot uses AI. Check for mistakes.

/// Returns a DateTime representing the value SOURCE_DATE_EPOCH environment variable
/// Note that the earliest timestamp a zip file can represent is 1980-01-01
fn zip_mtime() -> DateTime {
Expand Down
Loading