From 04742902b57ba9fc4e7551adbd714169f4a73abe Mon Sep 17 00:00:00 2001 From: Andrey Prokopyuk Date: Wed, 2 Sep 2026 18:44:05 +0300 Subject: [PATCH] Fix GP issues --- .github/workflows/ci.yml | 4 +- .github/workflows/release.yml | 6 +-- README.md | 9 ++-- app/build.gradle.kts | 7 +-- build.gradle.kts | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- scripts/build-release-apks.sh | 6 +-- scripts/build-release-bundle.sh | 63 ++++++++++++++++++++++-- 8 files changed, 78 insertions(+), 21 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1cc34e6..2659dad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -62,8 +62,8 @@ jobs: fi yes | "$sdkmanager" --licenses >/dev/null || true "$sdkmanager" \ - "platforms;android-35" \ - "build-tools;34.0.0" \ + "platforms;android-36" \ + "build-tools;36.0.0" \ "ndk;29.0.14206865" echo "ANDROID_NDK_HOME=$ANDROID_HOME/ndk/29.0.14206865" >> "$GITHUB_ENV" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 88d4b15..8b24e3a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,8 +45,8 @@ jobs: fi yes | "$sdkmanager" --licenses >/dev/null || true "$sdkmanager" \ - "platforms;android-35" \ - "build-tools;34.0.0" \ + "platforms;android-36" \ + "build-tools;36.0.0" \ "ndk;29.0.14206865" echo "ANDROID_NDK_HOME=$ANDROID_HOME/ndk/29.0.14206865" >> "$GITHUB_ENV" @@ -99,7 +99,7 @@ jobs: env: GH_TOKEN: ${{ github.token }} run: | - assets=(dist/release/*.apk dist/release/*.aab dist/release/SHA256SUMS) + assets=(dist/release/*.apk dist/release/*.aab dist/release/*-native-debug-symbols.zip dist/release/SHA256SUMS) if gh release view "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1; then gh release upload "$GITHUB_REF_NAME" "${assets[@]}" \ --repo "$GITHUB_REPOSITORY" \ diff --git a/README.md b/README.md index 2faf5ee..5dac789 100644 --- a/README.md +++ b/README.md @@ -206,7 +206,7 @@ The command-line build does not require Android Studio. It requires: - Go 1.26 or newer - `gomobile` - Android SDK Platform 35 -- Android Build Tools 34.0.0 +- Android SDK Platform 36 and Build Tools 36.0.0 - Android NDK 29.0.14206865 Example environment on macOS: @@ -294,9 +294,10 @@ universal APK used for reproducible F-Droid verification: The scripts read the default signing key from `$HOME/AndroidApkKey` and its password from `$HOME/.my-tokens/android-key-password`. Override these with `MEGAPROXY_KEYSTORE_PATH`, `MEGAPROXY_KEY_ALIAS`, `MEGAPROXY_KEY_PASSWORD_FILE`, and `MEGAPROXY_KEY_PASSWORD`. The signed -ABI-specific and universal APKs, the signed universal App Bundle, and `SHA256SUMS` are -written to `dist/release`. The App Bundle contains every supported ABI; app stores generate and -serve optimized device-specific APK splits from it. +ABI-specific and universal APKs, the signed universal App Bundle, its native debug-symbol archive, +and `SHA256SUMS` are written to `dist/release`. The App Bundle contains every supported ABI; app +stores generate and serve optimized device-specific APK splits from it. Go native symbols are +provided as `mega-proxy-native-debug-symbols.zip` for upload in Play Console. Pushing a version tag runs the GitHub release workflow, builds and verifies every APK and the App Bundle, and attaches the artifacts to a GitHub Release. The tag must match `versionName` exactly: diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2f18d4e..9d382a1 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -32,13 +32,13 @@ val gitCommitHash = providers.environmentVariable("GITHUB_SHA") android { namespace = "net.megaproxy487" - compileSdk = 35 - buildToolsVersion = "34.0.0" + compileSdk = 36 + buildToolsVersion = "36.0.0" defaultConfig { applicationId = "net.megaproxy487" minSdk = 26 - targetSdk = 35 + targetSdk = 36 // Each APK has a unique, monotonically ordered code. Keeping the // universal code below the ABI variants lets app stores prefer the // smaller compatible APK when both are available. @@ -73,6 +73,7 @@ android { signingConfig = signingConfigs.findByName("release") isMinifyEnabled = true isShrinkResources = true + ndk.debugSymbolLevel = "SYMBOL_TABLE" proguardFiles( getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro", diff --git a/build.gradle.kts b/build.gradle.kts index 1b4481a..022c030 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("com.android.application") version "8.7.3" apply false + id("com.android.application") version "8.9.1" apply false id("org.jetbrains.kotlin.android") version "2.0.21" apply false id("org.jetbrains.kotlin.plugin.compose") version "2.0.21" apply false } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 09523c0..e2847c8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/scripts/build-release-apks.sh b/scripts/build-release-apks.sh index 4388423..75cf0e3 100755 --- a/scripts/build-release-apks.sh +++ b/scripts/build-release-apks.sh @@ -66,9 +66,9 @@ mkdir -p "$MEGAPROXY_RELEASE_DIR" "$project_dir/app/libs" # Avoid carrying artifacts from an older version into SHA256SUMS or a release. find "$MEGAPROXY_RELEASE_DIR" -maxdepth 1 -type f \ \( -name 'mega-proxy-*.apk' -o -name SHA256SUMS \) -delete -apksigner="$ANDROID_HOME/build-tools/34.0.0/apksigner" +apksigner="$ANDROID_HOME/build-tools/36.0.0/apksigner" if [[ ! -x "$apksigner" ]]; then - echo "Android apksigner 34.0.0 is unavailable: $apksigner" >&2 + echo "Android apksigner 36.0.0 is unavailable: $apksigner" >&2 exit 1 fi @@ -90,7 +90,7 @@ verify_release_version_code() { local expected_version_code="$2" local actual_version_code actual_version_code="$( - "$ANDROID_HOME/build-tools/34.0.0/aapt" dump badging "$apk" \ + "$ANDROID_HOME/build-tools/36.0.0/aapt" dump badging "$apk" \ | sed -n "s/^package:.*versionCode='\([^']*\)'.*/\1/p" )" if [[ "$actual_version_code" != "$expected_version_code" ]]; then diff --git a/scripts/build-release-bundle.sh b/scripts/build-release-bundle.sh index b2a9e29..8a66829 100755 --- a/scripts/build-release-bundle.sh +++ b/scripts/build-release-bundle.sh @@ -19,7 +19,7 @@ fi export JAVA_HOME ANDROID_HOME ANDROID_NDK_HOME export PATH="$JAVA_HOME/bin:$HOME/go/bin:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$PATH" -for command in go gomobile java jarsigner keytool unzip; do +for command in go gomobile java jarsigner keytool unzip zip; do if ! command -v "$command" >/dev/null 2>&1; then echo "Required command is unavailable: $command" >&2 exit 1 @@ -56,7 +56,8 @@ keytool -list \ -alias "$MEGAPROXY_KEY_ALIAS" >/dev/null mkdir -p "$MEGAPROXY_RELEASE_DIR" "$project_dir/app/libs" -find "$MEGAPROXY_RELEASE_DIR" -maxdepth 1 -type f -name 'mega-proxy.aab' -delete +find "$MEGAPROXY_RELEASE_DIR" -maxdepth 1 -type f \ + \( -name 'mega-proxy.aab' -o -name 'mega-proxy-native-debug-symbols.zip' \) -delete temporary_dir="$(mktemp -d "${TMPDIR:-/tmp}/megaproxy-bundle.XXXXXX")" original_aar="$project_dir/app/libs/megaproxy.aar" @@ -75,6 +76,14 @@ restore_workspace() { } trap restore_workspace EXIT +llvm_bin_dirs=("$ANDROID_NDK_HOME"/toolchains/llvm/prebuilt/*/bin) +llvm_objcopy="${llvm_bin_dirs[0]}/llvm-objcopy" +llvm_readelf="${llvm_bin_dirs[0]}/llvm-readelf" +if [[ ! -x "$llvm_objcopy" || ! -x "$llvm_readelf" ]]; then + echo "NDK LLVM tools are unavailable under $ANDROID_NDK_HOME" >&2 + exit 1 +fi + export MEGAPROXY_KEYSTORE_PATH export MEGAPROXY_KEYSTORE_PASSWORD="$keystore_password" export MEGAPROXY_KEY_ALIAS @@ -83,15 +92,43 @@ export MEGAPROXY_KEY_PASSWORD echo "Building universal native AAR for the App Bundle" ( cd "$project_dir/native" + # External linking preserves the ELF symbol table and DWARF data in the + # input libraries. AGP strips the packaged copies and extracts the + # requested SYMBOL_TABLE metadata for Play Console symbolication. gomobile bind \ -target=android \ -androidapi 26 \ -trimpath \ - -ldflags="-s -w -buildid=" \ + -ldflags="-linkmode=external -buildid= -extldflags=-Wl,--build-id=sha1" \ -o ../app/libs/megaproxy.aar \ ./mobile ) +# gomobile provides the Go shared libraries as an AAR dependency, so AGP does +# not retain their symbols automatically. Create the Play-compatible archive +# first, then replace the AAR copies with stripped libraries for the bundle. +aar_contents="$temporary_dir/aar" +symbols_dir="$temporary_dir/native-debug-symbols" +mkdir -p "$aar_contents" "$symbols_dir" +unzip -q "$original_aar" -d "$aar_contents" +for library in "$aar_contents"/jni/*/libgojni.so; do + abi="$(basename "$(dirname "$library")")" + mkdir -p "$symbols_dir/$abi" + "$llvm_objcopy" --strip-debug "$library" "$symbols_dir/$abi/libgojni.so.dbg" + "$llvm_objcopy" --strip-all "$library" "$library.stripped" + mv "$library.stripped" "$library" +done +output_symbols="$MEGAPROXY_RELEASE_DIR/mega-proxy-native-debug-symbols.zip" +( + cd "$symbols_dir" + zip -q -r "$output_symbols" . +) +rm "$original_aar" +( + cd "$aar_contents" + zip -q -r "$original_aar" . +) + echo "Building signed App Bundle" ( cd "$project_dir" @@ -122,6 +159,8 @@ fi expected_abis=(arm64-v8a armeabi-v7a x86 x86_64) bundle_entries="$temporary_dir/bundle-entries.txt" unzip -Z1 "$output_bundle" > "$bundle_entries" +symbol_entries="$temporary_dir/symbol-entries.txt" +unzip -Z1 "$output_symbols" > "$symbol_entries" for abi in "${expected_abis[@]}"; do for library in libandroidx.graphics.path.so libgojni.so; do entry="base/lib/$abi/$library" @@ -130,18 +169,34 @@ for abi in "${expected_abis[@]}"; do exit 1 fi done + symbol_entry="$abi/libgojni.so.dbg" + if ! grep -Fxq "$symbol_entry" "$symbol_entries"; then + echo "Native debug-symbol archive is missing $symbol_entry" >&2 + exit 1 + fi done +arm64_symbols="$temporary_dir/libgojni-arm64.so.dbg" +unzip -p "$output_symbols" arm64-v8a/libgojni.so.dbg > "$arm64_symbols" +if ! "$llvm_readelf" -S "$arm64_symbols" 2>/dev/null | grep '\.symtab' >/dev/null; then + echo "Native debug-symbol archive does not contain an ELF symbol table" >&2 + exit 1 +fi + ( cd "$MEGAPROXY_RELEASE_DIR" checksum_files=() while IFS= read -r file; do checksum_files+=("$file") - done < <(find . -maxdepth 1 -type f \( -name 'mega-proxy-*.apk' -o -name 'mega-proxy.aab' \) -print | sort) + done < <(find . -maxdepth 1 -type f \ + \( -name 'mega-proxy-*.apk' -o -name 'mega-proxy.aab' -o -name 'mega-proxy-native-debug-symbols.zip' \) \ + -print | sort) shasum -a 256 "${checksum_files[@]}" > SHA256SUMS ) echo echo "Signed release App Bundle:" ls -lh "$output_bundle" +echo "Native debug symbols:" +ls -lh "$output_symbols" echo "Checksums: $MEGAPROXY_RELEASE_DIR/SHA256SUMS"