Bug 1684463 - [devtools] Part 1: Shorten the _createAttribute function by refactoring...
[gecko.git] / substitute-local-geckoview.gradle
blob246ae3addf0eab4ef618b864c24310f59e0b6a7d
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.
6 //
7 // To use this, in a consuming Gradle project's `/build.gradle` add a stanza like:
8 //
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
23 // versions.
25 import groovy.json.JsonSlurper
27 def log(message) {
28     logger.lifecycle("[substitute-local-geckoview] ${message}")
31 if (!project.ext.has('topsrcdir')) {
32     throw new GradleException("ext.topsrcdir must be specified to substitute for a local GeckoView")
35 // Cribbed from https://hg.mozilla.org/mozilla-central/file/tip/settings.gradle.  When run in
36 // topobjdir, `mach environment` correctly finds the mozconfig corresponding to that object
37 // directory.
38 def commandLine = ["${topsrcdir}/mach", "environment", "--format", "json", "--verbose"]
39 def proc = commandLine.execute(null, new File(ext.has('topobjdir') ? ext.get('topobjdir') : topsrcdir))
40 def standardOutput = new ByteArrayOutputStream()
41 proc.consumeProcessOutput(standardOutput, standardOutput)
42 proc.waitFor()
44 // Only show the output if something went wrong.
45 if (proc.exitValue() != 0) {
46     throw new GradleException("Process '${commandLine}' finished with non-zero exit value ${proc.exitValue()}:\n\n${standardOutput.toString()}")
49 def slurper = new JsonSlurper()
50 def mozconfig = slurper.parseText(standardOutput.toString())
52 if (topsrcdir != mozconfig.topsrcdir) {
53     throw new GradleException("Specified topsrcdir ('${topsrcdir}') is not mozconfig topsrcdir ('${mozconfig.topsrcdir}')")
56 if (!ext.has('topobjdir')) {
57     ext.topobjdir = mozconfig.topobjdir
58     log("Found topobjdir ${topobjdir} from topsrcdir ${topsrcdir}")
61 if (mozconfig.substs.MOZ_BUILD_APP != 'mobile/android') {
62     throw new GradleException("Building with Gradle is only supported for Fennec, i.e., MOZ_BUILD_APP == 'mobile/android'.")
65 log("Will substitute GeckoView (geckoview-{nightly,beta}) with local GeckoView (geckoview-default) from ${topobjdir}/gradle/build/mobile/android/geckoview/maven")
67 if (!mozconfig.substs.COMPILE_ENVIRONMENT) {
68     log("To update the local GeckoView, run `./mach gradle geckoview:publishWithGeckoBinariesDebugPublicationToMavenRepository` in ${topsrcdir}")
69 } else {
70     log("To update the local GeckoView, run `./mach build binaries && ./mach gradle geckoview:publishWithGeckoBinariesDebugPublicationToMavenRepository` in ${topsrcdir}")
73 repositories {
74     maven {
75         name "Local GeckoView Maven repository"
76         url "${topobjdir}/gradle/build/mobile/android/geckoview/maven"
77     }
80 configurations.all { config ->
81     // Like `geckoview-nightly` for a multi-architecture fat AAR or
82     // `geckoview-nightly-armeabi-v7a` for an architecture-specific AAR.
83     def geckoviewModules = [
84         'geckoview-nightly',
85         'geckoview-nightly-armeabi-v7a',
86         'geckoview-nightly-arm64-v8a',
87         'geckoview-nightly-x86',
88         'geckoview-nightly-x86_64',
89         'geckoview-beta',
90         'geckoview-beta-armeabi-v7a',
91         'geckoview-beta-arm64-v8a',
92         'geckoview-beta-x86',
93         'geckoview-beta-x86_64',
94     ]
96     if (config.isCanBeResolved()) {
97         config.resolutionStrategy { strategy ->
98             dependencySubstitution {
99                 all { dependency ->
100                     // We could restrict based on target architecture, but there doesn't seem to
101                     // be much advantage to doing so right now.
103                     if (!(dependency.requested instanceof ModuleComponentSelector)) {
104                         // We can only substitute for a module: we're never going to substitute
105                         // for a project.
106                         return
107                     }
109                     def group = dependency.requested.group
110                     if (group == 'org.mozilla.geckoview' && geckoviewModules.contains(dependency.requested.module)) {
111                         def name = 'geckoview-default'
112                         log("Substituting ${group}:${dependency.requested.module} with local GeckoView ${group}:${name} in ${config}")
114                         dependency.useTarget([group: group, name: name, version: '+'])
116                         // We substitute with a dynamic version ('+').  It seems that Gradle
117                         // discovers the underlying AAR is out of date correctly based on file
118                         // timestamp already, but let's try to avoid some class of cache
119                         // invalidation error while we're here.
120                         strategy.cacheDynamicVersionsFor 0, 'seconds'
121                         strategy.cacheChangingModulesFor 0, 'seconds'
122                     }
123                 }
124             }
125         }
126     }