Skip to content

build(android): add opt-in flag to disable SVE dispatch on Apple Silicon emulators - #719

Merged
farfromrefug merged 1 commit into
mainfrom
fix/emulator-sve-sigill
Sep 10, 2026
Merged

build(android): add opt-in flag to disable SVE dispatch on Apple Silicon emulators#719
farfromrefug merged 1 commit into
mainfrom
fix/emulator-sve-sigill

Conversation

@farfromrefug

Copy link
Copy Markdown
Collaborator

Summary

Android emulators running on Apple Silicon advertise SVE, SVE2 and friends in HWCAP even though the host CPU implements none of them. KleidiCV, OpenCV's arm64 HAL, reads HWCAP in its static initializers and selects its SVE2 kernels, so the first SVE instruction executed raises SIGILL and the app dies in nativeCrop as soon as a scan is cropped:

signal 4 (SIGILL), code 1 (ILL_ILLOPC)
  #00 libdocument_detector.so  kleidicv::sve2::remap_s16point5<unsigned char>
  #11 libdocument_detector.so  Java_..._nativeCrop
  • Add hwcap_sve.cpp, a getauxval interposition that hides the SVE bits so KleidiCV falls back to its NEON implementations. It is compiled in only when building with --gradleArgs=-PdisableSVE, and is a development aid — enabling it for a release would give up KleidiCV's SVE2 code paths on the devices that really support them.
  • The flag value is always passed to CMake explicitly, because a value left in the CMake cache would survive the flag being dropped and silently disable SVE in a release build.

Nothing changes for a normal build.

Testing

Both directions checked with real plugin rebuilds on an arm64 emulator (API 36, Apple Silicon host):

Build CMake cache getauxval Crop
ns build android DISABLE_SVE:BOOL=0 imported from libc crashes, unchanged
--gradleArgs=-PdisableSVE DISABLE_SVE:BOOL=1 bound locally, no PLT call left capture + crop complete, document saved

Note that the CLI reuses the prebuilt plugin aar, so toggling the flag alone rebuilds nothing until a plugin source changes.

…con emulators

Android emulators on Apple Silicon advertise SVE, SVE2 and friends in HWCAP although
the host CPU implements none of them. KleidiCV, OpenCV's arm64 HAL, reads HWCAP in its
static initializers and selects its SVE2 kernels, so the first SVE instruction (addvl)
raises SIGILL and the app dies in `nativeCrop` as soon as a scan is cropped.

Add a `getauxval` interposition that hides the SVE bits, compiled in only when building
with `--gradleArgs=-PdisableSVE`, so KleidiCV falls back to NEON. The flag value is
always passed to CMake so it cannot linger in the cache and reach a release build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@farfromrefug
farfromrefug marked this pull request as ready for review September 10, 2026 14:43
@farfromrefug
farfromrefug merged commit 38410a0 into main Sep 10, 2026
1 check passed
@farfromrefug
farfromrefug deleted the fix/emulator-sve-sigill branch September 10, 2026 14:43
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