feat: add Android arm64 Bionic support - #62
Conversation
|
Consumer integration: gogpu/wgpu#268 at exact head The WGPU module commits no |
2524e33 to
8ccaae7
Compare
|
@kolkov — the only missing readiness signal here is approval of the fork workflow run: https://github.com/go-webgpu/goffi/actions/runs/29439408858. GitHub currently records it as As a preflight at exact head |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
kolkov
left a comment
There was a problem hiding this comment.
Sorry for the delay reviewing this — we've been through the errno v0.6.0 release and the stack-move fix from @tie in parallel. Read through the full diff, ran the CI (15/15 green including both Android jobs), and studied the downstream context in wgpu#268.
The quality here is outstanding. The four-argument _cgo_init matching asm_arm64.s, the Bionic sigset_t difference (8 bytes vs glibc 128 — would silently corrupt pthread_sigmask), the dlerror-within-cgocall thread-locality capture, and the ELF rejection gates in the check script are all things that show deep runtime source knowledge. The fakecgo work goes beyond what purego has done for Android — they only support CGO_ENABLED=1 there.
A couple of points before we merge:
1. runtime.iscgo on Android CGO_ENABLED=0
callbacks.go and iscgo.go exclude android from their build tags, so runtime.iscgo stays false. I assume this is intentional since callbacks are rejected — but iscgo affects several runtime paths beyond callbacks. Can you confirm you've traced through what iscgo=false means for the outbound cgocall path you're using?
2. Exported RTLD constants
ffi/dl_android.go exports RTLD_NOW, RTLD_LOCAL, RTLD_NODELETE from the ffi package. Other platform loaders keep these internal. Is there a use case for callers passing custom flags, or should these be internal with LoadLibrary applying them automatically?
3. Rebase needed — purego_ → goffi_ rename landed
We just merged #63 which renames all purego_ dynamic imports to goffi_ across internal/fakecgo/ and updates the copyright headers to dual Ebitengine + GoGPU attribution. Your commit b1503fc touches gen.go, symbols_linux.go, and trampolines_stubs.s which will conflict — you'll need a rebase on current main and resolve by keeping goffi_ prefix. Your 4 new Android files (android_dl.go, android_dl_stubs_arm64.s, symbols_android_imports.go, trampolines_stubs_android.s) should also switch to goffi_ prefix.
4. x_cgo_inittls diagnostics
if tlsg == nil || *tlsg != androidTLSGOffset {
androidFatal("fakecgo: Android runtime.tls_g offset mismatch")
}Two different failure modes produce the same message: tlsg == nil means the runtime didn't pass the pointer at all (startup sequence issue), while *tlsg != 16 means the TLS slot offset changed (Go ABI drift). On a device without a debugger attached, this fatal is the only diagnostic you get. Worth splitting into two distinct messages? You know the Android startup path better — curious what you think.
Everything else — build tags, assembly, errno routing, callback rejection, CI matrix — looks solid. Happy to merge as guarded preview once we align on these and the rebase is done. Physical device validation can happen through wgpu#268 post-merge.
|
One more thing — once this lands, would you be open to being added to |
Document and assert the runtime.iscgo wiring selected by Android's implicit linux build tag, keep RTLD policy internal, split TLS startup diagnostics, and align all Android fakecgo imports with the goffi_ prefix introduced by go-webgpu#63.
8ccaae7 to
a8a33c7
Compare
|
Thank you for the thorough review. The subtle part of point 1 is that Go defines I also removed the exported RTLD constants, rebased onto #63 with And yes—absolutely, I’d be happy to be added as CODEOWNER for the Android paths and help review and maintain future Android changes. |
kolkov
left a comment
There was a problem hiding this comment.
All four review points addressed cleanly. Build tags, goffi_ naming, iscgo assertions, RTLD internalization, and split diagnostics verified. LGTM as guarded preview.
|
Merged and released as v0.6.1. You're now in |
Summary
Android arm64/API 29+ is ready for code review as a guarded preview candidate rebased onto current
mainafter #63 (2bd8752a68324d4cc47343b8f3a38d154147be85). The candidate keeps the public module path and separates the review surface into dependency-ordered commits:b7a3a76f0d339bc193537bd039178f85a81ff8bf— Bionic platform loader and__errno/errno routing for cgo=0 and cgo=1.0cb3ecb9ba84705b6d51f8b2e3d1bd5e684d25af— Android arm64 fakecgo startup, four-argument_cgo_init, API/TLS guard, Bionic layouts/imports, and explicit callback rejection.53d06d7c96e7624eb6a69bd764e8c5cefca8a4ff— generated-source, NDK ABI, cross-build/ELF probes, CI matrix, and preview documentation.a8a33c781c0f0ab4de96b2f81834f9913e2d2a11— refactor: rename purego_ → goffi_ in fakecgo + copyright update #63 alignment plus theruntime.iscgo, RTLD API, and TLS-diagnostic review follow-up.The exact branch head is
a8a33c781c0f0ab4de96b2f81834f9913e2d2a11. The previously published one-commit head is preserved atbesmpl/archive/android-arm64-bionic-3d665de,3d665de6d43af35dd6dae005ef09231c15b0d456.Android loader mappings remain process-lifetime mappings (
RTLD_NODELETE);FreeLibraryis retained for API symmetry. Android callbacks fail with a stable panic until foreign-thread startup has physical-device evidence.Validation
The Android check passed on both audited toolchains with NDK r29 (
29.0.14206865):Each run covers
CGO_ENABLED=0andCGO_ENABLED=1, generated fakecgo freshness, Bionic LP64 header/layout assertions, AArch64 ELF dependencies, callback/glibc symbol rejection, startup/TLS disassembly, and same-call loader-error capture. Focused hostgo test ./ffi ./typespasses in both cgo modes; root module verification, formatting, shell syntax, and diff checks are clean.The same matrix was rerun locally against this exact head on 2026-07-21 and passed for Go 1.25.12 and Go 1.26.5. The review follow-up also asserts Android's implicit Linux-tag selection of
callbacks.go,iscgo.go, andsetenv.go, and verifies that nopurego_dynamic imports remain. The new upstream Actions run currently needs a maintainer to approve workflows from the fork: https://github.com/go-webgpu/goffi/actions/runs/29806270436.Review and evidence boundary
This PR is ready for implementation review now. It does not claim released Android support: cross-build, ABI, and ELF evidence cannot prove process startup or foreign-call behavior on a physical device. API 29 and API 30+ arm64 device runs remain the outstanding acceptance evidence before Android should be advertised as supported. Android callback support remains explicitly unavailable rather than being inferred from desktop behavior.
A downstream WGPU consumer exercises the non-callback FFI path. Its host keeps Android Activity/JNI policy outside goffi, uses ordinary cgo for incoming Activity callbacks, and uses goffi only for outgoing Vulkan calls. This lets the runtime work be reviewed without expanding goffi into an Android callback framework.
Downstream integration
The corresponding pure-Go WGPU Android candidate is gogpu/wgpu#268 at exact head
041e19e65620a0a554718a712ead544794a863b5. Its temporary CI still pins the successful pre-rebase goffi head8ccaae72d877a7af0af4b628bf86e92536e27d88; it will refresh to this PR's current head or the canonical release before its next integration claim. It uses no fork module path,replace, or committedgo.work.Rust-v29 typed surface parity is separate in gogpu/wgpu#273 at exact head
d61c2152ed95a80985ff53b30df7f65fd0431367. This PR deliberately remains outbound Bionic FFI only. Activity, JNI, nativeexport, and foreign-thread entry are host/runtime work above WGPU; the experimental zero-cgo native-entry prototype is not included here and is not a merge prerequisite.API 29 is the downstream native/install floor; API 36 compile/target is downstream host policy. Merge and release goffi#62 first, then #268 can drop its temporary pin and consume the canonical release.