Skip to content

android: Compile native code against min_sdk, not target_sdk - #245

Closed
MarijnS95 wants to merge 1 commit into
masterfrom
fix-ndk-min-sdk-compile-level
Closed

android: Compile native code against min_sdk, not target_sdk#245
MarijnS95 wants to merge 1 commit into
masterfrom
fix-ndk-min-sdk-compile-level

Conversation

@MarijnS95

Copy link
Copy Markdown
Member

What

The Android NDK compile level — the <api> suffix on --target=<triple><api>, i.e. __ANDROID_API__ — gates which symbols the compiler treats as available. xbuild currently feeds target_sdk_version into it (BuildEnv::cargo_builduse_android_ndk), so with e.g. min_sdk 21 / target_sdk 34 the native .so is compiled at API 34.

Compiling above min_sdk_version lets native code emit strong references to symbols absent on the oldest supported device, which then fails to load at runtime — the exact compatibility breakage min_sdk_version exists to prevent. Only aapt / android.jar should track target_sdk_version (unchanged here).

Why it was wrong

Not a deliberate target-over-min choice: the API level wasn't set at all until #209; when the versioned --target was finally added it reused the pre-existing target_sdk_version variable already wired up for android.jar, inheriting the target level incidentally.

Prior art

cargo-apk got this right back in 2021 — rust-mobile/ndk#197 ("cargo-apk: Use min_sdk_version to select compiler target"), from before cargo-apk was split into its own repo — per the NDK docs.

Change

use_android_ndk now takes min_sdk_version (renamed param) and BuildEnv::cargo_build passes manifest.sdk.min_sdk_version instead of target_sdk_version. android.jar selection is untouched.

The NDK compile level — the `<api>` suffix on `--target=<triple><api>`,
i.e. `__ANDROID_API__` — gates which symbols the compiler treats as
available. Setting it to `target_sdk_version` lets native code link strong
references to symbols that don't exist on the oldest supported device,
which then fails to load at runtime: exactly the compatibility breakage
`min_sdk_version` exists to prevent. Only aapt and `android.jar` should
follow `target_sdk_version`.

This was never a deliberate target-over-min choice: the API level wasn't
set at all until #209, and when the versioned `--target` was finally added
it simply reused the pre-existing `target_sdk_version` variable that had
been wired up for `android.jar`, so the target-SDK level was inherited
incidentally from that earlier path.

cargo-apk got this right back in 2021 — rust-mobile/ndk#197
("cargo-apk: Use min_sdk_version to select compiler target"), pre-split
from cargo-apk's own repo, per
https://developer.android.com/ndk/guides/sdk-versions#minsdkversion

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@MarijnS95 MarijnS95 closed this Jul 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant