From 75661828af0bda18f1cbac5c6e113d2dec72408f Mon Sep 17 00:00:00 2001 From: Farnam Taheri Date: Mon, 11 May 2026 20:15:25 +0330 Subject: [PATCH 1/3] fix(android): prevent gomobile builds from mutating core modules --- android/BUILDING.md | 23 ++++++++++++++ android/build_go_mobile.bat | 62 ++++++++++++++++++++++++++++++++++--- android/build_go_mobile.sh | 36 +++++++++++++++++---- android/gomobile.version | 1 + 4 files changed, 112 insertions(+), 10 deletions(-) create mode 100644 android/BUILDING.md create mode 100644 android/gomobile.version diff --git a/android/BUILDING.md b/android/BUILDING.md new file mode 100644 index 0000000..e9565df --- /dev/null +++ b/android/BUILDING.md @@ -0,0 +1,23 @@ +# Android build notes + +This Android client wraps the shared Go engine through `gomobile`. +Android build helpers must not edit the shared Go module files at the repository root. + +Use the provided scripts to rebuild the Android AAR: + +```bash +./android/build_go_mobile.sh +``` + +```bat +android\build_go_mobile.bat +``` + +Both scripts: + +- read the pinned gomobile/gobind version from `android/gomobile.version` +- run gomobile binding from an isolated temporary source tree +- run any `go get` dependency preparation only in the temporary tree +- fail if the real `go.mod` or `go.sum` are modified + +If the build reports missing Go module dependencies, update the shared Go module in a separate upstream/core change rather than from the Android build script. diff --git a/android/build_go_mobile.bat b/android/build_go_mobile.bat index d4e29ad..2647555 100644 --- a/android/build_go_mobile.bat +++ b/android/build_go_mobile.bat @@ -4,8 +4,7 @@ REM MasterDnsVPN - Build Go Mobile Library for Android REM Prerequisites: Go 1.25+, gomobile, Android NDK REM ============================================================================ -set MOBILE_TOOLS_VERSION=v0.0.0-20231127183840-76ac6878050a - +set /p MOBILE_TOOLS_VERSION=<"%~dp0gomobile.version" echo =================================== echo MasterDnsVPN - Android Build Script echo =================================== @@ -20,6 +19,18 @@ if errorlevel 1 ( exit /b 1 ) +cd /d "%~dp0.." + +git diff --quiet -- go.mod go.sum +if errorlevel 1 ( + echo. + echo ERROR: go.mod/go.sum already have local changes. + echo Refusing to build because android builds must not modify shared Go module files. + git diff -- go.mod go.sum + pause + exit /b 1 +) + REM Install pinned gomobile toolchain go install golang.org/x/mobile/cmd/gomobile@%MOBILE_TOOLS_VERSION% go install golang.org/x/mobile/cmd/gobind@%MOBILE_TOOLS_VERSION% @@ -40,8 +51,36 @@ echo. echo [1/2] Building Go mobile library... echo. -cd /d "%~dp0.." -gomobile bind -v -target=android/arm64,android/arm,android/amd64,android/386 -androidapi 21 -o android/app/libs/masterdnsvpn.aar ./mobile/ +set "SOURCE_ROOT=%CD%" +set "BUILD_ROOT=%TEMP%\masterdnsvpn-gomobile-%RANDOM%%RANDOM%" +mkdir "%BUILD_ROOT%" +if errorlevel 1 ( + echo ERROR: Failed to create temporary build directory + pause + exit /b 1 +) + +robocopy "%SOURCE_ROOT%" "%BUILD_ROOT%" /MIR /XD .git android\.gradle android\app\build android\build >nul +if errorlevel 8 ( + echo ERROR: Failed to copy source tree for isolated gomobile build + rmdir /s /q "%BUILD_ROOT%" + pause + exit /b 1 +) + +cd /d "%BUILD_ROOT%" + +REM Resolve gomobile's bind dependency only in this temporary build tree. +GO111MODULE=on go get golang.org/x/mobile@%MOBILE_TOOLS_VERSION% +if errorlevel 1 ( + echo ERROR: Failed to prepare temporary gomobile module dependencies + cd /d "%SOURCE_ROOT%" + rmdir /s /q "%BUILD_ROOT%" + pause + exit /b 1 +) + +gomobile bind -v -target=android/arm64,android/arm,android/amd64,android/386 -androidapi 21 -o "%SOURCE_ROOT%\android\app\libs\masterdnsvpn.aar" ./mobile/ if errorlevel 1 ( echo. @@ -50,6 +89,21 @@ if errorlevel 1 ( echo. echo ANDROID_HOME should point to: %LOCALAPPDATA%\Android\Sdk echo ANDROID_NDK_HOME should point to: %LOCALAPPDATA%\Android\Sdk\ndk\(version) + cd /d "%SOURCE_ROOT%" + rmdir /s /q "%BUILD_ROOT%" + pause + exit /b 1 +) + +cd /d "%SOURCE_ROOT%" +rmdir /s /q "%BUILD_ROOT%" + +git diff --quiet -- go.mod go.sum +if errorlevel 1 ( + echo. + echo ERROR: gomobile build modified shared Go module files. + echo Refusing to continue because android builds must not change go.mod/go.sum. + git diff -- go.mod go.sum pause exit /b 1 ) diff --git a/android/build_go_mobile.sh b/android/build_go_mobile.sh index 1de21b8..e71cdbe 100644 --- a/android/build_go_mobile.sh +++ b/android/build_go_mobile.sh @@ -4,26 +4,50 @@ set -euo pipefail ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" cd "$ROOT_DIR" -MOBILE_TOOLS_VERSION="v0.0.0-20260312152759-81488f6aeb60" +MOBILE_TOOLS_VERSION="$(tr -d '[:space:]' < android/gomobile.version)" +OUTPUT_AAR="$ROOT_DIR/android/app/libs/masterdnsvpn.aar" + +check_go_modules_clean() { + if ! git diff --quiet -- go.mod go.sum; then + echo "ERROR: gomobile build modified shared Go module files." + echo "Refusing to continue because android builds must not change go.mod/go.sum." + git diff -- go.mod go.sum + exit 1 + fi +} + +trap check_go_modules_clean EXIT +check_go_modules_clean # Always install a pinned, known-good gomobile/gobind pair. go install "golang.org/x/mobile/cmd/gomobile@${MOBILE_TOOLS_VERSION}" go install "golang.org/x/mobile/cmd/gobind@${MOBILE_TOOLS_VERSION}" -# Ensure module dependency is available for gomobile bind -GO111MODULE=on go get golang.org/x/mobile@${MOBILE_TOOLS_VERSION} -GO111MODULE=on go get golang.org/x/mobile/bind@${MOBILE_TOOLS_VERSION} - export PATH="$(go env GOPATH)/bin:$PATH" GO111MODULE=on gomobile init mkdir -p android/app/libs +BUILD_DIR="$(mktemp -d)" +cleanup() { + rm -rf "$BUILD_DIR" + check_go_modules_clean +} +trap cleanup EXIT + +git archive HEAD | tar -x -C "$BUILD_DIR" +cd "$BUILD_DIR" + +# gomobile's generated binding imports golang.org/x/mobile/bind. Resolve that +# dependency only in the temporary build tree so the real go.mod/go.sum stay +# untouched for upstream/core merge safety. +GO111MODULE=on go get "golang.org/x/mobile@${MOBILE_TOOLS_VERSION}" + gomobile bind \ -v \ -target=android/arm64,android/arm,android/amd64,android/386 \ -androidapi 21 \ - -o android/app/libs/masterdnsvpn.aar \ + -o "$OUTPUT_AAR" \ ./mobile/ echo "Built android/app/libs/masterdnsvpn.aar" diff --git a/android/gomobile.version b/android/gomobile.version new file mode 100644 index 0000000..7c5077e --- /dev/null +++ b/android/gomobile.version @@ -0,0 +1 @@ +v0.0.0-20260312152759-81488f6aeb60 From 00428ecf5711c22ec3ba2e5cdc3e1d0f0a7d57d9 Mon Sep 17 00:00:00 2001 From: Farnam Taheri Date: Mon, 11 May 2026 20:35:58 +0330 Subject: [PATCH 2/3] fix(android): prefetch gomobile deps in isolated build Download module dependencies inside the temporary gomobile source tree after adding the pinned x/mobile module. This keeps the real shared Go modules untouched while giving CI a complete module cache before gomobile bind runs. --- android/build_go_mobile.bat | 9 +++++++++ android/build_go_mobile.sh | 1 + 2 files changed, 10 insertions(+) diff --git a/android/build_go_mobile.bat b/android/build_go_mobile.bat index 2647555..3478bd0 100644 --- a/android/build_go_mobile.bat +++ b/android/build_go_mobile.bat @@ -80,6 +80,15 @@ if errorlevel 1 ( exit /b 1 ) +GO111MODULE=on go mod download +if errorlevel 1 ( + echo ERROR: Failed to download temporary gomobile module dependencies + cd /d "%SOURCE_ROOT%" + rmdir /s /q "%BUILD_ROOT%" + pause + exit /b 1 +) + gomobile bind -v -target=android/arm64,android/arm,android/amd64,android/386 -androidapi 21 -o "%SOURCE_ROOT%\android\app\libs\masterdnsvpn.aar" ./mobile/ if errorlevel 1 ( diff --git a/android/build_go_mobile.sh b/android/build_go_mobile.sh index e71cdbe..8ddfd59 100644 --- a/android/build_go_mobile.sh +++ b/android/build_go_mobile.sh @@ -42,6 +42,7 @@ cd "$BUILD_DIR" # dependency only in the temporary build tree so the real go.mod/go.sum stay # untouched for upstream/core merge safety. GO111MODULE=on go get "golang.org/x/mobile@${MOBILE_TOOLS_VERSION}" +GO111MODULE=on go mod download gomobile bind \ -v \ From b0e0f009cc65ec7d7b1a4379327b77bcd5342542 Mon Sep 17 00:00:00 2001 From: Farnam Taheri Date: Mon, 11 May 2026 20:43:57 +0330 Subject: [PATCH 3/3] fix(android): run gomobile cleanup from repo root Return to the real repository before removing the temporary gomobile source tree. CI was building the AAR successfully, then the EXIT trap ran git diff from the deleted temp directory and failed with 'Unable to read current working directory'. --- android/build_go_mobile.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/android/build_go_mobile.sh b/android/build_go_mobile.sh index 8ddfd59..1a12b86 100644 --- a/android/build_go_mobile.sh +++ b/android/build_go_mobile.sh @@ -30,6 +30,7 @@ mkdir -p android/app/libs BUILD_DIR="$(mktemp -d)" cleanup() { + cd "$ROOT_DIR" rm -rf "$BUILD_DIR" check_go_modules_clean }