Revision control

Copy as Markdown

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$project.rootDir/automation/gradle/versionCode.gradle"
import com.android.build.api.variant.FilterConfiguration
import com.android.build.gradle.internal.tasks.AppPreBuildTask
import groovy.json.JsonOutput
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
android {
defaultConfig {
applicationId "org.mozilla.reference.browser"
minSdkVersion Config.minSdkVersion
compileSdk Config.compileSdkVersion
targetSdkVersion Config.targetSdkVersion
versionCode 1
versionName Config.generateDebugVersionName()
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments clearPackageData: 'true'
}
def releaseTemplate = {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
matchingFallbacks = ['release'] // Use on the "release" build type in dependencies (AARs)
if (gradle.hasProperty("localProperties.autosignReleaseWithDebugKey")) {
signingConfig signingConfigs.debug
}
if (gradle.hasProperty("localProperties.debuggable")) {
debuggable true
}
}
buildFeatures {
buildConfig true
compose true
}
composeOptions {
kotlinCompilerExtensionVersion = libs.versions.compose.compiler.get()
}
buildTypes {
debug {
applicationIdSuffix ".debug"
}
raptor releaseTemplate >> { // the ">>" concatenates the raptor-specific options with the template
applicationIdSuffix ".raptor"
manifestPlaceholders.isRaptorEnabled = "true"
matchingFallbacks = ['release']
}
nightly releaseTemplate >> {
buildConfigField "boolean", "IS_RELEASED", "true"
}
}
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
}
lintOptions {
lintConfig file("lint.xml")
baseline file("lint-baseline.xml")
disable 'GradleDependency', 'AndroidGradlePluginVersion'
}
packagingOptions {
exclude 'META-INF/atomicfu.kotlin_module'
}
splits {
abi {
enable true
reset()
include "x86", "armeabi-v7a", "arm64-v8a", "x86_64"
}
}
namespace 'org.mozilla.reference.browser'
}
kotlin {
jvmToolchain(Config.jvmTargetCompatibility)
}
tasks.withType(KotlinCompile).configureEach {
kotlinOptions.allWarningsAsErrors = true
kotlinOptions.freeCompilerArgs += [
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
"-Xjvm-default=all"
]
}
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
// 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
}
}
}
}
// -------------------------------------------------------------------------------------------------
// 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.
project.configurations.configureEach {
resolutionStrategy.capabilitiesResolution.withCapability("org.mozilla.telemetry:glean-native") {
def toBeSelected = candidates.find { it.id instanceof ModuleComponentIdentifier && it.id.module.contains('geckoview') }
if (toBeSelected != null) {
select(toBeSelected)
}
because 'use GeckoView Glean instead of standalone Glean'
}
}
dependencies {
implementation libs.mozilla.concept.awesomebar
implementation libs.mozilla.concept.engine
implementation libs.mozilla.concept.menu
implementation libs.mozilla.concept.tabstray
implementation libs.mozilla.concept.toolbar
implementation libs.mozilla.concept.storage
implementation libs.mozilla.concept.sync
implementation libs.mozilla.concept.push
implementation libs.mozilla.compose.awesomebar
implementation libs.mozilla.browser.engine.gecko
implementation libs.mozilla.browser.domains
implementation libs.mozilla.browser.tabstray
implementation libs.mozilla.browser.toolbar
implementation libs.mozilla.browser.menu
implementation libs.mozilla.browser.menu2
implementation libs.mozilla.browser.session.storage
implementation libs.mozilla.browser.state
implementation libs.mozilla.browser.storage.sync
implementation libs.mozilla.browser.icons
implementation libs.mozilla.browser.thumbnails
implementation libs.mozilla.feature.accounts.base
implementation libs.mozilla.feature.accounts.push
implementation libs.mozilla.feature.addons
implementation libs.mozilla.feature.app.links
implementation libs.mozilla.feature.awesomebar
implementation libs.mozilla.feature.autofill
implementation libs.mozilla.feature.contextmenu
implementation libs.mozilla.feature.customtabs
implementation libs.mozilla.feature.findinpage
implementation libs.mozilla.feature.media
implementation libs.mozilla.feature.sitepermissions
implementation libs.mozilla.feature.intent
implementation libs.mozilla.feature.search
implementation libs.mozilla.feature.session
implementation libs.mozilla.feature.toolbar
implementation libs.mozilla.feature.tabs
implementation libs.mozilla.feature.downloads
implementation libs.mozilla.feature.prompts
implementation libs.mozilla.feature.push
implementation libs.mozilla.feature.pwa
implementation libs.mozilla.feature.qr
implementation libs.mozilla.feature.readerview
implementation libs.mozilla.feature.syncedtabs
implementation libs.mozilla.feature.webauthn
implementation libs.mozilla.feature.webcompat
implementation libs.mozilla.feature.webnotifications
implementation libs.mozilla.ui.autocomplete
implementation libs.mozilla.ui.colors
implementation libs.mozilla.ui.icons
implementation libs.mozilla.ui.tabcounter
implementation libs.mozilla.ui.widgets
implementation libs.mozilla.service.firefox.accounts
implementation libs.mozilla.service.location
implementation libs.mozilla.service.sync.logins
implementation libs.mozilla.support.images
implementation libs.mozilla.support.utils
implementation libs.mozilla.support.ktx
implementation libs.mozilla.support.rustlog
implementation libs.mozilla.support.rusthttp
implementation libs.mozilla.support.webextensions
implementation libs.mozilla.lib.crash.base
implementation libs.mozilla.lib.crash.sentry
implementation libs.mozilla.lib.push.firebase
implementation libs.mozilla.lib.publicsuffixlist
implementation libs.mozilla.lib.dataprotect
implementation libs.thirdparty.sentry
implementation libs.kotlinx.coroutines.android
implementation libs.androidx.appcompat
implementation libs.androidx.core.ktx
implementation libs.androidx.constraintlayout
implementation libs.androidx.lifecycle.process
implementation libs.androidx.preference.ktx
implementation libs.androidx.swiperefreshlayout
implementation libs.androidx.work.runtime.ktx
implementation platform(libs.androidx.compose.bom)
implementation libs.androidx.activity.compose
implementation libs.androidx.compose.ui.base
implementation libs.androidx.compose.ui.tooling
implementation libs.androidx.compose.foundation
implementation libs.androidx.compose.material
implementation libs.google.material
androidTestImplementation libs.uiautomator
androidTestImplementation libs.junit.ktx
androidTestImplementation libs.espresso.core, {
exclude group: 'com.android.support', module: 'support-annotations'
}
androidTestImplementation(libs.espresso.contrib) {
exclude module: 'appcompat-v7'
exclude module: 'support-v4'
exclude module: 'support-annotations'
exclude module: 'recyclerview-v7'
exclude module: 'design'
exclude module: 'espresso-core'
}
androidTestImplementation libs.espresso.idling.resources
androidTestImplementation libs.espresso.web, {
exclude group: 'com.android.support', module: 'support-annotations'
}
androidTestImplementation libs.mockwebserver
androidTestImplementation libs.tools.test.runner
androidTestImplementation libs.tools.test.rules
androidTestUtil libs.orchestrator
androidTestImplementation libs.espresso.core, {
exclude group: 'com.android.support', module: 'support-annotations'
}
}
// -------------------------------------------------------------------------------------------------
// Task for printing APK information for the requested variant
// Usage: ./gradlew printVariants
// -------------------------------------------------------------------------------------------------
tasks.register('printVariants') {
doLast {
def variants = android.applicationVariants.collect { variant ->
[
apks : variant.outputs.collect { output ->
[
abi : output.getFilter(FilterConfiguration.FilterType.ABI.name()),
fileName: output.outputFile.name
]
},
build_type: variant.buildType.name,
name : variant.name,
]
}
println 'variants: ' + JsonOutput.toJson(variants)
}
}
tasks.register('printGeckoviewVersion') {
doLast {
def configuration = configurations.implementationDependenciesMetadata
def dependencies = configuration.incoming.resolutionResult.allDependencies
def geckoviewDependency = dependencies.find { it.selected.id.moduleIdentifier.group == 'org.mozilla.geckoview' }
println('geckoviewVersion: ' + JsonOutput.toJson(geckoviewDependency.selected.moduleVersion.version))
}
}
if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopsrcdir')) {
if (gradle.hasProperty('localProperties.dependencySubstitutions.geckoviewTopobjdir')) {
ext.topobjdir = gradle."localProperties.dependencySubstitutions.geckoviewTopobjdir"
}
ext.topsrcdir = gradle."localProperties.dependencySubstitutions.geckoviewTopsrcdir"
apply from: "${topsrcdir}/substitute-local-geckoview.gradle"
}
if (gradle.hasProperty('localProperties.autoPublish.android-components.dir')) {
ext.acSrcDir = gradle."localProperties.autoPublish.android-components.dir"
apply from: "../${acSrcDir}/substitute-local-ac.gradle"
}
if (gradle.hasProperty('localProperties.autoPublish.application-services.dir')) {
ext.appServicesSrcDir = gradle."localProperties.autoPublish.application-services.dir"
apply from: "../${appServicesSrcDir}/build-scripts/substitute-local-appservices.gradle"
}