diff --git a/xbuild/src/cargo/mod.rs b/xbuild/src/cargo/mod.rs index 7b916bda..b1a3aa30 100644 --- a/xbuild/src/cargo/mod.rs +++ b/xbuild/src/cargo/mod.rs @@ -287,11 +287,13 @@ impl CargoBuild { }) } - pub fn use_android_ndk(&mut self, path: &Path, target_sdk_version: u32) -> Result<()> { + pub fn use_android_ndk(&mut self, path: &Path, min_sdk_version: u32) -> Result<()> { let path = dunce::canonicalize(path)?; let ndk_triple = self.target.ndk_triple(); assert_eq!(Some(ndk_triple), self.triple); - let ndk_versioned_triple = format!("{ndk_triple}{target_sdk_version}"); + // The `` suffix sets `__ANDROID_API__`, the compile-time symbol + // availability floor — hence min, not target, SDK (see the call site). + let ndk_versioned_triple = format!("{ndk_triple}{min_sdk_version}"); self.cfg_tool(Tool::Cc, "clang"); self.cfg_tool(Tool::Cxx, "clang++"); self.cfg_tool(Tool::Ar, "llvm-ar"); @@ -300,11 +302,11 @@ impl CargoBuild { self.add_cflag(&format!("--target={ndk_versioned_triple}")); self.add_cxxflag("-stdlib=libc++"); let lib_dir = path.join("usr").join("lib").join(ndk_triple); - let sdk_lib_dir = lib_dir.join(target_sdk_version.to_string()); + let sdk_lib_dir = lib_dir.join(min_sdk_version.to_string()); anyhow::ensure!( sdk_lib_dir.exists(), "ndk doesn't support sdk version {}", - target_sdk_version + min_sdk_version ); self.use_ld("lld"); self.add_link_arg(&format!("--target={ndk_versioned_triple}")); diff --git a/xbuild/src/lib.rs b/xbuild/src/lib.rs index 8839068a..25b4bc87 100644 --- a/xbuild/src/lib.rs +++ b/xbuild/src/lib.rs @@ -677,14 +677,20 @@ impl BuildEnv { } if target.platform() == Platform::Android { let ndk = self.android_ndk(); - let target_sdk_version = self + // Native code is compiled against the min SDK/API level, not the + // target SDK: the NDK compile level gates symbol availability, so a + // level above min_sdk links symbols absent on the oldest supported + // device. aapt and `android.jar` track the target SDK separately. + // Matches cargo-apk: https://github.com/rust-mobile/ndk/pull/197 + // https://developer.android.com/ndk/guides/sdk-versions#minsdkversion + let min_sdk_version = self .config() .android() .manifest .sdk - .target_sdk_version + .min_sdk_version .unwrap(); - cargo.use_android_ndk(&ndk, target_sdk_version)?; + cargo.use_android_ndk(&ndk, min_sdk_version)?; } if target.platform() == Platform::Windows { let sdk = self.windows_sdk();