diff options
| author | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2025-01-08 09:33:44 +0100 |
|---|---|---|
| committer | Jonatan Rhodin <jonatan.rhodin@mullvad.net> | 2025-01-08 10:48:48 +0100 |
| commit | 1c1ca559b69810904538c2e46c2326d2ebcaa014 (patch) | |
| tree | e42cb4535910bdeeb25018786035a21130e5ff31 | |
| parent | ac9ac4b824b62d60f64be46f69a4678152d64fb5 (diff) | |
| download | mullvadvpn-1c1ca559b69810904538c2e46c2326d2ebcaa014.tar.xz mullvadvpn-1c1ca559b69810904538c2e46c2326d2ebcaa014.zip | |
Add gradle rust plugin
| -rw-r--r-- | .github/workflows/android-app.yml | 85 | ||||
| -rw-r--r-- | .github/workflows/daemon.yml | 1 | ||||
| -rw-r--r-- | .github/workflows/testframework.yml | 1 | ||||
| -rw-r--r-- | android/BuildInstructions.md | 10 | ||||
| -rw-r--r-- | android/app/build.gradle.kts | 110 | ||||
| -rw-r--r-- | android/build.gradle.kts | 3 | ||||
| -rwxr-xr-x | android/build.sh (renamed from build-apk.sh) | 61 | ||||
| -rw-r--r-- | android/buildSrc/src/main/kotlin/Versions.kt | 1 | ||||
| -rw-r--r-- | android/docker/Dockerfile | 2 | ||||
| -rw-r--r-- | android/docs/BuildInstructions.macos.md | 24 | ||||
| -rw-r--r-- | android/docs/DebugInstructions.md | 16 | ||||
| -rw-r--r-- | android/gradle/libs.versions.toml | 6 | ||||
| -rwxr-xr-x | android/scripts/update-lockfile.sh | 4 | ||||
| -rw-r--r-- | building/android-container-image.txt | 2 | ||||
| -rwxr-xr-x | building/containerized-build.sh | 2 |
15 files changed, 176 insertions, 152 deletions
diff --git a/.github/workflows/android-app.yml b/.github/workflows/android-app.yml index 5e784b5d69..a035439ead 100644 --- a/.github/workflows/android-app.yml +++ b/.github/workflows/android-app.yml @@ -98,7 +98,7 @@ jobs: retention-days: 7 generate-relay-list: - name: Generate relay list + name: Generate relay list # Used by wait for jobs. needs: prepare runs-on: ubuntu-latest container: @@ -129,11 +129,8 @@ jobs: - name: Generate if: steps.cache-relay-list.outputs.cache-hit != 'true' - env: - RUSTFLAGS: --deny warnings - run: | - mkdir -p android/app/build/extraAssets - cargo run --bin relay_list > android/app/build/extraAssets/relays.json + shell: bash + run: ./android/gradlew -p android generateRelayList - name: Upload uses: actions/upload-artifact@v4 @@ -144,7 +141,7 @@ jobs: retention-days: 7 build-native: - name: Build native + name: Build native # Used by wait for jobs. needs: prepare runs-on: ubuntu-latest container: @@ -152,18 +149,14 @@ jobs: strategy: matrix: include: - - arch: "x86_64" - abi: "x86_64" - target: "x86_64-linux-android" - - arch: "i686" - abi: "x86" - target: "i686-linux-android" - - arch: "aarch64" - abi: "arm64-v8a" - target: "aarch64-linux-android" - - arch: "armv7" - abi: "armeabi-v7a" - target: "armv7-linux-androideabi" + - abi: "x86_64" + task-variant: "X86_64" + - abi: "x86" + task-variant: "X86" + - abi: "arm64-v8a" + task-variant: "Arm64" + - abi: "armeabi-v7a" + task-variant: "Arm" steps: # Fix for HOME path overridden by GH runners when building in containers, see: # https://github.com/actions/runner/issues/863 @@ -197,27 +190,28 @@ jobs: env: cache_hash: ${{ steps.native-lib-cache-hash.outputs.native_lib_hash }} with: - path: ./android/app/build/extraJni + path: ./android/app/build/rustJniLibs/android key: android-native-libs-${{ runner.os }}-${{ matrix.abi }}-${{ env.cache_hash }} - name: Build native libraries if: steps.cache-native-libs.outputs.cache-hit != 'true' - env: - RUSTFLAGS: --deny warnings - BUILD_TYPE: debug - run: | - ARCHITECTURES="${{ matrix.abi }}" - UNSTRIPPED_LIB_PATH="$CARGO_TARGET_DIR/${{ matrix.target }}/$BUILD_TYPE/libmullvad_jni.so" - STRIPPED_LIB_PATH="./android/app/build/extraJni/${{ matrix.abi }}/libmullvad_jni.so" - NDK_TOOLCHAIN_STRIP_TOOL="$NDK_TOOLCHAIN_DIR/llvm-strip" - cargo build --target ${{ matrix.target }} --verbose --package mullvad-jni --features api-override - $NDK_TOOLCHAIN_STRIP_TOOL --strip-debug --strip-unneeded -o "$STRIPPED_LIB_PATH" "$UNSTRIPPED_LIB_PATH" + uses: burrunan/gradle-cache-action@v1 + with: + job-id: jdk17 + arguments: cargoBuild${{ matrix.task-variant }} + gradle-version: wrapper + build-root-directory: android + execution-only-caches: false + # Disable if logs are hard to follow. + concurrent: true + read-only: ${{ github.ref != 'refs/heads/main' }} + - name: Upload native libs uses: actions/upload-artifact@v4 with: - name: native-libs-${{ matrix.arch }} - path: android/app/build/extraJni + name: native-libs-${{ matrix.abi }} + path: android/app/build/rustJniLibs/android if-no-files-found: error retention-days: 7 @@ -290,7 +284,9 @@ jobs: uses: burrunan/gradle-cache-action@v1 with: job-id: jdk17 - arguments: compileOssProdDebugKotlin + arguments: | + compileOssProdDebugKotlin + -x cargoBuild gradle-version: wrapper build-root-directory: android execution-only-caches: false @@ -299,24 +295,26 @@ jobs: read-only: ${{ github.ref != 'refs/heads/main' }} - name: Wait for other jobs (native, relay list) - uses: kachick/wait-other-jobs@v2.0.3 + uses: kachick/wait-other-jobs@v3.6.0 with: + wait-seconds-before-first-polling: '0' wait-list: | [ { "workflowFile": "android-app.yml", - "jobName": "build-native" + "jobMatchMode": "prefix", + "jobName": "Build native" }, { "workflowFile": "android-app.yml", - "jobName": "generate-relay-list" + "jobName": "Generate relay list" } ] - uses: actions/download-artifact@v4 with: pattern: native-libs-* - path: android/app/build/extraJni + path: android/app/build/rustJniLibs/android merge-multiple: true - uses: actions/download-artifact@v4 @@ -328,7 +326,9 @@ jobs: uses: burrunan/gradle-cache-action@v1 with: job-id: jdk17 - arguments: assembleOssProdDebug + arguments: | + assembleOssProdDebug + -x cargoBuild gradle-version: wrapper build-root-directory: android execution-only-caches: true @@ -341,7 +341,9 @@ jobs: if: github.event.inputs.run_firebase_tests == 'true' with: job-id: jdk17 - arguments: assemblePlayStagemoleDebug + arguments: | + assemblePlayStagemoleDebug + -x cargoBuild gradle-version: wrapper build-root-directory: android execution-only-caches: true @@ -396,7 +398,10 @@ jobs: uses: burrunan/gradle-cache-action@v1 with: job-id: jdk17 - arguments: ${{ matrix.assemble-command }} + arguments: | + ${{ matrix.assemble-command }} + -x cargoBuild + -x generateRelayList gradle-version: wrapper build-root-directory: android execution-only-caches: false diff --git a/.github/workflows/daemon.yml b/.github/workflows/daemon.yml index 2b6241d76f..2727d6697b 100644 --- a/.github/workflows/daemon.yml +++ b/.github/workflows/daemon.yml @@ -10,7 +10,6 @@ on: - '!.github/CODEOWNERS' - '!android/**' - '!audits/**' - - '!build-apk.sh' - '!build.sh' - '!ci/**' - 'ci/check-rust.sh' diff --git a/.github/workflows/testframework.yml b/.github/workflows/testframework.yml index f8d729d271..288aee4273 100644 --- a/.github/workflows/testframework.yml +++ b/.github/workflows/testframework.yml @@ -10,7 +10,6 @@ on: - '.github/workflows/daemon.yml' - '!android/**' - '!audits/**' - - '!build-apk.sh' - '!build.sh' - '!ci/**' - '!clippy.toml' diff --git a/android/BuildInstructions.md b/android/BuildInstructions.md index c80214f013..e89d1b3102 100644 --- a/android/BuildInstructions.md +++ b/android/BuildInstructions.md @@ -118,10 +118,10 @@ Linux distro: ```bash cd "$ANDROID_HOME" # Or some other directory to place the Android NDK - wget https://dl.google.com/android/repository/android-ndk-r27b-linux.zip - unzip android-ndk-r27b-linux.zip + wget https://dl.google.com/android/repository/android-ndk-r27c-linux.zip + unzip android-ndk-r27c-linux.zip - cd android-ndk-r27b + cd android-ndk-r27c export ANDROID_NDK_HOME="$PWD" ``` @@ -162,7 +162,7 @@ Run the following command to download wireguard-go-rs submodule: `git submodule ### Debug build Run the following command to build a debug build: ```bash -../build-apk.sh --dev-build +../android/build.sh --dev-build ``` ### Release build @@ -170,7 +170,7 @@ Run the following command to build a debug build: 2. Move, copy or symlink the directory from step 1 to [./credentials/](./credentials/) (`<repository>/android/credentials/`). 3. Run the following command to build: ```bash - ../build-apk.sh --app-bundle + ../android/build.sh --app-bundle ``` ## Configure signing key diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 5fed7575d4..dd1444302c 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -1,7 +1,9 @@ import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties import com.android.build.gradle.internal.tasks.factory.dependsOn import com.github.triplet.gradle.androidpublisher.ReleaseStatus +import java.io.ByteArrayOutputStream import java.io.FileInputStream +import java.io.FileOutputStream import java.util.Properties import org.gradle.internal.extensions.stdlib.capitalized @@ -13,6 +15,7 @@ plugins { alias(libs.plugins.kotlin.ksp) alias(libs.plugins.compose) alias(libs.plugins.protobuf.core) + alias(libs.plugins.rust.android.gradle) id(Dependencies.junit5AndroidPluginId) version Versions.junit5Plugin } @@ -21,7 +24,6 @@ val repoRootPath = rootProject.projectDir.absoluteFile.parentFile.absolutePath val extraAssetsDirectory = layout.buildDirectory.dir("extraAssets").get() val relayListPath = extraAssetsDirectory.file("relays.json").asFile val defaultChangelogAssetsDirectory = "$repoRootPath/android/src/main/play/release-notes/" -val extraJniDirectory = layout.buildDirectory.dir("extraJni").get() val credentialsPath = "${rootProject.projectDir}/credentials" val keystorePropertiesFile = file("$credentialsPath/keystore.properties") @@ -35,6 +37,7 @@ android { namespace = "net.mullvad.mullvadvpn" compileSdk = Versions.compileSdkVersion buildToolsVersion = Versions.buildToolsVersion + ndkVersion = Versions.ndkVersion defaultConfig { val localProperties = gradleLocalProperties(rootProject.projectDir, providers) @@ -126,7 +129,6 @@ android { .getOrDefault("OVERRIDE_CHANGELOG_DIR", defaultChangelogAssetsDirectory) assets.srcDirs(extraAssetsDirectory, changelogDir) - jniLibs.srcDirs(extraJniDirectory) } } @@ -239,12 +241,14 @@ android { createDistBundle.dependsOn("bundle$capitalizedVariantName") - // Ensure all relevant assemble tasks depend on our ensure tasks. - tasks["assemble$capitalizedVariantName"].apply { - dependsOn(tasks["ensureRelayListExist"]) - dependsOn(tasks["ensureJniDirectoryExist"]) - dependsOn(tasks["ensureValidVersionCode"]) - } + // Ensure we have relay list ready before merging assets. + tasks["merge${capitalizedVariantName}Assets"].dependsOn(tasks["generateRelayList"]) + + // Ensure that we have all the JNI libs before merging them. + tasks["merge${capitalizedVariantName}JniLibFolders"].dependsOn("cargoBuild") + + // Ensure all relevant assemble tasks depend on our ensure task. + tasks["assemble$capitalizedVariantName"].dependsOn(tasks["ensureValidVersionCode"]) } } @@ -255,6 +259,80 @@ junitPlatform { } } +cargo { + val isReleaseBuild = isReleaseBuild() + val enableApiOverride = !isReleaseBuild || isAlphaOrDevBuild() + module = repoRootPath + libname = "mullvad-jni" + // All available targets: + // https://github.com/mozilla/rust-android-gradle/tree/master?tab=readme-ov-file#targets + targets = + gradleLocalProperties(rootProject.projectDir, providers) + .getProperty("CARGO_TARGETS") + ?.split(",") ?: listOf("arm", "arm64", "x86", "x86_64") + profile = + if (isReleaseBuild) { + "release" + } else { + "debug" + } + prebuiltToolchains = true + targetDirectory = "$repoRootPath/target" + features { + if (enableApiOverride) { + defaultAnd(arrayOf("api-override")) + } + } + targetIncludes = arrayOf("libmullvad_jni.so") + extraCargoBuildArguments = buildList { + add("--package=mullvad-jni") + if (isReleaseBuild) { + add("--locked") + } + } +} + +tasks.register<Exec>("generateRelayList") { + workingDir = File(repoRootPath) + standardOutput = ByteArrayOutputStream() + + onlyIf { isReleaseBuild() || !relayListPath.exists() } + + commandLine("cargo", "run", "--bin", "relay_list") + + doLast { + val output = standardOutput as ByteArrayOutputStream + // Create file if needed + relayListPath.parentFile.mkdirs() + relayListPath.createNewFile() + FileOutputStream(relayListPath).use { it.write(output.toByteArray()) } + } +} + +tasks.register<Exec>("cargoClean") { + workingDir = File(repoRootPath) + commandLine("cargo", "clean") +} + +if ( + gradleLocalProperties(rootProject.projectDir, providers) + .getProperty("CLEAN_CARGO_BUILD") + ?.toBoolean() != false +) { + tasks["clean"].dependsOn("cargoClean") +} + +// This is a hack and will not work correctly under all scenarios. +// See DROID-1696 for how we can improve this. +fun isReleaseBuild() = + gradle.startParameter.getTaskNames().any { it.contains("release", ignoreCase = true) } + +fun isAlphaOrDevBuild(): Boolean { + val localProperties = gradleLocalProperties(rootProject.projectDir, providers) + val versionName = generateVersionName(localProperties) + return versionName.contains("dev") || versionName.contains("alpha") +} + androidComponents { beforeVariants { variantBuilder -> variantBuilder.enable = @@ -276,22 +354,6 @@ configure<org.owasp.dependencycheck.gradle.extension.DependencyCheckExtension> { skipConfigurations = listOf("lintClassPath") } -tasks.register("ensureRelayListExist") { - doLast { - if (!relayListPath.exists()) { - throw GradleException("Missing relay list: $relayListPath") - } - } -} - -tasks.register("ensureJniDirectoryExist") { - doLast { - if (!extraJniDirectory.asFile.exists()) { - throw GradleException("Missing JNI directory: $extraJniDirectory") - } - } -} - // This is a safety net to avoid generating too big version codes, since that could potentially be // hard and inconvenient to recover from. tasks.register("ensureValidVersionCode") { diff --git a/android/build.gradle.kts b/android/build.gradle.kts index 24bcb0e4d0..b43f4fec86 100644 --- a/android/build.gradle.kts +++ b/android/build.gradle.kts @@ -14,6 +14,7 @@ plugins { alias(libs.plugins.kotlin.ksp) apply false alias(libs.plugins.kotlin.parcelize) apply false alias(libs.plugins.protobuf.core) apply false + alias(libs.plugins.rust.android.gradle) apply false alias(libs.plugins.detekt) apply true alias(libs.plugins.dependency.versions) apply true @@ -68,6 +69,8 @@ buildscript { classpath("$prebuilt:linux-x86_64@tar.gz") classpath("$prebuilt:macos-aarch64@tar.gz") classpath("$prebuilt:macos-x86_64@tar.gz") + + classpath("org.mozilla.rust-android-gradle:plugin:${libs.versions.rust.android.gradle}") } } diff --git a/build-apk.sh b/android/build.sh index da09e06479..43dc034ff8 100755 --- a/build-apk.sh +++ b/android/build.sh @@ -18,15 +18,11 @@ BUILD_BUNDLE="no" BUNDLE_TASKS=(createPlayProdReleaseDistBundle) RUN_PLAY_PUBLISH_TASKS="no" PLAY_PUBLISH_TASKS=() -CARGO_ARGS=( "--release" ) -CARGO_TARGET_DIR=${CARGO_TARGET_DIR:-"target"} -SKIP_STRIPPING=${SKIP_STRIPPING:-"no"} while [ -n "${1:-""}" ]; do if [[ "${1:-""}" == "--dev-build" ]]; then BUILD_TYPE="debug" GRADLE_BUILD_TYPE="debug" - CARGO_ARGS=() GRADLE_TASKS=(createOssProdDebugDistApk) BUNDLE_TASKS=(createOssProdDebugDistBundle) elif [[ "${1:-""}" == "--fdroid" ]]; then @@ -37,15 +33,13 @@ while [ -n "${1:-""}" ]; do BUILD_BUNDLE="yes" elif [[ "${1:-""}" == "--enable-play-publishing" ]]; then RUN_PLAY_PUBLISH_TASKS="yes" - elif [[ "${1:-""}" == "--skip-stripping" ]]; then - SKIP_STRIPPING="yes" fi shift 1 done if [[ "$GRADLE_BUILD_TYPE" == "release" ]]; then - if [ ! -f "$SCRIPT_DIR/android/credentials/keystore.properties" ]; then + if [ ! -f "$SCRIPT_DIR/credentials/keystore.properties" ]; then echo "ERROR: No keystore.properties file found" >&2 echo " Please configure the signing keys as described in the README" >&2 exit 1 @@ -54,28 +48,16 @@ fi if [[ "$BUILD_TYPE" == "release" ]]; then if [[ "$PRODUCT_VERSION" == *"-dev-"* ]]; then - CARGO_ARGS+=( "--features" "api-override" ) GRADLE_TASKS+=(createPlayDevmoleReleaseDistApk createPlayStagemoleReleaseDistApk) BUNDLE_TASKS+=(createPlayDevmoleReleaseDistBundle createPlayStagemoleReleaseDistBundle) elif [[ "$PRODUCT_VERSION" == *"-alpha"* ]]; then echo "Removing old Rust build artifacts" - CARGO_ARGS+=( "--locked" ) - cargo clean - CARGO_ARGS+=( "--features" "api-override" ) GRADLE_TASKS+=(createPlayStagemoleReleaseDistApk) BUNDLE_TASKS+=(createPlayStagemoleReleaseDistBundle) PLAY_PUBLISH_TASKS=(publishPlayStagemoleReleaseBundle) - else - echo "Removing old Rust build artifacts" - CARGO_ARGS+=( "--locked" ) - cargo clean fi -else - CARGO_ARGS+=( "--features" "api-override" ) fi -pushd "$SCRIPT_DIR/android" - # Fallback to the system-wide gradle command if the gradlew script is removed. # It is removed by the F-Droid build process before the build starts. if [ -f "gradlew" ]; then @@ -89,48 +71,7 @@ else fi $GRADLE_CMD --console plain clean -mkdir -p "app/build/extraAssets" -mkdir -p "app/build/extraJni" -popd - -for ARCHITECTURE in ${ARCHITECTURES:-aarch64 armv7 x86_64 i686}; do - case "$ARCHITECTURE" in - "x86_64") - TARGET="x86_64-linux-android" - ABI="x86_64" - ;; - "i686") - TARGET="i686-linux-android" - ABI="x86" - ;; - "aarch64") - TARGET="aarch64-linux-android" - ABI="arm64-v8a" - ;; - "armv7") - TARGET="armv7-linux-androideabi" - ABI="armeabi-v7a" - ;; - esac - - echo "Building mullvad-daemon for $TARGET" - cargo build "${CARGO_ARGS[@]}" --target "$TARGET" --package mullvad-jni - - STRIP_TOOL="${NDK_TOOLCHAIN_DIR}/llvm-strip" - TARGET_LIB_PATH="$SCRIPT_DIR/android/app/build/extraJni/$ABI/libmullvad_jni.so" - UNSTRIPPED_LIB_PATH="$CARGO_TARGET_DIR/$TARGET/$BUILD_TYPE/libmullvad_jni.so" - - if [[ "$SKIP_STRIPPING" == "yes" ]]; then - cp "$UNSTRIPPED_LIB_PATH" "$TARGET_LIB_PATH" - else - $STRIP_TOOL --strip-debug --strip-unneeded -o "$TARGET_LIB_PATH" "$UNSTRIPPED_LIB_PATH" - fi -done - -echo "Updating relays.json..." -cargo run --bin relay_list "${CARGO_ARGS[@]}" > android/app/build/extraAssets/relays.json -cd "$SCRIPT_DIR/android" $GRADLE_CMD --console plain "${GRADLE_TASKS[@]}" if [[ "$BUILD_BUNDLE" == "yes" ]]; then diff --git a/android/buildSrc/src/main/kotlin/Versions.kt b/android/buildSrc/src/main/kotlin/Versions.kt index 223331cfc5..d08012324b 100644 --- a/android/buildSrc/src/main/kotlin/Versions.kt +++ b/android/buildSrc/src/main/kotlin/Versions.kt @@ -4,6 +4,7 @@ object Versions { const val buildToolsVersion = "35.0.0" const val minSdkVersion = 26 const val targetSdkVersion = 35 + const val ndkVersion = "27.2.12479018" const val junitJupiter = "5.11.4" const val junit5Android = "1.6.0" diff --git a/android/docker/Dockerfile b/android/docker/Dockerfile index 17a68510ed..32175853a6 100644 --- a/android/docker/Dockerfile +++ b/android/docker/Dockerfile @@ -8,7 +8,7 @@ # -v $GRADLE_CACHE_VOLUME_NAME:/root/.gradle:Z \ # -v $ANDROID_CREDENTIALS_DIR:/build/android/credentials:Z \ # -v /path/to/repository_root:/build:Z \ -# mullvadvpn-app-build-android ./build-apk.sh --dev-build +# mullvadvpn-app-build-android ./android/build.sh --dev-build # # See the base image Dockerfile in the repository root (../../Dockerfile) # for more information. diff --git a/android/docs/BuildInstructions.macos.md b/android/docs/BuildInstructions.macos.md index 78bf345d1d..0368c1e917 100644 --- a/android/docs/BuildInstructions.macos.md +++ b/android/docs/BuildInstructions.macos.md @@ -17,7 +17,7 @@ brew install --cask android-studio Install the following packages: ```bash -brew install protobuf gcc go openjdk@17 rustup-init +brew install protobuf gcc go openjdk@17 rustup-init python3 ``` > __*NOTE:*__ Ensure that you setup `openjdk@17` to be the active JDK, follow instructions in @@ -38,7 +38,7 @@ Open Android Studio -> Tools -> SDK Manager, and install `Android SDK Command-li Install the necessary Android SDK tools ```bash -~/Library/Android/sdk/cmdline-tools/latest/bin/sdkmanager "platforms;android-35" "build-tools;35.0.0" "platform-tools" "ndk;27.1.12297006" +~/Library/Android/sdk/cmdline-tools/latest/bin/sdkmanager "platforms;android-35" "build-tools;35.0.0" "platform-tools" "ndk;27.2.12479018" ``` Install Android targets @@ -50,7 +50,7 @@ Export the following environmental variables, and possibly store them for exampl `~/.zprofile` or `~/.zshrc` file: ```bash export ANDROID_HOME="$HOME/Library/Android/sdk" -export ANDROID_NDK_HOME="$ANDROID_HOME/ndk/27.1.12297006" +export ANDROID_NDK_HOME="$ANDROID_HOME/ndk/27.2.12479018" export NDK_TOOLCHAIN_DIR="$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/darwin-x86_64/bin" export AR_aarch64_linux_android="$NDK_TOOLCHAIN_DIR/llvm-ar" export AR_armv7_linux_androideabi="$NDK_TOOLCHAIN_DIR/llvm-ar" @@ -74,10 +74,23 @@ git submodule update --init --recursive --depth=1 wireguard-go-rs ``` ## 4. Debug build + +### Android Studio + +Create the file `android/local.properties` if it does not exist and add the following line: + +```bash +rust.pythonCommand=/opt/homebrew/bin/python3 +``` + +You should now be able to run the app directly from Android Studio. + +### `android/build.sh` + Run the build script in the root of the project to assemble all the native libraries and the app: ```bash -./build-apk.sh --dev-build +./android/build.sh --dev-build ``` Once the build is complete you should receive a message looking similar to this: @@ -92,9 +105,6 @@ Once the build is complete you should receive a message looking similar to this: ********************************** ``` -Your native binaries have now been built, any subsequent builds that does not have changes to the -native code can be done in Android Studio or using gradle. - # Build options and configuration For configuring signing or options to your build continue with the general [build instructions](../BuildInstructions.md). diff --git a/android/docs/DebugInstructions.md b/android/docs/DebugInstructions.md index e4c9100e0e..9faa5237b2 100644 --- a/android/docs/DebugInstructions.md +++ b/android/docs/DebugInstructions.md @@ -1,15 +1,13 @@ ## Debugging the native libraries in Android Studio with LLDB -1. Make sure the native libraries have been built with debug symbols. If using the `build-apk.sh` - script, run `SKIP_STRIPPING=yes ../build-apk.sh --dev-build`. -2. In Android Studio, go to `Run -> Edit configurations...` -3. Make sure the `app` configuration is selected. -4. In the `Debugger` tab, select `Dual (Java + Native)` -5. Start debugging the app as usual from Android Studio. The app should now stop on a SIGURG signal. -6. Select the `LLDB` tab in the debugger. Now you can set breakpoints etc, e.g. +1. In Android Studio, go to `Run -> Edit configurations...` +2. Make sure the `app` configuration is selected. +3. In the `Debugger` tab, select `Dual (Java + Native)` +4. Start debugging the app as usual from Android Studio. The app should now stop on a SIGURG signal. +5. Select the `LLDB` tab in the debugger. Now you can set breakpoints etc, e.g. `breakpoint set -n open_tun` -7. Before continuing run `pro hand -p true -s false SIGURG` -8. Click `Resume Program` and the app will resume until the breakpoint is hit. +6. Before continuing run `pro hand -p true -s false SIGURG` +7. Click `Resume Program` and the app will resume until the breakpoint is hit. NOTE: When running LLDB, Android Studio can sometimes get into a state where it will try to connect to the debugger when running the app normally, which blocks the app from starting. diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index 3428c8a8b9..bab6a4fd49 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -54,6 +54,9 @@ kotlinx-serialization = "2.1.0" protobuf-gradle-plugin = "0.9.4" protobuf = "4.29.2" +# Rust Android Gradle +rust-android-gradle = "0.9.5" + # Misc commonsvalidator = "1.9.0" dependency-check = "10.0.4" @@ -186,6 +189,9 @@ protobuf-protoc = { id = "com.google.protobuf:protoc", version.ref = "protobuf" grpc-protoc-gen-grpc-java = { id = "io.grpc:protoc-gen-grpc-java", version.ref = "grpc" } grpc-protoc-gen-grpc-kotlin = { id = "io.grpc:protoc-gen-grpc-kotlin", version.ref = "grpc-kotlin-jar" } +# Rust Android Gradle +rust-android-gradle = { id = "org.mozilla.rust-android-gradle.rust-android", version.ref = "rust-android-gradle" } + # Misc dependency-check = { id = "org.owasp.dependencycheck", version.ref = "dependency-check" } dependency-versions = { id = "com.github.ben-manes.versions", version.ref = "dependency-versions" } diff --git a/android/scripts/update-lockfile.sh b/android/scripts/update-lockfile.sh index e400caed72..0c20ae31c3 100755 --- a/android/scripts/update-lockfile.sh +++ b/android/scripts/update-lockfile.sh @@ -20,8 +20,8 @@ GRADLE_TASKS=( "lint" ) EXCLUDED_GRADLE_TASKS=( - "-xensureRelayListExist" - "-xensureJniDirectoryExist" + "-xgenerateRelayList" + "-xcargoBuild" ) export GRADLE_OPTS diff --git a/building/android-container-image.txt b/building/android-container-image.txt index 0f1f220ce4..973dbf7a5c 100644 --- a/building/android-container-image.txt +++ b/building/android-container-image.txt @@ -1 +1 @@ -ghcr.io/mullvad/mullvadvpn-app-build-android:7b6bc0f44 +ghcr.io/mullvad/mullvadvpn-app-build-android:7b6bc0f44
\ No newline at end of file diff --git a/building/containerized-build.sh b/building/containerized-build.sh index 86b0148a72..16e09ea8f2 100755 --- a/building/containerized-build.sh +++ b/building/containerized-build.sh @@ -18,7 +18,7 @@ case $platform in shift 1 ;; android) - build_command=("./build-apk.sh") + build_command=("./android/build.sh") shift 1 ;; *) |
