build(android): drop the x86_64 ABI, which no Android can run
The fat APK's second half was 31 MB that cannot execute on any Android device. modernc.org/libc's Xlstat64 issues a raw lstat syscall on linux/amd64, and Android's seccomp policy forbids it because bionic never issues it, so the process takes SIGSYS the first time anything touches the database -- which for this app is startup. That is every x86_64 Android, x86 Chromebooks included, not merely the emulator. arm64 is structurally unaffected: the architecture has no lstat syscall at all, so modernc routes through fstatat. 27,059,130 bytes to 15,898,465, and one lib/ entry. Three places had to agree, and the third is what would have made this a silent no-op: abiFilters (what Gradle packages), android:package rather than package:fat (what Go *compiles* -- otherwise the library is still built and then discarded), and the native-code assertion in CI. That assertion is anchored, `native-code: 'arm64-v8a'$`, because without the anchor it also matches the fat APK's line and would pass on exactly the thing it exists to catch. Checked against a real artifact. Adding the ABI back, if modernc ever fixes Xlstat64, is those same three edits.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
name: Build & publish the Android APK
|
||||
|
||||
# The fifth workflow, and the second that publishes. It builds a signed
|
||||
# fat APK (arm64-v8a + x86_64) on every version tag and puts it in
|
||||
# arm64-v8a APK on every version tag and puts it in
|
||||
# Gitea's *generic* package registry, which — unlike the repository — is
|
||||
# readable without credentials. That is what lets an Obtainium client
|
||||
# poll a plain URL with no token and no public mirror of the source.
|
||||
@@ -225,7 +225,7 @@ jobs:
|
||||
# `$GITHUB_ENV` — where the `env:` dump is only masked for values
|
||||
# that are *verbatim* a secret, so a trimmed one could print in
|
||||
# clear — or repeating the trimming logic in both.
|
||||
- name: Build the signed fat APK
|
||||
- name: Build the signed APK
|
||||
working-directory: /src
|
||||
env:
|
||||
KEYSTORE_B64: ${{ secrets.ANDROID_KEYSTORE_B64 }}
|
||||
@@ -333,9 +333,14 @@ jobs:
|
||||
ls -la "$apk"
|
||||
"$bt/aapt2" dump badging "$apk" | sed -n '1p;/application-label:/p;/native-code/p'
|
||||
|
||||
# Both ABIs, or the artifact is not the fat APK it claims to be.
|
||||
"$bt/aapt2" dump badging "$apk" | grep -q "native-code: 'arm64-v8a' 'x86_64'" || {
|
||||
echo "the APK does not carry both ABIs" >&2; exit 1; }
|
||||
# arm64 and *only* arm64. x86_64 Android cannot run this app
|
||||
# (modernc's raw lstat against Android's seccomp filter, which
|
||||
# is every x86_64 device and not merely the emulator), so an
|
||||
# x86_64 slice would be ~31 MB that runs nowhere -- and its
|
||||
# reappearance would mean someone had put the ABI back in
|
||||
# app/build.gradle without knowing that.
|
||||
"$bt/aapt2" dump badging "$apk" | grep -q "native-code: 'arm64-v8a'$" || {
|
||||
echo "the APK's ABI set is not exactly arm64-v8a" >&2; exit 1; }
|
||||
|
||||
# The identity the pipeline exists to keep stable.
|
||||
"$bt/aapt2" dump badging "$apk" | grep -q "versionCode='${{ steps.version.outputs.code }}'" || {
|
||||
|
||||
@@ -52,8 +52,13 @@ ANDROID_SDK ?= $(HOME)/Android/Sdk
|
||||
ANDROID_NDK ?= /opt/android-ndk
|
||||
ANDROID_ENV := ANDROID_HOME=$(ANDROID_SDK) ANDROID_SDK_ROOT=$(ANDROID_SDK) ANDROID_NDK_HOME=$(ANDROID_NDK)
|
||||
|
||||
android: build-frontend ## Build the fat APK (arm64 + x86_64) into bin/
|
||||
@$(ANDROID_ENV) PATH="$(TOOLBIN):$$PATH" go tool wails3 task android:package:fat
|
||||
# `package`, not `package:fat`: x86_64 Android cannot run this app at
|
||||
# all (modernc's raw lstat vs Android's seccomp -- see
|
||||
# android-tier.md), so the second ABI was ~31 MB that could not run
|
||||
# anywhere. app/build.gradle's abiFilters says the same thing to
|
||||
# Gradle; both have to agree or the .so is built and then dropped.
|
||||
android: build-frontend ## Build the arm64 APK into bin/
|
||||
@$(ANDROID_ENV) PATH="$(TOOLBIN):$$PATH" go tool wails3 task android:package
|
||||
|
||||
android-setup: ## Install the SDK pieces and create the AVD (once, ~3.5GB)
|
||||
@$(ANDROID_ENV) ./scripts/android-emulator.sh setup
|
||||
|
||||
@@ -40,9 +40,21 @@ android {
|
||||
versionCode Integer.parseInt(System.getenv("YJ_VERSION_CODE") ?: "1")
|
||||
versionName System.getenv("YJ_VERSION") ?: "0.0.0"
|
||||
|
||||
// Configure supported ABIs
|
||||
// **arm64 only, and x86_64 is not a gap.** `modernc.org/libc`'s
|
||||
// Xlstat64 issues a raw lstat syscall on linux/amd64, which
|
||||
// Android's seccomp policy forbids (bionic never issues it), so
|
||||
// the process takes SIGSYS the first time anything touches the
|
||||
// database -- which for this app is startup. That is every
|
||||
// x86_64 Android, emulators and x86 Chromebooks alike, not just
|
||||
// some. arm64 is structurally unaffected: the architecture has
|
||||
// no lstat syscall at all, so modernc routes through fstatat.
|
||||
//
|
||||
// So the second ABI was ~31 MB of an artifact that could not run
|
||||
// anywhere. If modernc fixes it, adding 'x86_64' back here and
|
||||
// to the native-code assertion in android-apk.yml is the whole
|
||||
// change.
|
||||
ndk {
|
||||
abiFilters 'arm64-v8a', 'x86_64'
|
||||
abiFilters 'arm64-v8a'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +105,6 @@ android {
|
||||
packagingOptions {
|
||||
// Don't strip Go symbols in debug builds
|
||||
doNotStrip '*/arm64-v8a/libwails.so'
|
||||
doNotStrip '*/x86_64/libwails.so'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user