Skip to content

Fix Android API gating: use weak symbols instead of __ANDROID_API__#229

Merged
bernardladenthin merged 1 commit into
mainfrom
claude/friendly-mayer-nkqkjl
Jun 13, 2026
Merged

Fix Android API gating: use weak symbols instead of __ANDROID_API__#229
bernardladenthin merged 1 commit into
mainfrom
claude/friendly-mayer-nkqkjl

Conversation

@bernardladenthin

Copy link
Copy Markdown
Owner

Summary

  • Replace the __ANDROID_API__=28 approach with __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ to properly gate Android bionic declarations on the dockcross cross-compiler toolchain
  • Remove -DANDROID_PLATFORM=android-28 from CI build commands, as it is ignored by the Debian-style cross-clang used by dockcross
  • Update documentation to explain why the weak-symbols approach is necessary and how it works

Motivation

The dockcross-android-arm64 image used by CI is not the Google NDK CMake toolchain—it's a Debian-style cross-clang (/usr/aarch64-linux-android/bin/clang) that:

  • Never sets the ANDROID / ANDROID_ABI CMake variables
  • Ignores -DANDROID_PLATFORM (CMake reports it as unused)
  • Predefines __ANDROID_API__ from its baked-in target triple

The old approach of bumping __ANDROID_API__=28 doesn't work on this toolchain because it clashes with the compiler's builtin definition and doesn't move __ANDROID_MIN_SDK_VERSION__, which is what bionic's __BIONIC_AVAILABILITY_GUARD(api) actually tests.

The working fix is __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__, which forces all guarded declarations to be visible and makes newer-API symbols weak references resolved at load time—present on every API-28+ device we target.

Changes

CMakeLists.txt:

  • Replace if(ANDROID_ABI) + add_compile_definitions(__ANDROID_API__=28) with a more robust detection that checks ANDROID, ANDROID_ABI, OS_NAME MATCHES "Android", or compiler path
  • Define __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ instead of __ANDROID_API__
  • Add detailed comments explaining why this approach is necessary and how bionic's availability guards work

.github/workflows/publish.yml:

  • Remove -DANDROID_PLATFORM=android-28 from both crosscompile-android-aarch64 and crosscompile-android-aarch64-opencl job steps

CLAUDE.md:

  • Update Android minimum API level section to document the weak-symbols approach
  • Remove references to updating -DANDROID_PLATFORM in CI
  • Add "How the API gate is satisfied" section explaining the toolchain limitations and the working solution
  • Update local sanity-build example to remove -DANDROID_PLATFORM=android-28

Test plan

  • CI is green on this branch (Android builds with dockcross-android-arm64 will now use the correct API gating mechanism)
  • The weak-symbols macro is never compiler-predefined, so defining it is clean and deterministic
  • Existing Android artifacts will continue to work on API-28+ devices

Checklist

  • I have read CONTRIBUTING.md and CODE_OF_CONDUCT.md
  • My commits follow Conventional Commits
  • No security-sensitive changes

https://claude.ai/code/session_013jKzHGzz97hiY6t7mp3MGr

The previous API-28 fix (c6bb70d) was a no-op on the current
dockcross-android-arm64 image and the Android build still failed compiling
mtmd-helper.cpp (vendor/sheredom/subprocess.h -> posix_spawn*).

Root cause: that image is NOT the Google NDK CMake toolchain but a
Debian-style cross-clang (/usr/aarch64-linux-android/bin/clang). It never sets
ANDROID/ANDROID_ABI, so the if(ANDROID_ABI)-guarded
add_compile_definitions(__ANDROID_API__=28) never ran; and it ignores
-DANDROID_PLATFORM=android-28 (CMake flags it as an unused variable). bionic
gates posix_spawn behind __BIONIC_AVAILABILITY_GUARD(28), which tests
__ANDROID_MIN_SDK_VERSION__ (predefined by clang from the target triple) — not
__ANDROID_API__ — so even applying that define would not have helped.

Fix: define __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ for the Android build.
That forces __BIONIC_AVAILABILITY_GUARD(api) to 1 for every level (declarations
always visible) and weak-links symbols newer than the baked-in min-SDK, which
resolve at load time on the API-28+ devices the artifact targets. It is never
compiler-predefined, so defining it is clean (no -Wmacro-redefined). It also
subsumes the getifaddrs (API 24) case. Detection no longer relies on
ANDROID_ABI: it uses OS_NAME MATCHES "Android" (CI passes -DOS_NAME=Linux-Android)
and the compiler path, plus ANDROID/ANDROID_ABI for a future NDK switch.

Also drop the inert -DANDROID_PLATFORM=android-28 from both Android jobs (it
only produced an unused-variable warning) and rewrite the CLAUDE.md Android
section to document the real mechanism.

https://claude.ai/code/session_013jKzHGzz97hiY6t7mp3MGr
@bernardladenthin bernardladenthin merged commit 740b09b into main Jun 13, 2026
17 of 26 checks passed
@bernardladenthin bernardladenthin deleted the claude/friendly-mayer-nkqkjl branch June 13, 2026 17:14
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.

2 participants