Bug 1509573 - Part 2: Use |mach build faster| rather than special Make target. r=snorp
authorNick Alexander <nalexander@mozilla.com>
Wed, 28 Nov 2018 19:46:35 +0000
changeset 507859 36cf7b9ce095cca9ebc495fb44f23125c100efa7
parent 507858 d7e0661e34c223c23d04ef2083b2191f15c1d3c9
child 507860 059741f95cf4d4f680bea3eeadb714e567cd5413
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1509573
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1509573 - Part 2: Use |mach build faster| rather than special Make target. r=snorp This uses |mach build faster| rather than a custom target, reducing Make magic and making it easier to reason about the Gradle build. I also took the opportunity to improve the task logging. Differential Revision: https://phabricator.services.mozilla.com/D12797
build.gradle
mobile/android/app/build.gradle
mobile/android/base/Makefile.in
mobile/android/gradle/with_gecko_binaries.gradle
--- a/build.gradle
+++ b/build.gradle
@@ -53,51 +53,67 @@ buildscript {
     if (gradle.mozconfig.substs.MOZ_ANDROID_GOOGLE_PLAY_SERVICES) {
         ext.google_play_services_version = '15.0.1'
     }
 
     dependencies {
         classpath 'org.mozilla.apilint:apilint:0.1.4'
         classpath 'com.android.tools.build:gradle:3.1.4'
         classpath 'com.getkeepsafe.dexcount:dexcount-gradle-plugin:0.8.2'
+        classpath 'org.apache.commons:commons-exec:1.3'
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
     }
 }
 
