commit 747cf457f2e53f8961a829e7d0a23255e51483b8
parent 5f69ec3ff974cc330813df72e2209e87ad311e4a
Author: Georg Koppen <gk@torproject.org>
Date: Tue, 13 Oct 2020 07:17:10 +0000
[android] Modify build system
Bug 40083: Make locale ordering in BuildConfig deterministic
Bug 40042: Add option do overwrite timestamp in extension version
Bug 40059: Use MOZ_BUILD_DATE for versionCode
At the same time we adapt MOZ_BUILD_DATE to our needs where it is
actually used and not in tor-browser-build. This gives us more
flexibility. See: tor-browser-build#40084.
Bug 40067: Fix reproducibility issue in classes2.dex
We make sure our MOZ_BUILD_DATE gets used as a source for showing date
related information on the Fenix about page.
Bug 40071: Show only supported locales
Bug 40064: Use Gecko Beta for Nightly and Debug variants
Bug 40123: Allow building the instrumented tests apks for variants other than debug
This allows to specify the variant of the instrumented tests via
a `testBuildType` gradle argument. It also applies a workaround for
a R8 issue from https://issuetracker.google.com/issues/140851070.
Bug 40143: Use deterministic date in Test apk
The build config was using Date() when generating the Test apk's
versionName.
Diffstat:
7 files changed, 130 insertions(+), 4 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -403,3 +403,11 @@ CLAUDE.local.md
# Ignore binary base of Tor Browser
.binaries
+
+# Other files modified at build time
+mobile/android/.experimenter.json
+
+# Tor libraries for local builds
+mobile/android/fenix/app/tor-expert-bundle.aar
+mobile/android/fenix/app/src/main/assets/extensions/{73a6fe31-595d-460b-a920-fcc0f8843232}.xpi
+
diff --git a/mobile/android/android-components/plugins/config/src/main/java/ConfigPlugin.kt b/mobile/android/android-components/plugins/config/src/main/java/ConfigPlugin.kt
@@ -21,7 +21,12 @@ object Config {
@JvmStatic
private fun generateDebugVersionName(): String {
- val today = Date()
+ val today = if (System.getenv("MOZ_BUILD_DATE") != null) {
+ val format = SimpleDateFormat("yyyyMMddHHmmss", Locale.US)
+ format.parse(System.getenv("MOZ_BUILD_DATE"))
+ } else {
+ Date()
+ }
// Append the year (2 digits) and week in year (2 digits). This will make it easier to distinguish versions and
// identify ancient versions when debugging issues. However this will still keep the same version number during
// the week so that we do not end up with a lot of versions in tools like Sentry. As an extra this matches the
@@ -60,7 +65,7 @@ object Config {
private val fennecBaseVersionCode by lazy {
val format = SimpleDateFormat("yyyyMMddHHmmss", Locale.US)
val cutoff = format.parse("20141228000000")
- val build = Date()
+ val build = if (System.getenv("MOZ_BUILD_DATE") != null) format.parse(System.getenv("MOZ_BUILD_DATE")) else Date()
Math.floor((build.time - cutoff.time) / (1000.0 * 60.0 * 60.0)).toInt()
}
diff --git a/mobile/android/fenix/app/build.gradle b/mobile/android/fenix/app/build.gradle
@@ -61,7 +61,17 @@ def getBuildId() {
return file("${gradle.mozconfig.topobjdir}/buildid.h").getText('utf-8').split()[2]
}
+def obtainTestBuildType() {
+ def result = "debug";
+ if (project.hasProperty("testBuildType")) {
+ result = project.getProperties().get("testBuildType")
+ }
+ result
+}
+
android {
+ testBuildType obtainTestBuildType()
+
project.maybeConfigForJetpackBenchmark(it)
if (project.hasProperty("testBuildType")) {
// Allowing to configure the test build type via command line flag (./gradlew -PtestBuildType=beta ..)
@@ -314,12 +324,18 @@ android.applicationVariants.configureEach { variant ->
def isDebugOrDCD = isDebug || isDataCollectionDisabled
def useReleaseVersioning = variant.buildType.buildConfigFields['USE_RELEASE_VERSIONING']?.value ?: false
+ // When this is set, a-s doesn't attempt to download NIMBUS_FML.
+ if (gradle.mozconfig.substs.NIMBUS_FML) {
+ System.setProperty("nimbusFml", gradle.mozconfig.substs.NIMBUS_FML)
+ }
+
project.logger.debug("----------------------------------------------")
project.logger.debug("Variant name: " + variant.name)
project.logger.debug("Application ID: " + [variant.applicationId, variant.buildType.applicationIdSuffix].findAll().join())
project.logger.debug("Build type: " + variant.buildType.name)
project.logger.debug("Flavor: " + variant.flavorName)
project.logger.debug("Telemetry enabled: " + !isDebugOrDCD)
+ project.logger.debug("nimbusFml: " + System.getProperty("nimbusFml"))
if (useReleaseVersioning) {
// The Google Play Store does not allow multiple APKs for the same app that all have the
@@ -916,16 +932,24 @@ def getSupportedLocales() {
// This isn't running as a task, instead the array is build when the gradle file is parsed.
// https://github.com/mozilla-mobile/fenix/issues/14175
def foundLocales = new StringBuilder()
+ def languageCodes = []
foundLocales.append("new String[]{")
fileTree("src/main/res").visit { FileVisitDetails details ->
- if (details.file.path.endsWith("${File.separator}strings.xml")) {
+ if (details.file.path.endsWith("${File.separator}torbrowser_strings.xml")) {
def languageCode = details.file.parent.tokenize(File.separator).last().replaceAll('values-', '').replaceAll('-r', '-')
languageCode = (languageCode == "values") ? "en-US" : languageCode
- foundLocales.append("\"").append(languageCode).append("\"").append(",")
+ languageCodes.add(languageCode)
}
}
+ // The order of files in a `FileTree` is not stable, even on a single
+ // computer. Thus we need to sort the `languageCode`s. See: fenix#40083.
+ languageCodes.sort()
+ languageCodes.each {
+ foundLocales.append("\"").append(it).append("\"").append(",")
+ }
+
foundLocales.append("}")
def foundLocalesString = foundLocales.toString().replaceAll(',}', '}')
return foundLocalesString
diff --git a/mobile/android/fenix/app/proguard-rules.pro b/mobile/android/fenix/app/proguard-rules.pro
@@ -28,3 +28,6 @@
# Keep code generated from Glean Metrics
-keep class org.mozilla.fenix.GleanMetrics.** { *; }
+
+# Workaround for 'already has mapping' r8 issue (https://issuetracker.google.com/issues/140851070)
+-keep class com.google.android.gms.common.internal.BaseGmsClient { *; }
diff --git a/mobile/android/fenix/build.gradle b/mobile/android/fenix/build.gradle
@@ -8,6 +8,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
buildscript {
// This logic is duplicated in the allprojects block: I don't know how to fix that.
repositories {
+ mavenLocal()
gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
maven {
url = repository
@@ -42,6 +43,7 @@ plugins {
allprojects {
// This logic is duplicated in the buildscript block: I don't know how to fix that.
repositories {
+ mavenLocal()
gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
maven {
url = repository
diff --git a/mobile/android/fenix/tools/tba-fetch-deps.sh b/mobile/android/fenix/tools/tba-fetch-deps.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+echo -e "\033[1;33mThis file is deprecated.\033[0m"
+echo "Run ./mach bootstrap and/or define options in your mozconfig from now on."
+echo "See documentation at: https://gitlab.torproject.org/tpo/applications/wiki/-/wikis/Development-Information/Firefox-Android/Building"
+
+exit 1
diff --git a/mobile/android/fenix/tools/tba-sign-devbuilds.sh b/mobile/android/fenix/tools/tba-sign-devbuilds.sh
@@ -0,0 +1,77 @@
+#!/bin/bash
+
+cd "$(dirname $(realpath "$0"))/.."
+
+objdir=$1
+if [ -z "$objdir" ]; then
+ echo "Usage $0 objdir"
+ exit 1
+fi
+
+if [ -z "$APKSIGNER_ARGS" ]; then
+ if [ -z "$QA_KEY" ]; then
+ if [ -z "$TOR_BROWSER_BUILD" ]; then
+ TOR_BROWSER_BUILD=../../../../tor-browser-build
+ fi
+ QA_KEY="$TOR_BROWSER_BUILD/projects/browser/android-qa.keystore"
+ fi
+ if [ ! -f "$QA_KEY" ]; then
+ echo "The QA key has not been found."
+ echo "Please define either \$QA_KEY with its path, or \$TOR_BROWSER_BUILD with the path to tor-browser-build"
+ exit 2
+ fi
+ APKSIGNER_ARGS="--ks "$QA_KEY" --ks-key-alias androidqakey --key-pass pass:android --ks-pass pass:android"
+fi
+
+if [ -z "$ANDROID_HOME" ]; then
+ ANDROID_HOME=~/Android
+fi
+
+function find_tool() {
+ tool="$(find $ANDROID_HOME -name "$1" | head -1)"
+ if [ -z "$tool" ]; then
+ tool=$(which $1)
+ fi
+ echo $tool
+}
+
+apksigner="$(find_tool apksigner)"
+zipalign="$(find_tool zipalign)"
+if [ -z "$apksigner" -o ! -x "$apksigner" -o -z "$zipalign" -o ! -x "$zipalign" ]; then
+ echo "apksigner or zipalign not found."
+ echo "Please make sure they are on your \$PATH, or define \$ANDROID_HOME."
+ exit 3
+fi
+
+noscript="$(find "$TOR_BROWSER_BUILD/out/browser" -name 'noscript*.xpi' -print | sort | tail -1)"
+tmpdir="$(mktemp -d)"
+mkdir -p "$tmpdir/assets/extensions"
+if [ -f "$noscript" ]; then
+ cp "$noscript" "$tmpdir/assets/extensions/{73a6fe31-595d-460b-a920-fcc0f8843232}.xpi"
+fi
+
+sign () {
+ apk="$(realpath $1)"
+ out="$apk"
+ if [ ! -f "$apk" ]; then
+ return
+ fi
+ out="${out/unsigned/signed}"
+ aligned="$apk"
+ aligned="${aligned/unsigned/aligned}"
+ pushd "$tmpdir" > /dev/null
+ zip -Xr "$apk" assets > /dev/null
+ popd > /dev/null
+ rm -f "$aligned"
+ "$zipalign" -p 4 "$apk" "$aligned"
+ echo "Signing $out"
+ "$apksigner" sign --in "$aligned" --out "$out" $APKSIGNER_ARGS
+}
+
+for channel in "$objdir/gradle/build/mobile/android/fenix/app/outputs/apk/fenix/"*; do
+ for apk in $channel/*-unsigned.apk; do
+ sign "$apk"
+ done
+done
+
+rm -rf "$tmpdir"