Skip to content

Keith's PR #1827 changes (for review) - #6

Closed
AttilaTheFun wants to merge 8 commits into
android-supportfrom
android-keith-review
Closed

Keith's PR #1827 changes (for review)#6
AttilaTheFun wants to merge 8 commits into
android-supportfrom
android-keith-review

Conversation

@AttilaTheFun

Copy link
Copy Markdown
Owner

Keith's changes from his fork (bazelbuild#1827 / the gist) applied on
top of our android-support tip, so the delta is reviewable here. Squashed into
one commit because the upstream history is noisy.

The headline change: static libc++ instead of shared libc++_shared.so — he
drops -lstdc++, re-adds --exclude-libs,ALL + -export-dynamic, deletes
select_android_runtime_lib and the example's libcxx targets. JNI symbols stay
exported via -export-dynamic + rules_android_ndk's --undefined-glob.

Other notable moves:

  • Validation → real test/ test rules (android_so_abi_test /
    android_apk_contents_test) against a self-contained fixture APK; uses
    llvm-nm + llvm-readelf, generalized needed/not-needed lists.
  • Root MODULE.bazel is now entirely Android-free — all wiring moved into
    android.MODULE.bazel (+ a new rules_android_ndk dep/override).
  • Reverted our worker DEVELOPER_DIR guard (back to unconditional).
  • Dropped the unused swift_sdk_linker_inputs; added armv7; enabled the example
    on Linux CI; hardened run.sh's boot check; trimmed docs.

Things to confirm with keith (see ~/Downloads/keith_pr1827_changes.md for the
full writeup):

  1. Static vs. shared libc++ — opposite of what we landed; intended tradeoff?
  2. The DEVELOPER_DIR revert — relies on it being set (CI-only) or genuinely
    unneeded?
  3. register_toolchains("@androidndk//:all") appears twice in
    android.MODULE.bazel — looks accidental.

AttilaTheFun and others added 8 commits June 24, 2026 20:25
Add `swift.android_sdk`, which downloads the swift.org Android Swift SDK bundle
and defines a Swift toolchain targeting {aarch64,x86_64}-unknown-linux-android.
`swift_binary(linkshared = True)` produces a JNI lib<name>.so whose entry points
are written entirely in Swift; examples/cross_compilation builds one.

rules_swift does not fetch or manage the Android NDK. C/C++ compilation and
linking go through a separately registered Android C++ cc toolchain (e.g.
@androidndk//:all from hermetic_android_toolchains), and the Swift toolchain
reads that toolchain's sysroot at analysis time. Register one alongside the
Swift toolchain.

A few NDK-integration details handled in the Swift toolchain rule:
- rules_android_ndk's CcToolchainInfo.sysroot reports the clang dir, not the
  sysroot, so we derive the sysroot from the toolchain's files.
- The Swift link action drives the NDK clang directly and bypasses the cc
  toolchain's sysroot/runtime-lib link features, so for Android we add --sysroot
  and stage libc++_shared.so (which the NDK clang links by default) into the
  link ourselves.
- select_android_runtime_lib selects libc++_shared.so from the resolved cc
  toolchain for APK packaging.

Verified end to end: //examples/cross_compilation:libSwiftJNI.so builds a real
aarch64 Android .so linked through @androidndk, and a downstream app packages it
into a working APK alongside libc++_shared.so.
…Swift)

The cross_compilation example previously built only the JNI .so and documented
(in prose) how a downstream module would package it into an APK. Replace that
recipe with a real, building android_binary that runs on a device/emulator and
shows the Swift greeting on screen — a far more compelling demonstration of
integrating Swift into an Android app.

It's packaged the real-world way, with rules_android (android_binary) and
rules_kotlin (kt_android_library). The one rules_swift-specific detail: the
swift_binary(linkshared) .so arrives via DefaultInfo (not CcInfo), so it's
wrapped in a cc_library to feed android_binary's per-ABI native split; libc++
is selected via select_android_runtime_lib the same way.

rules_android/rules_kotlin/rules_java/rules_jvm_external are all dev_dependency
deps (with a pinned Maven lock and the hermetic @AndroidSDK), so consumers of
rules_swift are unaffected. CI builds the APK via a build_test under
--config=android_example (scoped flags; the rest of the build is untouched).