+// A stream that processes bytes line by line, prepending a tag before sending
+// each line to Gradle's logging.
+class TaggedLogOutputStream extends org.apache.commons.exec.LogOutputStream {
+    String tag
+    Logger logger
+
+    TaggedLogOutputStream(tag, logger) {
+        this.tag = tag
+        this.logger = logger
+    }
+
+    void processLine(String line, int level) {
+        logger.lifecycle("${this.tag} ${line}")
+    }
+}
+
 if ('multi' == System.env.AB_CD) {
     // Multi-l10n builds set `AB_CD=multi`, which isn't a valid locale.  This
     // causes the
     //
-    // |mach build| > |mach gradle| > |make gradle-targets| > AndroidManifest.xml > strings.xml > multi/brand.dtd
+    // |mach build| > |mach gradle| > AndroidManifest.xml > strings.xml > multi/brand.dtd
     //
     // dependency chain to fail, since multi isn't a real locale.  To avoid
     // this, if Gradle is invoked with AB_CD=multi, we don't invoke Make at all.
-    task generateCodeAndResources()
+    task machBuildFaster()
 } else if (System.env.IS_LANGUAGE_REPACK == '1') {
     // Single-locale l10n repacks set `IS_LANGUAGE_REPACK=1` and handle resource
     // and code generation themselves.
-    task generateCodeAndResources()
+    task machBuildFaster()
 } else {
-    task generateCodeAndResources(type:Exec) {
-        workingDir "${topobjdir}"
-
-        commandLine mozconfig.substs.GMAKE
-        args '-C'
-        args "${topobjdir}/mobile/android/base"
-        args 'gradle-targets'
+    task machBuildFaster(type: Exec) {
+        workingDir "${topsrcdir}"
 
-        // Only show the output if something went wrong.
-        ignoreExitValue = true
-        standardOutput = new ByteArrayOutputStream()
+        commandLine mozconfig.substs.PYTHON
+        args "${topsrcdir}/mach"
+        args 'build'
+        args 'faster'
+
+        // Add `-v` if we're running under `--info` (or `--debug`).
+        if (project.logger.isEnabled(LogLevel.INFO)) {
+            args '-v'
+        }
+
+        // `path` is like `:machBuildFaster`.
+        standardOutput = new TaggedLogOutputStream("${path}>", logger)
         errorOutput = standardOutput
-        doLast {
-            if (execResult.exitValue != 0) {
-                throw new GradleException("Process '${commandLine}' finished with non-zero exit value ${execResult.exitValue}:\n\n${standardOutput.toString()}")
-            }
-        }
     }
 }
 
 afterEvaluate {
     subprojects { project ->
         if (project.name != 'thirdparty') {
             tasks.withType(JavaCompile) {
                 // Add compiler args for all code except third-party code.
@@ -126,20 +142,20 @@ afterEvaluate {
                 }
             }
         }
 
         if (!hasProperty('android')) {
             return
         }
         android.applicationVariants.all {
-            preBuild.dependsOn rootProject.generateCodeAndResources
+            preBuild.dependsOn rootProject.machBuildFaster
         }
         android.libraryVariants.all {
-            preBuild.dependsOn rootProject.generateCodeAndResources
+            preBuild.dependsOn rootProject.machBuildFaster
         }
     }
 }
 
 apply plugin: 'idea'
 
 idea {
     project {
--- a/mobile/android/app/build.gradle
+++ b/mobile/android/app/build.gradle
@@ -333,17 +333,17 @@ android.applicationVariants.all { varian
     // `sourceSets` task, for reasons unknown.
     variant.registerGeneratedResFolders(project.files(syncPreprocessedRes.destinationDir).builtBy(syncPreprocessedRes))
 
     // It's not easy -- see the backout in Bug 1242213 -- to change the
     // <manifest> package for Fennec.  Gradle has grown a mechanism to achieve
     // what we want for Fennec, however, with applicationId.  To use the same
     // manifest as moz.build, we replace the package with org.mozilla.gecko (the
     // eventual package) here.
-    def rewriteManifestPackage = task("rewriteManifestPackageFor${variant.name.capitalize()}", type: Copy, dependsOn: rootProject.generateCodeAndResources) {
+    def rewriteManifestPackage = task("rewriteManifestPackageFor${variant.name.capitalize()}", type: Copy, dependsOn: rootProject.machBuildFaster) {
         into("${project.buildDir}/moz.build/src/${variant.name}")
         from("${topobjdir}/mobile/android/base/AndroidManifest.xml")
         filter { it.replaceFirst(/package=".*?"/, 'package="org.mozilla.gecko"') }
         exclude('**/*.mkdir.done')
     }
 
     // Every configuration needs the stub manifest at
     // src/main/AndroidManifest.xml and the generated manifest.  We can't use
@@ -354,19 +354,19 @@ android.applicationVariants.all { varian
 
 
     // Local (read, not 'official') builds want to reflect developer changes to
     // AndroidManifest.xml.in, strings.xml, and preprocessed Java code.  To do
     // this, the Gradle build calls out to the moz.build system, which can be
     // re-entrant.  Official builds are driven by the moz.build system and
     // should never be re-entrant in this way.
     if (!mozconfig.substs.MOZILLA_OFFICIAL) {
-        syncPreprocessedJava.dependsOn rootProject.generateCodeAndResources
-        syncPreprocessedRes.dependsOn rootProject.generateCodeAndResources
-        rewriteManifestPackage.dependsOn rootProject.generateCodeAndResources
+        syncPreprocessedJava.dependsOn rootProject.machBuildFaster
+        syncPreprocessedRes.dependsOn rootProject.machBuildFaster
+        rewriteManifestPackage.dependsOn rootProject.machBuildFaster
     }
 
     // When driven from moz.build via |mach build|, Gradle does not require or
     // use Gecko binaries.  It's only |mach package| that packs the Gecko
     // binaries into the resulting APK.  The "withoutGeckoBinaries" variants
     // handle this.  When driven from Android Studio or Gradle, the
     // "withGeckoBinaries" variants handle packing the Gecko binaries into the
     // resulting APK (for on-device deployment).  They also update the Omnijars
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -1,29 +1,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # Developer builds call mach -> Make -> gradle -> mach, which races to
 # find and create .mozconfig files and to generate targets.
 .NOTPARALLEL:
 
-generated_resources := \
-  AndroidManifest.xml \
-  res/raw/suggestedsites.json \
-  res/values/strings.xml \
-  $(NULL)
-
-generated_files := \
-  AndroidManifest.xml \
-  generated/preprocessed/org/mozilla/gecko/AdjustConstants.java \
-  generated/preprocessed/org/mozilla/gecko/AppConstants.java \
-  generated/preprocessed/org/mozilla/gecko/MmaConstants.java \
-  $(NULL)
-
 include $(topsrcdir)/config/AB_rCD.mk
 
 chrome-%:: AB_CD=$*
 chrome-%::
 	$(MAKE) \
 	  res/values$(AB_rCD)/strings.xml \
 	  res/raw$(AB_rCD)/suggestedsites.json \
 	  AB_CD=$*
@@ -39,27 +26,19 @@ include $(topsrcdir)/config/rules.mk
 	$(REPORT_BUILD)
 	$(MAKE) -C ../../../faster
 	$(MAKE) -C ../installer stage-package
 	$(MKDIR) -p $(@D)
 	rsync --update $(DIST)/fennec/$(notdir $(OMNIJAR_NAME)) $@
 	$(RM) $(DIST)/fennec/$(notdir $(OMNIJAR_NAME))
 
 ifndef MOZILLA_OFFICIAL
-# Targets built very early during a Gradle build.  In automation,
-# these are built before Gradle is invoked, and gradle-targets is not
-# made at all.  This is required to avoid building gradle-targets with
-# AB_CD=multi during multi-l10n builds.
-gradle-targets: $(generated_resources) $(generated_files)
-
 # Local developers update omni.ja during their builds.  There's a
 # chicken-and-egg problem here.
 gradle-omnijar: $(abspath $(DIST)/fennec/$(OMNIJAR_NAME))
 else
 # In automation, omni.ja is built only during packaging.
 gradle-omnijar:
-
-gradle-targets:
 endif
 
-.PHONY: gradle-targets gradle-omnijar
+.PHONY: gradle-omnijar
 
 export:: android_apks
--- a/mobile/android/gradle/with_gecko_binaries.gradle
+++ b/mobile/android/gradle/with_gecko_binaries.gradle
@@ -7,17 +7,17 @@
 // That arrangement labels them nicely in IntelliJ.  See the comment in the
 // :omnijar project for more context.
 evaluationDependsOn(':omnijar')
 
 // The JNI wrapper generation tasks depend on the JAR creation task of the :annotations project.
 evaluationDependsOn(':annotations')
 
 task buildOmnijars(type:Exec) {
-    dependsOn rootProject.generateCodeAndResources
+    dependsOn rootProject.machBuildFaster
 
     // See comment in :omnijar project regarding interface mismatches here.
     inputs.file(project(':omnijar').sourceSets.main.resources.srcDirs).skipWhenEmpty() 
 
     // Produce both the Fennec and the GeckoView omnijars.
     outputs.file "${topobjdir}/dist/fennec/assets/omni.ja"
     outputs.file "${topobjdir}/dist/geckoview/assets/omni.ja"