1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 // Substitute a local GeckoView AAR into a consuming Gradle project.
7 // To use this, in a consuming Gradle project's `/build.gradle` add a stanza like:
9 // ext.topsrcdir = '/absolute/path/to/mozilla-central'; apply from: "${ext.topsrcdir}/substitute-local-geckoview.gradle"
11 // The object directory will be determined using `mach environment` and will agree with `./mach
12 // gradle` and Android Studio. Or, specify the exact object directory with a stanza like:
14 // ext.topsrcdir = '/absolute/path/to/mozilla-central'
15 // ext.topobjdir = '/absolute/path/to/objdir'
16 // apply from: "${ext.topsrcdir}/substitute-local-geckoview.gradle"
18 // Substitution works with artifact and non-artifact builds.
20 // If you get errors about .jar files not being found, ensure that the consuming
21 // application is using a recent Android-Gradle plugin (say, 3.4+). There were
22 // issues with Jetifier, and issues with .jar vs. .aar extensions, in older
25 import groovy.json.JsonSlurper
28 logger.lifecycle("[substitute-local-geckoview] ${message}")
32 logger.warn("[substitute-local-geckoview] Warning: ${message}")
35 if (!project.ext.has('topsrcdir')) {
36 throw new GradleException("ext.topsrcdir must be specified to substitute for a local GeckoView")
39 apply from: "${topsrcdir}/mobile/android/gradle/mach_env.gradle"
41 // Cribbed from https://hg.mozilla.org/mozilla-central/file/tip/settings.gradle. When run in
42 // topobjdir, `mach environment` correctly finds the mozconfig corresponding to that object
44 def commandLine = ["${topsrcdir}/mach", "environment", "--format", "json", "--verbose"]
45 def proc = commandLine.execute(
47 new File(ext.has('topobjdir') ? ext.get('topobjdir') : topsrcdir))
48 def standardOutput = new ByteArrayOutputStream()
49 proc.consumeProcessOutput(standardOutput, standardOutput)
52 // Only show the output if something went wrong.
53 if (proc.exitValue() != 0) {
54 throw new GradleException("Process '${commandLine}' finished with non-zero exit value ${proc.exitValue()}:\n\n${standardOutput.toString()}")
57 def slurper = new JsonSlurper()
58 def mozconfig = slurper.parseText(standardOutput.toString())
60 if (topsrcdir != mozconfig.topsrcdir) {
61 throw new GradleException("Specified topsrcdir ('${topsrcdir}') is not mozconfig topsrcdir ('${mozconfig.topsrcdir}')")
64 if (!ext.has('topobjdir')) {
65 ext.topobjdir = mozconfig.topobjdir
66 log("Found topobjdir ${topobjdir} from topsrcdir ${topsrcdir}")
69 if (mozconfig.substs.MOZ_BUILD_APP != 'mobile/android') {
70 throw new GradleException("Building with Gradle is only supported for GeckoView, i.e., MOZ_BUILD_APP == 'mobile/android'.")
73 log("Will substitute GeckoView (geckoview-{nightly,beta}) with local GeckoView (geckoview-default) from ${topobjdir}/gradle/build/mobile/android/geckoview/maven")
75 if (!mozconfig.substs.COMPILE_ENVIRONMENT) {
76 log("To update the local GeckoView, run `./mach gradle geckoview:publishWithGeckoBinariesDebugPublicationToMavenRepository` in ${topsrcdir}")
78 log("To update the local GeckoView, run `./mach build binaries && ./mach gradle geckoview:publishWithGeckoBinariesDebugPublicationToMavenRepository` in ${topsrcdir}")
83 name "Local GeckoView Maven repository"
84 url "${topobjdir}/gradle/build/mobile/android/geckoview/maven"
88 configurations.all { config ->
89 // Like `geckoview-nightly` for a multi-architecture fat AAR or
90 // `geckoview-nightly-armeabi-v7a` for an architecture-specific AAR.
91 def geckoviewModules = [
93 'geckoview-nightly-armeabi-v7a',
94 'geckoview-nightly-arm64-v8a',
95 'geckoview-nightly-x86',
96 'geckoview-nightly-x86_64',
98 'geckoview-beta-armeabi-v7a',
99 'geckoview-beta-arm64-v8a',
100 'geckoview-beta-x86',
101 'geckoview-beta-x86_64',
104 def geckoviewOmniModules = [
105 'geckoview-nightly-omni',
106 'geckoview-nightly-omni-armeabi-v7a',
107 'geckoview-nightly-omni-arm64-v8a',
108 'geckoview-nightly-omni-x86',
109 'geckoview-nightly-omni-x86_64',
110 'geckoview-beta-omni',
111 'geckoview-beta-omni-armeabi-v7a',
112 'geckoview-beta-omni-arm64-v8a',
113 'geckoview-beta-omni-x86',
114 'geckoview-beta-omni-x86_64',
117 if (config.isCanBeResolved()) {
118 config.resolutionStrategy { strategy ->
119 dependencySubstitution {
121 // We could restrict based on target architecture, but there doesn't seem to
122 // be much advantage to doing so right now.
124 if (!(dependency.requested instanceof ModuleComponentSelector)) {
125 // We can only substitute for a module: we're never going to substitute
130 def group = dependency.requested.group
131 def module = dependency.requested.module
132 if (group == 'org.mozilla.geckoview'
133 && (geckoviewModules.contains(module) || geckoviewOmniModules.contains(module))) {
135 def isLite = mozconfig.substs.MOZ_ANDROID_GECKOVIEW_LITE
138 name = 'geckoview-default'
140 name = 'geckoview-default-omni'
143 if (geckoviewModules.contains(module) && !isLite) {
144 warn("Substituting a geckoview omni build into a lite dependency. Add ac_add_options --enable-geckoview-lite to ${mozconfig.mozconfig.path} to fix this.")
145 } else if (geckoviewOmniModules.contains(module) && isLite) {
146 // Substituting lite into omni is unlikely to work at
147 // all so we just error out here.
148 throw new GradleException("Substituting a geckoview lite build into an omni dependency. Remove ac_add_options --enable-geckoview-lite in ${mozconfig.mozconfig.path} to fix this.")
151 log("Substituting ${group}:${dependency.requested.module} with local GeckoView ${group}:${name} in ${config}")
153 dependency.useTarget([group: group, name: name, version: '+'])
155 // We substitute with a dynamic version ('+'). It seems that Gradle
156 // discovers the underlying AAR is out of date correctly based on file
157 // timestamp already, but let's try to avoid some class of cache
158 // invalidation error while we're here.
159 strategy.cacheDynamicVersionsFor 0, 'seconds'
160 strategy.cacheChangingModulesFor 0, 'seconds'