From 629097b1f90b504db3c14a1742b9da964641dc0e Mon Sep 17 00:00:00 2001 From: mcarare <48995920+mcarare@users.noreply.github.com> Date: Wed, 3 Dec 2025 15:25:28 +0200 Subject: [PATCH] Update AGP to 9.0.0-beta03 - Update `android-gradle-plugin` version in version catalog. - Remove `kotlin-android` plugin alias from version catalog and root build file. - Migrate `android.applicationVariants.configureEach` logic in `app/build.gradle` to `androidComponents` API (`beforeVariants` and `onVariants`) to support AGP 9.0. - Use `variant.buildConfigFields.put` instead of `buildConfigField`. - Update version code generation logic to use `variant.outputs` within `onVariants`. - Remove `variantFilter` block in favor of `beforeVariants` disabling. - Migrate `kotlinOptions.allWarningsAsErrors` to `tasks.withType(KotlinCompile).compilerOptions`. --- app/build.gradle | 205 ++++++++++++++------------------------ build.gradle | 17 +++- gradle/libs.versions.toml | 3 +- 3 files changed, 89 insertions(+), 136 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 06e62e6b8..96fde11e6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,15 +6,87 @@ plugins { alias libs.plugins.android.application alias libs.plugins.compose.compiler alias libs.plugins.dependency.analysis - alias libs.plugins.kotlin.android } apply from: "$project.rootDir/automation/gradle/versionCode.gradle" +def baseVersionCode = generatedVersionCode + +import com.android.build.api.variant.BuildConfigField import com.android.build.api.variant.FilterConfiguration -import com.android.build.gradle.internal.tasks.AppPreBuildTask import groovy.json.JsonOutput +androidComponents { + beforeVariants(selector().withBuildType("release")) { variantBuilder -> + variantBuilder.enable = false + } + + onVariants(selector().all()) { variant -> + // ------------------------------------------------------------------------- + // 1. Sentry Token + // ------------------------------------------------------------------------- + String sentryToken = "null" + try { + File tokenFile = file("${rootDir}/.sentry_token") + if (tokenFile.exists()) { + sentryToken = '"' + tokenFile.text.trim() + '"' + println("(Added Sentry token from file)") + } + } catch (Exception ignored) { } + + variant.buildConfigFields.put("SENTRY_TOKEN", + new BuildConfigField("String", sentryToken, "Sentry Token")) + + // ------------------------------------------------------------------------- + // 2. Crash Reporting & Telemetry + // ------------------------------------------------------------------------- + boolean crashReporting = project.hasProperty("crashReportEnabled") && project.property("crashReportEnabled") == "true" + variant.buildConfigFields.put("CRASH_REPORTING_ENABLED", + new BuildConfigField("boolean", crashReporting.toString(), "Crash Reporting")) + + boolean telemetry = project.hasProperty("telemetry") && project.property("telemetry") == "true" + variant.buildConfigFields.put("TELEMETRY_ENABLED", + new BuildConfigField("boolean", telemetry.toString(), "Telemetry")) + + // ------------------------------------------------------------------------- + // 3. Official Build Flag + // ------------------------------------------------------------------------- + boolean official = project.hasProperty("official") || gradle.hasProperty("localProperties.official") + variant.buildConfigFields.put("MOZILLA_OFFICIAL", + new BuildConfigField("Boolean", official.toString(), "Official Build")) + + // ------------------------------------------------------------------------- + // 4. Version Codes (Only if IS_RELEASED is true) + // ------------------------------------------------------------------------- + // Note: In the new API, checking buildConfigFields defined in build types is harder. + // We check the build type name directly instead. + if (variant.buildType == "nightly") { + // Logic adapted for new API + def baseCode = baseVersionCode + if (baseCode % 2 != 0) baseCode += 1 // Ensure even + + variant.outputs.each { output -> + def abiFilter = output.filters.find { it.filterType == FilterConfiguration.FilterType.ABI } // Note: Accessing specific ABI names in AGP 9 via 'filters' can be tricky + def abiName = abiFilter?.identifier // This returns "x86", "arm64-v8a", etc. + + // Simplified mapping for demonstration: + def addedCode = 0 + if (project.hasProperty("aab")) { + addedCode = 1 + } else if (abiName != null) { + // FIX: Check the abiName identifier instead of output.name + if (abiName == "x86_64") addedCode = 6 + else if (abiName == "x86") addedCode = 4 + else if (abiName == "arm64-v8a") addedCode = 2 + } + + output.versionCode.set(baseCode + addedCode) + output.versionName.set(Config.releaseVersionName(project)) + } + } + } +} + android { defaultConfig { applicationId "org.mozilla.reference.browser" @@ -35,7 +107,7 @@ android { def releaseTemplate = { minifyEnabled true - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' matchingFallbacks = ['release'] // Use on the "release" build type in dependencies (AARs) if (gradle.hasProperty("localProperties.autosignReleaseWithDebugKey")) { @@ -61,12 +133,6 @@ android { } } - variantFilter { // There's a "release" build type that exists by default that we don't use (it's replaced by "nightly" and "beta") - if (buildType.name == 'release') { - setIgnore true - } - } - testOptions { execution = 'ANDROIDX_TEST_ORCHESTRATOR' animationsDisabled = true @@ -95,127 +161,6 @@ kotlin { jvmToolchain(Config.jvmTargetCompatibility) } -def baseVersionCode = generatedVersionCode - -android.applicationVariants.configureEach { variant -> - -// ------------------------------------------------------------------------------------------------- -// Sentry: Read token from local file if it exists (Only release builds) -// ------------------------------------------------------------------------------------------------- - print("Sentry token: "+ variant.name) - try { - def token = new File("${rootDir}/.sentry_token").text.trim() - buildConfigField 'String', 'SENTRY_TOKEN', '"' + token + '"' - println "(Added from .sentry_token file)" - } catch (FileNotFoundException ignored) { - buildConfigField 'String', 'SENTRY_TOKEN', 'null' - println(" :( ") - } - -// ------------------------------------------------------------------------------------------------- -// Activating crash reports with command line parameter. -// ------------------------------------------------------------------------------------------------- - if (project.hasProperty("crashReportEnabled") && project.property("crashReportEnabled") == "true") { - buildConfigField 'boolean', 'CRASH_REPORTING_ENABLED', 'true' - } else { - buildConfigField 'boolean', 'CRASH_REPORTING_ENABLED', 'false' - } - -// ------------------------------------------------------------------------------------------------- -// Activating telemetry with command line paramter. -// ------------------------------------------------------------------------------------------------- - -if (project.hasProperty("telemetry") && project.property("telemetry") == "true") { - buildConfigField 'boolean', 'TELEMETRY_ENABLED', 'true' -} else { - buildConfigField 'boolean', 'TELEMETRY_ENABLED', 'false' -} - -// ------------------------------------------------------------------------------------------------- -// Generating version codes for Google Play -// ------------------------------------------------------------------------------------------------- - if (variant.buildType.buildConfigFields['IS_RELEASED']?.value) { - // The Google Play Store does not allow multiple APKs for the same app that all have the - // same version code. Therefore we need to have different version codes for our ARM and x86 - // builds. See https://developer.android.com/studio/publish/versioning - - // Our x86 builds need a higher version code to avoid installing ARM builds on an x86 device - // with ARM compatibility mode. - - // AAB builds need a version code that is distinct from any APK builds. Since AAB and APK - // builds may run in parallel, AAB and APK version codes might be based on the same - // (minute granularity) time of day. To avoid conflicts, we ensure the minute portion - // of the version code is even for APKs and odd for AABs. - - def versionName = Config.releaseVersionName(project) - - variant.outputs.each { output -> - def abi = output.getFilter(FilterConfiguration.FilterType.ABI.name()) - def aab = project.hasProperty("aab") - - // ensure baseVersionCode is an even number - if (baseVersionCode % 2) { - baseVersionCode = baseVersionCode + 1 - } - - def versionCodeOverride = baseVersionCode - - if (aab) { - // AAB version code is odd - versionCodeOverride = baseVersionCode + 1 - println("versionCode for AAB = $versionCodeOverride") - } else { - // APK version codes are even - if (abi == "x86_64") { - versionCodeOverride = baseVersionCode + 6 - } else if (abi == "x86") { - versionCodeOverride = baseVersionCode + 4 - } else if (abi == "arm64-v8a") { - versionCodeOverride = baseVersionCode + 2 - } else if (abi == "armeabi-v7a") { - versionCodeOverride = baseVersionCode - } - println("versionCode for $abi = $versionCodeOverride") - } - - output.versionNameOverride = versionName - output.versionCodeOverride = versionCodeOverride - } - - // If this is a release build, validate that "versionName" is set - tasks.withType(AppPreBuildTask).configureEach { prebuildTask -> - // You can't add a closure to a variant, so we need to look for an early variant-specific type - // of task (AppPreBuildTask is the first) and filter to make sure we're looking at the task for - // this variant that we're currently configuring - if (prebuildTask.variantName != variant.name) { - return - } - - // Append to the task so the first thing it does is run our validation - prebuildTask.doFirst { - if (!project.hasProperty('versionName')) { - throw new RuntimeException("Release builds require the 'versionName' property to be set.\n" + - "If you're using an IDE, set your build variant to be a \"debug\" type.\n" + - "If you're using the command-line, either build a debug variant instead ('./gradlew assembleDebug')\n" + - "\tor continue building the release build and set the \"versionName\" property ('./gradlew -PversionName=<...> assembleNightly').") - // TODO when Android Studio 3.5.0 is prevalent, we can set the "debug" build type as the default - // https://issuetracker.google.com/issues/36988145#comment59 - } - } - } - } - -// ------------------------------------------------------------------------------------------------- -// BuildConfig: Set flag for official builds; similar to MOZILLA_OFFICIAL in mozilla-central. -// ------------------------------------------------------------------------------------------------- - - if (project.hasProperty("official") || gradle.hasProperty("localProperties.official")) { - buildConfigField 'Boolean', 'MOZILLA_OFFICIAL', 'true' - } else { - buildConfigField 'Boolean', 'MOZILLA_OFFICIAL', 'false' - } -} - // Select the Glean from GeckoView. // `service-sync-logins` requires Glean, which pulls in glean-native, // but that's also provided by geckoview-omni, so now we need to select which one to use. diff --git a/build.gradle b/build.gradle index 399dca7e5..41ee976a6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,8 +1,15 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. import io.gitlab.arturbosch.detekt.Detekt +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile buildscript { + dependencies { + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") { + version { strictly(libs.versions.kotlin.get()) } + } + } + repositories { if (project.hasProperty("googleRepo")) { maven { @@ -31,7 +38,6 @@ plugins { alias libs.plugins.compose.compiler apply false alias libs.plugins.dependency.analysis alias libs.plugins.detekt - alias libs.plugins.kotlin.android apply false } allprojects { @@ -88,9 +94,6 @@ subprojects { } android { - kotlinOptions { - kotlinOptions.allWarningsAsErrors = true - } testOptions { unitTests { @@ -104,6 +107,12 @@ subprojects { } } + tasks.withType(KotlinCompile).configureEach { + compilerOptions { + allWarningsAsErrors = true + } + } + if (project.hasProperty("coverage") && project.name != "support-test") { tasks.withType(Test).configureEach { jacoco.includeNoLocationClasses = true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3d58d8543..0d3364765 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ android-components = "147.0.20251201213546" # AGP -android-gradle-plugin = "8.13.1" +android-gradle-plugin = "9.0.0-beta03" # Kotlin kotlin = "2.2.21" @@ -193,4 +193,3 @@ android-application = { id = "com.android.application", version.ref = "android-g compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } dependency-analysis = { id = "com.autonomousapps.dependency-analysis", version.ref = "dependency-analysis" } detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" } -kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }