1
0
Fork 0

Update fenix for new megazord setup

master
Thom Chiovoloni 2019-07-17 15:09:47 -07:00 committed by Grisha Kruglov
parent ccae66c08a
commit a1adb2e57f
4 changed files with 51 additions and 87 deletions

View File

@ -409,7 +409,22 @@ dependencies {
testImplementation 'org.apache.maven:maven-ant-tasks:2.1.3'
implementation Deps.fragment_testing
testImplementation Deps.places_forUnitTests
// For production builds, the native code for all `org.mozilla.appservices`
// dependencies gets compiled together into a single "megazord" build, and
// different megazords are published for different subsets of features. Ref
// https://mozilla.github.io/application-services/docs/applications/consuming-megazord-libraries.html
// We want to use the one that's specifically designed for Fenix.
implementation Deps.fenix_megazord
testImplementation Deps.fenix_megazord_forUnitTests
implementation Deps.mozilla_support_rusthttp
modules {
module('org.mozilla.appservices:full-megazord') {
replacedBy('org.mozilla.appservices:fenix-megazord', 'prefer the fenix megazord, to reduce final application size')
}
module('org.mozilla.appservices:fenix-megazord') {
replacedBy('org.mozilla.appservices:fenix-megazord-forUnitTests', 'prefer the forUnitTests variant if present')
}
}
testImplementation Deps.mockito_core
androidTestImplementation Deps.mockito_android
@ -421,6 +436,10 @@ dependencies {
releaseImplementation Deps.flipper_noop
}
if (project.hasProperty("raptor")) {
android.defaultConfig.manifestPlaceholders.isRaptorEnabled = "true"
}
// -------------------------------------------------------------------------------------------------
// Task for printing all build variants to build variants in parallel in automation
// -------------------------------------------------------------------------------------------------
@ -448,41 +467,8 @@ apply from: 'https://github.com/mozilla-mobile/android-components/raw/' + glean_
// into a single "megazord" build, and different megazords are published for different subsets of features.
// Ref https://mozilla.github.io/application-services/docs/applications/consuming-megazord-libraries.html
// Substitute all appservices dependencies with an appropriate megazord.
afterEvaluate {
def megazord = "fenix-megazord"
def appServicesGroup = "org.mozilla.appservices"
def appServicesVersion = null
configurations.each { configuration ->
configuration.resolutionStrategy.eachDependency { DependencyResolveDetails dependency ->
if (dependency.requested.group == appServicesGroup) {
// Ensure that we only depend on a single, consistent version of appservices.
if (appServicesVersion == null) {
appServicesVersion = dependency.requested.version
} else {
if (dependency.requested.version != appServicesVersion) {
logger.lifecycle("In ${configuration}: mismatched '${appServicesGroup}` dependency version:" +
" '${dependency.requested.group}:${dependency.requested.name}:${dependency.requested.version}'" +
" does not have expected version ${appServicesVersion}")
throw new RuntimeException("mismatched '${appServicesGroup}` dependency version")
}
}
// Check whether it was already megazorded.
// Hack: sync15 is pure kotlin, and thus not part of the megazord.
if (! dependency.requested.name.endsWith("-withoutLib") && dependency.requested.name != "sync15") {
// Use either the -forUnitTests megazord, or the default one.
def substitution
if (dependency.requested.name.endsWith("-forUnitTests")) {
substitution = "org.mozilla.appservices:${megazord}-forUnitTests:${appServicesVersion}"
} else {
substitution = "org.mozilla.appservices:${megazord}:${appServicesVersion}"
}
logger.lifecycle("In ${configuration}: substituting megazord module '$substitution' for component module" +
" '${dependency.requested.group}:${dependency.requested.name}:${dependency.requested.version}'")
dependency.useTarget(substitution)
}
}
}
}
// Format test output. Ported from AC #2401
tasks.matching {it instanceof Test}.all {

View File

@ -16,7 +16,7 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import mozilla.components.concept.fetch.Client
import mozilla.appservices.Megazord
import mozilla.components.concept.push.PushProcessor
import mozilla.components.service.fretboard.Fretboard
import mozilla.components.service.fretboard.source.kinto.KintoExperimentSource
@ -26,6 +26,7 @@ import mozilla.components.support.base.log.logger.Logger
import mozilla.components.support.base.log.sink.AndroidLogSink
import mozilla.components.support.ktx.android.content.isMainProcess
import mozilla.components.support.ktx.android.content.runOnlyInMainProcess
import mozilla.components.support.rusthttp.RustHttpConfig
import mozilla.components.support.rustlog.RustLog
import org.mozilla.fenix.components.Components
import org.mozilla.fenix.utils.Settings
@ -49,8 +50,9 @@ open class FenixApplication : Application() {
open fun setupApplication() {
setupCrashReporting()
setDayNightTheme()
val megazordEnabled = setupMegazord()
setupLogging(megazordEnabled)
setupMegazord()
setupLogging()
registerRxExceptionHandling()
enableStrictMode()
@ -129,16 +131,12 @@ open class FenixApplication : Application() {
// no-op, LeakCanary is disabled by default
}
private fun setupLogging(megazordEnabled: Boolean) {
private fun setupLogging() {
// We want the log messages of all builds to go to Android logcat
Log.addSink(AndroidLogSink())
if (megazordEnabled) {
// We want rust logging to go through the log sinks.
// This has to happen after initializing the megazord, and
// it's only worth doing in the case that we are a megazord.
RustLog.enable()
}
// We want rust logging to go through the log sinks.
// This has to happen after initializing the megazord.
RustLog.enable()
}
private fun loadExperiments(): Deferred<Boolean> {
@ -171,34 +169,18 @@ open class FenixApplication : Application() {
/**
* Initiate Megazord sequence! Megazord Battle Mode!
*
* Mozilla Application Services publishes many native (Rust) code libraries that stand alone: each published Android
* ARchive (AAR) contains managed code (classes.jar) and multiple .so library files (one for each supported
* architecture). That means consuming multiple such libraries entails at least two .so libraries, and each of those
* libraries includes the entire Rust standard library as well as (potentially many) duplicated dependencies. To
* save space and allow cross-component native-code Link Time Optimization (LTO, i.e., inlining, dead code
* elimination, etc).
* Application Services also publishes composite libraries -- so called megazord libraries or just megazords -- that
* compose multiple Rust components into a single optimized .so library file.
*
* @return Boolean indicating if we're in a megazord.
* The application-services combined libraries are known as the "megazord". The default megazord
* contains several features that fenix doesn't need, and so we swap out with a customized fenix-specific
* version of the megazord. The best explanation for what this is, and why it's done is the a-s
* documentation on the topic:
* - https://github.com/mozilla/application-services/blob/master/docs/design/megazords.md
* - https://mozilla.github.io/application-services/docs/applications/consuming-megazord-libraries.html
*/
private fun setupMegazord(): Boolean {
// mozilla.appservices.FenixMegazord will be missing if we're doing an application-services
// dependency substitution locally. That class is supplied dynamically by the org.mozilla.appservices
// gradle plugin, and that won't happen if we're not megazording. We won't megazord if we're
// locally substituting every module that's part of the megazord's definition, which is what
// happens during a local substitution of application-services.
// As a workaround, use reflections to conditionally initialize the megazord in case it's present.
return try {
val megazordClass = Class.forName("mozilla.appservices.FenixMegazord")
val megazordInitMethod = megazordClass.getDeclaredMethod("init", Lazy::class.java)
val client: Lazy<Client> = lazy { components.core.client }
megazordInitMethod.invoke(megazordClass, client)
true
} catch (e: ClassNotFoundException) {
Logger.info("mozilla.appservices.FenixMegazord not found; skipping megazord init.")
false
}
private fun setupMegazord() {
// Note: This must be called as soon as possible
Megazord.init()
// This (and enabling RustLog) may be delayed if needed for performance reasons
RustHttpConfig.setClient(lazy { components.core.client })
}
override fun onTrimMemory(level: Int) {

View File

@ -37,9 +37,10 @@ object Versions {
// Note that android-components also depends on application-services,
// and in fact is our main source of appservices-related functionality.
// The version number below tracks the application-services version
// that we depend on directly for tests, and it's important that it
// be kept in sync with the version used by android-components above.
const val mozilla_appservices = "0.34.0"
// that we depend on directly for the fenix-megazord (and for it's
// forUnitTest variant), and it's important that it be kept in
// sync with the version used by android-components above.
const val mozilla_appservices = "0.36.0"
const val autodispose = "1.1.0"
const val adjust = "4.11.4"
@ -139,6 +140,7 @@ object Deps {
const val mozilla_support_base = "org.mozilla.components:support-base:${Versions.mozilla_android_components}"
const val mozilla_support_ktx = "org.mozilla.components:support-ktx:${Versions.mozilla_android_components}"
const val mozilla_support_rusthttp = "org.mozilla.components:support-rusthttp:${Versions.mozilla_android_components}"
const val mozilla_support_rustlog = "org.mozilla.components:support-rustlog:${Versions.mozilla_android_components}"
const val mozilla_support_utils = "org.mozilla.components:support-utils:${Versions.mozilla_android_components}"
const val mozilla_support_test = "org.mozilla.components:support-test:${Versions.mozilla_android_components}"
@ -200,7 +202,9 @@ object Deps {
const val robolectric = "org.robolectric:robolectric:${Versions.robolectric}"
const val fragment_testing = "androidx.fragment:fragment-testing:${Versions.androidx_testing}"
const val androidx_junit = "androidx.test.ext:junit:${Versions.androidx_test_ext}"
const val places_forUnitTests = "org.mozilla.appservices:places-forUnitTests:${Versions.mozilla_appservices}"
const val fenix_megazord = "org.mozilla.appservices:fenix-megazord:${Versions.mozilla_appservices}"
const val fenix_megazord_forUnitTests = "org.mozilla.appservices:fenix-megazord-forUnitTests:${Versions.mozilla_appservices}"
const val google_ads_id = "com.google.android.gms:play-services-ads-identifier:${Versions.google_ads_id_version}"
}

View File

@ -20,16 +20,8 @@ if (localProperties != null) {
if (appServicesLocalPath != null) {
logger.lifecycle("Local configuration: substituting application-services modules from path: $appServicesLocalPath")
includeBuild(appServicesLocalPath) {
dependencySubstitution {
substitute module('org.mozilla.appservices:fxaclient') with project(':fxa-client-library')
substitute module('org.mozilla.appservices:logins') with project(':logins-library')
substitute module('org.mozilla.appservices:places') with project(':places-library')
substitute module('org.mozilla.appservices:rustlog') with project(':rustlog-library')
}
}
// XXX doesn't quite work yet.
includeBuild(appServicesLocalPath)
} else {
logger.lifecycle("Local configuration: application-services substitution path missing. Specify it via '$settingAppServicesPath' setting.")
}