Claude-Session: https://claude.ai/code/session_01SmG1kqA3qB4WsLGU2xavuJ
Toolchain:
- Keep file_prefix_map enabled for Android (hermetic working-dir remap) instead
  of disabling it; the worker only requires DEVELOPER_DIR for the Apple
  developer-dir remap, so guard that remap on DEVELOPER_DIR being set (a cross
  compile on a macOS host has none). Fixes non-hermetic debug info.
- Extract the Android link logic into _swift_android_linkopts_cc_info keyed on
  os == "android"; drop the redundant -lm (the clang driver links libm anyway;
  -lstdc++ stays, since it selects the shared libc++_shared.so the SDK intends).
- Rename the SDK repo's host_swiftc attr to paired_swiftc.
- Trim verbose comments/docs across the toolchain and extensions; simplify the
  clang-only error message.

Example (//examples/cross_compilation/android_app):
- Consolidate the Swift sources, Kotlin app, and BUILD into android_app/.
- Build the .so as a dep of android_binary (its native split configures it for
  Android) instead of a hand-written platform transition; use the platforms
  rules_android exposes (@rules_android//:arm64-v8a) rather than a custom one.
- Drop the manual tags; mark the Android-only targets target_compatible_with
  os:android so the //examples/... wildcard skips them on a host and the example
  runs in the normal macOS CI job. Remove the dedicated cross-compilation task.
- Split the example's dev dependencies into android_app/android.MODULE.bazel,
  include()d from the root MODULE; move the Maven lock out of the repo root;
  link rules_android#485 for the maven.install requirement.
- Set the rules_android flags (android_platforms + hermetic JDK) globally rather
  than behind a --config.

Claude-Session: https://claude.ai/code/session_01SmG1kqA3qB4WsLGU2xavuJ
Per review, guard the Android cross-compile on CI without a device.

Analysis tests (//test:android, macOS) assert the action command lines:
- the Swift compile targets aarch64-linux-android,
- the link runs the NDK clang for the Android target against the NDK sysroot
  and links libc++ as the shared libc++_shared.so, and
- libc++_shared.so is staged into the link.

Artifact tests on the example (run via build_test) cover what a build can't see:
- android_so_abi_check runs the NDK llvm-readelf on the built .so to assert it
  is an AArch64 ELF that lists libc++_shared.so in NEEDED and exports the @_cdecl
  JNI entry point in .dynsym;
- android_apk_contents_check asserts the APK packages both .so files under
  lib/arm64-v8a/ and the dexed Kotlin.

Claude-Session: https://claude.ai/code/session_01SmG1kqA3qB4WsLGU2xavuJ
Adds //examples/cross_compilation/android_app:run, which installs the example
APK on a connected device/emulator and launches it — booting a hermetic
emulator first if nothing is connected, so the example runs with nothing
preinstalled (no Android Studio, no device). adb comes from @AndroidSDK; the
emulator + AOSP system image are downloaded by a dev module extension
(emulator.bzl). macOS/arm64 only, to keep the delta small.

Demonstrates what zero-setup 'bazel run' support would cost for the example.

Claude-Session: https://claude.ai/code/session_01SmG1kqA3qB4WsLGU2xavuJ
Explains why -lstdc++ is needed: the Android cc toolchain links libc++
statically by default, so the shared libc++_shared.so must be forced.

Claude-Session: https://claude.ai/code/session_01SmG1kqA3qB4WsLGU2xavuJ
Fixes the gazelle-up-to-date CI check. Uses the correct
@rules_cc//cc:find_cc_toolchain_bzl label (gazelle's auto-generated
find_cc_toolchain doesn't exist), matching swift/toolchains/BUILD.

Claude-Session: https://claude.ai/code/session_01SmG1kqA3qB4WsLGU2xavuJ
Keith's Android implementation (bazelbuild#1827) as a single commit
representing the delta against the prior android-support work: static libc++
(dropping the shared libc++_shared.so packaging and select_android_runtime_lib),
validation moved into test/ test rules with a fixture APK, and all Android
module wiring consolidated into android.MODULE.bazel.
@AttilaTheFun

Copy link
Copy Markdown
Owner Author

Superseded: keith pushed this delta directly and bazelbuild#1818 has merged upstream.

@AttilaTheFun
AttilaTheFun deleted the android-keith-review branch July 2, 2026 23:31
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