2 import org.tomlj.TomlParseResult
3 import org.tomlj.TomlTable
5 def tryInt = { string ->
9 if (string.isInteger()) {
10 return string as Integer
15 // Parses the Cargo.lock and returns the version for the given package name.
16 def getRustVersionFor(packageName) {
17 String version = null;
18 TomlParseResult result = Toml.parse(file("Cargo.lock").getText());
19 for (object in result.getArray("package").toList()) {
20 def table = (TomlTable) object
21 if (table.getString("name") == packageName) {
22 if (version != null) {
23 throw new StopExecutionException("Multiple versions for '${packageName}' found." +
24 " Ensure '${packageName}' is only included once.")
26 version = table.getString("version")
33 // Expose the per-object-directory configuration to all projects.
35 mozconfig = gradle.mozconfig
36 topsrcdir = gradle.mozconfig.topsrcdir
37 topobjdir = gradle.mozconfig.topobjdir
39 gleanVersion = "41.1.1"
40 if (gleanVersion != getRustVersionFor("glean")) {
41 throw new StopExecutionException("Mismatched Glean version, expected: ${gleanVersion}," +
42 " found ${getRustVersionFor("glean")}")
45 buildToolsVersion = mozconfig.substs.ANDROID_BUILD_TOOLS_VERSION
46 compileSdkVersion = tryInt(mozconfig.substs.ANDROID_TARGET_SDK)
47 targetSdkVersion = tryInt(mozconfig.substs.ANDROID_TARGET_SDK)
48 minSdkVersion = tryInt(mozconfig.substs.MOZ_ANDROID_MIN_SDK_VERSION)
49 manifestPlaceholders = [
50 ANDROID_PACKAGE_NAME: mozconfig.substs.ANDROID_PACKAGE_NAME,
51 ANDROID_TARGET_SDK: mozconfig.substs.ANDROID_TARGET_SDK,
52 MOZ_ANDROID_MIN_SDK_VERSION: mozconfig.substs.MOZ_ANDROID_MIN_SDK_VERSION,
57 gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
64 task downloadDependencies() {
65 description 'Download all dependencies to the Gradle cache'
67 configurations.each { configuration ->
68 if (configuration.canBeResolved) {
69 configuration.allDependencies.each { dependency ->
71 configuration.files(dependency)
73 println("Could not resolve ${configuration.name} -> ${dependency.name}")
74 println(" > ${e.message}")
76 println(" >> ${e.cause}")
78 println(" >> ${e.cause.cause}")
90 buildDir "${topobjdir}/gradle/build"
94 gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
101 ext.kotlin_version = '1.5.20'
104 classpath 'org.mozilla.apilint:apilint:0.4.4'
105 classpath 'com.android.tools.build:gradle:4.2.0'
106 classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.2'
107 classpath 'org.apache.commons:commons-exec:1.3'
108 classpath 'org.tomlj:tomlj:1.0.0'
109 classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
113 // A stream that processes bytes line by line, prepending a tag before sending
114 // each line to Gradle's logging.
115 class TaggedLogOutputStream extends org.apache.commons.exec.LogOutputStream {
119 TaggedLogOutputStream(tag, logger) {
124 void processLine(String line, int level) {
125 logger.lifecycle("${this.tag} ${line}")
129 ext.geckoBinariesOnlyIf = { task ->
130 // Never when Gradle was invoked within `mach build`.
131 if ('1' == System.env.GRADLE_INVOKED_WITHIN_MACH_BUILD) {
132 rootProject.logger.lifecycle("Skipping task ${task.path} because: within `mach build`")
136 // Never for official builds.
137 if (mozconfig.substs.MOZILLA_OFFICIAL) {
138 rootProject.logger.lifecycle("Skipping task ${task.path} because: MOZILLA_OFFICIAL")
142 // Multi-l10n builds set `AB_CD=multi`, which isn't a valid locale. To
143 // avoid failures, if Gradle is invoked with AB_CD=multi, we don't invoke
145 if ('multi' == System.env.AB_CD) {
146 rootProject.logger.lifecycle("Skipping task ${task.path} because: AB_CD=multi")
150 // Single-locale l10n repacks set `IS_LANGUAGE_REPACK=1` and handle resource
151 // and code generation themselves.
152 if ('1' == System.env.IS_LANGUAGE_REPACK) {
153 rootProject.logger.lifecycle("Skipping task ${task.path} because: IS_LANGUAGE_REPACK")
157 rootProject.logger.lifecycle("Executing task ${task.path}")
161 class MachExec extends Exec {
163 // Bug 1543982: When invoking `mach build` recursively, the outer `mach
164 // build` itself modifies the environment, causing configure to run
165 // again. This tries to restore the environment that the outer `mach
166 // build` was invoked in. See the comment in
167 // $topsrcdir/settings.gradle.
168 project.ext.mozconfig.mozconfig.env.unmodified.each { k, v -> environment.remove(k) }
169 environment project.ext.mozconfig.orig_mozconfig.env.unmodified
170 environment 'MOZCONFIG', project.ext.mozconfig.substs.MOZCONFIG
174 task machBuildFaster(type: MachExec) {
175 onlyIf rootProject.ext.geckoBinariesOnlyIf
177 workingDir "${topsrcdir}"
179 commandLine mozconfig.substs.PYTHON3
180 args "${topsrcdir}/mach"
184 // Add `-v` if we're running under `--info` (or `--debug`).
185 if (project.logger.isEnabled(LogLevel.INFO)) {
189 // `path` is like `:machBuildFaster`.
190 standardOutput = new TaggedLogOutputStream("${path}>", logger)
191 errorOutput = standardOutput
194 task machStagePackage(type: MachExec) {
195 onlyIf rootProject.ext.geckoBinariesOnlyIf
197 dependsOn rootProject.machBuildFaster
199 workingDir "${topobjdir}"
201 // We'd prefer this to be a `mach` invocation, but `mach build
202 // mobile/android/installer/stage-package` doesn't work as expected.
203 commandLine mozconfig.substs.GMAKE
205 args "${topobjdir}/mobile/android/installer"
208 outputs.file "${topobjdir}/dist/geckoview/assets/omni.ja"
210 outputs.file "${topobjdir}/dist/geckoview/assets/${mozconfig.substs.ANDROID_CPU_ARCH}/libxul.so"
211 outputs.file "${topobjdir}/dist/geckoview/lib/${mozconfig.substs.ANDROID_CPU_ARCH}/libmozglue.so"
213 // Force running `stage-package`.
214 outputs.upToDateWhen { false }
216 // `path` is like `:machStagePackage`.
217 standardOutput = new TaggedLogOutputStream("${path}>", logger)
218 errorOutput = standardOutput
222 subprojects { project ->
223 tasks.withType(JavaCompile) {
224 // Add compiler args for all code except third-party code.
225 options.compilerArgs += [
226 // Turn on all warnings, except...
228 // Deprecation, because we do use deprecated API for compatibility.
229 "-Xlint:-deprecation",
230 // Serial, because we don't use Java serialization.
232 // Classfile, because javac has a bug with MethodParameters attributes
233 // with Java 7. https://bugs.openjdk.java.net/browse/JDK-8190452
235 // Turn all remaining warnings into errors,
236 // unless marked by @SuppressWarnings.
246 languageLevel = '1.8'
250 // Object directories take a huge amount of time for IntelliJ to index.
251 // Exclude them. Convention is that object directories start with obj.
252 // IntelliJ is clever and will not exclude the parts of the object
253 // directory that are referenced, if there are any. In practice,
254 // indexing the entirety of the tree is taking too long, so exclude all
256 def topsrcdirURI = file(topsrcdir).toURI()
257 excludeDirs += files(file(topsrcdir)
258 .listFiles({it.isDirectory()} as FileFilter)
259 .collect({topsrcdirURI.relativize(it.toURI()).toString()}) // Relative paths.
260 .findAll({!it.equals('mobile/')}))
262 // If topobjdir is below topsrcdir, hide only some portions of that tree.
263 def topobjdirURI = file(topobjdir).toURI()
264 if (!topsrcdirURI.relativize(topobjdirURI).isAbsolute()) {
265 excludeDirs -= file(topobjdir)
266 excludeDirs += files(file(topobjdir).listFiles())
267 excludeDirs -= file("${topobjdir}/gradle")