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 = "42.3.0"
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 'com.diffplug.spotless:spotless-plugin-gradle:5.16.0'
109 classpath 'org.tomlj:tomlj:1.0.0'
110 classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
114 // A stream that processes bytes line by line, prepending a tag before sending
115 // each line to Gradle's logging.
116 class TaggedLogOutputStream extends org.apache.commons.exec.LogOutputStream {
120 TaggedLogOutputStream(tag, logger) {
125 void processLine(String line, int level) {
126 logger.lifecycle("${this.tag} ${line}")
130 ext.geckoBinariesOnlyIf = { task ->
131 // Never when Gradle was invoked within `mach build`.
132 if ('1' == System.env.GRADLE_INVOKED_WITHIN_MACH_BUILD) {
133 rootProject.logger.lifecycle("Skipping task ${task.path} because: within `mach build`")
137 // Never for official builds.
138 if (mozconfig.substs.MOZILLA_OFFICIAL) {
139 rootProject.logger.lifecycle("Skipping task ${task.path} because: MOZILLA_OFFICIAL")
143 // Multi-l10n builds set `AB_CD=multi`, which isn't a valid locale. To
144 // avoid failures, if Gradle is invoked with AB_CD=multi, we don't invoke
146 if ('multi' == System.env.AB_CD) {
147 rootProject.logger.lifecycle("Skipping task ${task.path} because: AB_CD=multi")
151 // Single-locale l10n repacks set `IS_LANGUAGE_REPACK=1` and handle resource
152 // and code generation themselves.
153 if ('1' == System.env.IS_LANGUAGE_REPACK) {
154 rootProject.logger.lifecycle("Skipping task ${task.path} because: IS_LANGUAGE_REPACK")
158 rootProject.logger.lifecycle("Executing task ${task.path}")
162 class MachExec extends Exec {
164 // Bug 1543982: When invoking `mach build` recursively, the outer `mach
165 // build` itself modifies the environment, causing configure to run
166 // again. This tries to restore the environment that the outer `mach
167 // build` was invoked in. See the comment in
168 // $topsrcdir/settings.gradle.
169 project.ext.mozconfig.mozconfig.env.unmodified.each { k, v -> environment.remove(k) }
170 environment project.ext.mozconfig.orig_mozconfig.env.unmodified
171 environment 'MOZCONFIG', project.ext.mozconfig.substs.MOZCONFIG
175 task machBuildFaster(type: MachExec) {
176 onlyIf rootProject.ext.geckoBinariesOnlyIf
178 workingDir "${topsrcdir}"
180 commandLine mozconfig.substs.PYTHON3
181 args "${topsrcdir}/mach"
185 // Add `-v` if we're running under `--info` (or `--debug`).
186 if (project.logger.isEnabled(LogLevel.INFO)) {
190 // `path` is like `:machBuildFaster`.
191 standardOutput = new TaggedLogOutputStream("${path}>", logger)
192 errorOutput = standardOutput
195 task machStagePackage(type: MachExec) {
196 onlyIf rootProject.ext.geckoBinariesOnlyIf
198 dependsOn rootProject.machBuildFaster
200 workingDir "${topobjdir}"
202 // We'd prefer this to be a `mach` invocation, but `mach build
203 // mobile/android/installer/stage-package` doesn't work as expected.
204 commandLine mozconfig.substs.GMAKE
206 args "${topobjdir}/mobile/android/installer"
209 outputs.file "${topobjdir}/dist/geckoview/assets/omni.ja"
211 outputs.file "${topobjdir}/dist/geckoview/assets/${mozconfig.substs.ANDROID_CPU_ARCH}/libxul.so"
212 outputs.file "${topobjdir}/dist/geckoview/lib/${mozconfig.substs.ANDROID_CPU_ARCH}/libmozglue.so"
214 // Force running `stage-package`.
215 outputs.upToDateWhen { false }
217 // `path` is like `:machStagePackage`.
218 standardOutput = new TaggedLogOutputStream("${path}>", logger)
219 errorOutput = standardOutput
223 subprojects { project ->
224 tasks.withType(JavaCompile) {
225 // Add compiler args for all code except third-party code.
226 options.compilerArgs += [
227 // Turn on all warnings, except...
229 // Deprecation, because we do use deprecated API for compatibility.
230 "-Xlint:-deprecation",
231 // Serial, because we don't use Java serialization.
233 // Classfile, because javac has a bug with MethodParameters attributes
234 // with Java 7. https://bugs.openjdk.java.net/browse/JDK-8190452
236 // Turn all remaining warnings into errors,
237 // unless marked by @SuppressWarnings.
247 languageLevel = '1.8'
251 // Object directories take a huge amount of time for IntelliJ to index.
252 // Exclude them. Convention is that object directories start with obj.
253 // IntelliJ is clever and will not exclude the parts of the object
254 // directory that are referenced, if there are any. In practice,
255 // indexing the entirety of the tree is taking too long, so exclude all
257 def topsrcdirURI = file(topsrcdir).toURI()
258 excludeDirs += files(file(topsrcdir)
259 .listFiles({it.isDirectory()} as FileFilter)
260 .collect({topsrcdirURI.relativize(it.toURI()).toString()}) // Relative paths.
261 .findAll({!it.equals('mobile/')}))
263 // If topobjdir is below topsrcdir, hide only some portions of that tree.
264 def topobjdirURI = file(topobjdir).toURI()
265 if (!topsrcdirURI.relativize(topobjdirURI).isAbsolute()) {
266 excludeDirs -= file(topobjdir)
267 excludeDirs += files(file(topobjdir).listFiles())
268 excludeDirs -= file("${topobjdir}/gradle")
274 apply plugin: "com.diffplug.spotless"
278 target project.fileTree(project.projectDir) {
280 exclude '**/thirdparty/**'
282 googleJavaFormat('1.7')