diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e1fb22ca..c50ff6c2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -81,9 +81,9 @@ jobs: run: | make aw-server-rust - - name: Check that jniLibs present + - name: Check that jniLibs present and valid ELF run: | - test -e mobile/src/main/jniLibs/x86_64/libaw_server.so + python3 scripts/check-jnilibs.py - name: Upload jniLibs artifact uses: actions/upload-artifact@v4 @@ -205,9 +205,9 @@ jobs: key: ${{ env.cache-name }}-release-${{ env.RELEASE }}-ndk-${{ env.NDK_VERSION }}-${{ hashFiles('.git/modules/aw-server-rust/HEAD') }} fail-on-cache-miss: false - - name: Check that jniLibs present + - name: Check that jniLibs present and valid ELF run: | - test -e mobile/src/main/jniLibs/x86_64/libaw_server.so + python3 scripts/check-jnilibs.py - name: Verify versionName matches tag if: startsWith(github.ref, 'refs/tags/v') # only on runs triggered from tag @@ -289,9 +289,9 @@ jobs: name: jniLibs path: mobile/src/main/jniLibs/ - - name: Check that jniLibs present + - name: Check that jniLibs present and valid ELF run: | - test -e mobile/src/main/jniLibs/x86_64/libaw_server.so + python3 scripts/check-jnilibs.py # Test - name: Test diff --git a/mobile/build.gradle b/mobile/build.gradle index 619fa488..d3d82822 100644 --- a/mobile/build.gradle +++ b/mobile/build.gradle @@ -38,6 +38,13 @@ android { applicationIdSuffix ".debug" jniDebuggable true renderscriptDebuggable true + // Limit debug APK to modern ABIs used by CI emulators and physical devices. + // armeabi-v7a debug Rust binaries are very large and can corrupt the CI + // artifact when disk space is tight; they aren't needed for x86_64 emulator + // runs or any arm64-v8a device released since ~2014. + ndk { + abiFilters 'arm64-v8a', 'x86_64' + } } } compileOptions { diff --git a/scripts/check-jnilibs.py b/scripts/check-jnilibs.py new file mode 100755 index 00000000..3f349ddf --- /dev/null +++ b/scripts/check-jnilibs.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +import os +import struct +import sys + + +ABIS = ["arm64-v8a", "armeabi-v7a", "x86", "x86_64"] +LIB_NAME = "libaw_server.so" + + +def check_lib(abi): + path = os.path.join("mobile", "src", "main", "jniLibs", abi, LIB_NAME) + if not os.path.exists(path): + print(f"MISSING {path}", file=sys.stderr) + return False + + fsize = os.path.getsize(path) + with open(path, "rb") as f: + header = f.read(64) + + if header[:4] != b"\x7fELF": + print(f"NOT_ELF {path}", file=sys.stderr) + return False + + if len(header) < 64: + print( + f"CORRUPT {path}: file too small for ELF header " + f"({len(header)} bytes)", + file=sys.stderr, + ) + return False + + e_class = header[4] # 1=32-bit, 2=64-bit + if e_class == 1: + e_shoff = struct.unpack("= fsize: + print( + f"CORRUPT {path}: section header past EOF " + f"(e_shoff=0x{e_shoff:x}, size={fsize})", + file=sys.stderr, + ) + return False + + print(f"OK {abi}/{LIB_NAME} ({fsize:,} bytes)") + return True + + +def main(): + ok = True + for abi in ABIS: + ok = check_lib(abi) and ok + return 0 if ok else 1 + + +if __name__ == "__main__": + sys.exit(main())