Bug 1509573 - Part 3: Use |make -C ... stage-package| rather than special Make target. r=snorp
authorNick Alexander <nalexander@mozilla.com>
Tue, 18 Dec 2018 23:01:16 +0000
changeset 511200 c15860d7d189eedc89ff61ca4e0bd145e71c151b
parent 511199 6fd3033d7cb7d3b8a58e85f0f1dcd70f16b25306
child 511201 0af0aeece19cffe04f2a3eeb3b1dad3315520b47
push id1953
push userffxbld-merge
push dateMon, 11 Mar 2019 12:10:20 +0000
treeherdermozilla-release@9c35dcbaa899 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssnorp
bugs1509573
milestone66.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 3: Use |make -C ... stage-package| rather than special Make target. r=snorp This splits the two stage-package invocations (which are rather slow) between Fennec and GeckoView, hopefully speeding local GV development up a little (in the IDE). The stage-package invocations depend on |mach build faster|, because the omnijar contents might need to be updated. In addition, we feed the packaged libs (and asset libs) through. Differential Revision: https://phabricator.services.mozilla.com/D12799
build.gradle
mobile/android/app/omnijar/build.gradle
mobile/android/base/Makefile.in
mobile/android/gradle/with_gecko_binaries.gradle
--- a/build.gradle
+++ b/build.gradle
@@ -158,16 +158,87 @@ task machBuildGeneratedAndroidCodeAndRes
         args '-v'
     }
 
     // `path` is like `:machBuildGeneratedAndroidCodeAndResources`.
     standardOutput = new TaggedLogOutputStream("${path}>", logger)
     errorOutput = standardOutput
 }
 
+// Why |mach build mobile/android/base/...| and |mach build faster|?  |mach
+// build faster| generates dependentlibs.list, which in turn depends on compiled
+// code.  That causes a circular dependency between Java compilation/JNI wrapper
+// generation/native code compilation.  So we have the special target for
+// Android-specific generated code, and the |mach build faster| target for all
+// the stuff that goes into the omnijar.
+task machBuildFaster(type: Exec) {
+    onlyIf rootProject.ext.geckoBinariesOnlyIf
+
+    workingDir "${topsrcdir}"
+
+    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
+}
+
+def createMachStagePackageTask(name) {
+    return task(name, type: Exec) {
+        onlyIf rootProject.ext.geckoBinariesOnlyIf
+
+        dependsOn rootProject.machBuildFaster
+
+        // We'd prefer to take these from the :omnijar project directly, but
+        // it's awkward to reach across projects at evaluation time, so we
+        // duplicate the list here.
+        inputs.dir "${topsrcdir}/mobile/android/chrome"
+        inputs.dir "${topsrcdir}/mobile/android/components"
+        inputs.dir "${topsrcdir}/mobile/android/locales"
+        inputs.dir "${topsrcdir}/mobile/android/modules"
+        inputs.dir "${topsrcdir}/mobile/android/themes"
+        inputs.dir "${topsrcdir}/toolkit"
+
+        workingDir "${topobjdir}"
+
+        // We'd prefer this to be a `mach` invocation, but `mach build
+        // mobile/android/installer/stage-package` doesn't work as expected.
+        commandLine mozconfig.substs.GMAKE
+        args '-C'
+        args "${topobjdir}/mobile/android/installer"
+        args 'stage-package'
+
+        outputs.file "${topobjdir}/dist/fennec/assets/${mozconfig.substs.ANDROID_CPU_ARCH}/libxul.so"
+        outputs.file "${topobjdir}/dist/fennec/lib/${mozconfig.substs.ANDROID_CPU_ARCH}/libmozglue.so"
+
+        // `path` is like `:machStagePackage`.
+        standardOutput = new TaggedLogOutputStream("${path}>", logger)
+        errorOutput = standardOutput
+    }
+}
+
+createMachStagePackageTask("machStagePackageForFennec").with {
+    outputs.file "${topobjdir}/dist/fennec/assets/omni.ja"
+}
+
+createMachStagePackageTask("machStagePackageForGeckoview").with {
+    args 'MOZ_GECKOVIEW_JAR=1'
+    outputs.file "${topobjdir}/dist/geckoview/assets/omni.ja"
+    // Avoid races between stage-package invocations.
+    mustRunAfter tasks["machStagePackageForFennec"]
+}
+
 afterEvaluate {
     subprojects { project ->
         if (project.name != 'thirdparty') {
             tasks.withType(JavaCompile) {
                 // Add compiler args for all code except third-party code.
                 options.compilerArgs += [
                     // Turn on all warnings, except...
                     "-Xlint:all",
--- a/mobile/android/app/omnijar/build.gradle
+++ b/mobile/android/app/omnijar/build.gradle
@@ -1,24 +1,25 @@
 buildDir "${topobjdir}/gradle/build/mobile/android/omnijar"
 
 apply plugin: 'java'
 
-// This project is a dummy project; the JAR produced is not used.  The :app
+// This project is a dummy project; the JAR produced is not used.  The root
 // project uses the set of inputs here to check if the omnijar needs to be
 // rebuilt.  By listing them here as resource directories, IntelliJ labels each
 // checked directly nicely.  Why list the directories here?  There's a mismatch
 // between SourceDirectorySet and TaskInputs: the former is directory oriented,
 // while the latter is more general.  That means its easy to convert this list
-// into inputs for :app, but not vice-versa.  Sadly this implies that :app
-// evaluation depends on :omnijar, but the evaluation overhead is low enough
-// that we accept it.
+// into inputs for the root project, but not vice-versa.  Sadly this would mean
+// that the root project evaluation depends on :omnijar, so we duplicate in the
+// root project.
 sourceSets {
     main {
-        // Depend on the Gecko resources in mobile/android.
+        // These are supposed to be files that go into the omnijar.  But yes,
+        // toolkit/ has lots of native code.
         resources {
             srcDir "${topsrcdir}/mobile/android/chrome"
             srcDir "${topsrcdir}/mobile/android/components"
             srcDir "${topsrcdir}/mobile/android/locales"
             srcDir "${topsrcdir}/mobile/android/modules"
             srcDir "${topsrcdir}/mobile/android/themes"
             srcDir "${topsrcdir}/toolkit"
         }
--- a/mobile/android/base/Makefile.in
+++ b/mobile/android/base/Makefile.in
@@ -11,32 +11,8 @@ 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=$*
 
 include $(topsrcdir)/config/rules.mk
-
-# This target is only used by IDE integrations. It rebuilds resources
-# that end up in omni.ja using the equivalent of |mach build faster|,
-# does most of the packaging step, and then updates omni.ja in
-# place. If you're not using an IDE, you should be using |mach build
-# mobile/android && mach package|.
-$(ABS_DIST)/fennec/$(OMNIJAR_NAME): FORCE
-	$(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
-# 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:
-endif
-
-.PHONY: gradle-omnijar
--- a/mobile/android/gradle/with_gecko_binaries.gradle
+++ b/mobile/android/gradle/with_gecko_binaries.gradle
@@ -1,49 +1,16 @@
 /* -*- Mode: Groovy; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
  * 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/. */
 
-// The omnijar inputs are listed as resource directory inputs to a dummy JAR.
-// 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.machBuildGeneratedAndroidCodeAndResources
-
-    // 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"
-
-    workingDir "${topobjdir}"
-
-    commandLine mozconfig.substs.GMAKE
-    args '-C'
-    args "${topobjdir}/mobile/android/base"
-    args 'gradle-omnijar'
-
-    // Only show the output if something went wrong.
-    ignoreExitValue = true
-    standardOutput = new ByteArrayOutputStream()
-    errorOutput = standardOutput
-    doLast {
-        if (execResult.exitValue != 0) {
-            throw new GradleException("Process '${commandLine}' finished with non-zero exit value ${execResult.exitValue}:\n\n${standardOutput.toString()}")
-        }
-    }
-}
-
 ext.configureVariantWithGeckoBinaries = { variant ->
     // :app needs the full Fennec omni.ja, whereas other projects need the
     // GeckoView-specific omni.ja.
     def omnijarDir = { "${topobjdir}/dist/${it}" }("app".equals(project.name) ? "fennec" : "geckoview")
     // All projects take the same Gecko libraries, which (for historical
     // reasons) are in "fennec".
     def distDir = "${topobjdir}/dist/fennec"
 
@@ -78,21 +45,30 @@ ext.configureVariantWithGeckoBinaries = 
     def syncAssetsFromDistDir = task("syncAssetsFromDistDirFor${variant.name.capitalize()}", type: Sync) {
         into("${project.buildDir}/moz.build/src/${variant.name}/assets")
         from("${distDir}/assets") {
             exclude 'omni.ja'
         }
     }
 
     // Local (read, not 'official') builds want to reflect developer changes to
-    // the Omnijar sources.  To do this, the Gradle build calls out to the
+    // the omnijar sources, and (when compiling) to reflect developer changes to
+    // the native binaries.  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) {
-        syncOmnijarFromDistDir.dependsOn buildOmnijars
+        if ("app".equals(project.name)) {
+            syncOmnijarFromDistDir.dependsOn rootProject.machStagePackageForFennec
+            syncLibsFromDistDir.dependsOn rootProject.machStagePackageForFennec
+            syncAssetsFromDistDir.dependsOn rootProject.machStagePackageForFennec
+        } else {
+            syncOmnijarFromDistDir.dependsOn rootProject.machStagePackageForGeckoview
+            syncLibsFromDistDir.dependsOn rootProject.machStagePackageForGeckoview
+            syncAssetsFromDistDir.dependsOn rootProject.machStagePackageForGeckoview
+        }
     }
 
     def assetGenTask = tasks.findByName("generate${variant.name.capitalize()}Assets")
     if ((variant.productFlavors*.name).contains('withGeckoBinaries')) {
         assetGenTask.dependsOn syncOmnijarFromDistDir
         assetGenTask.dependsOn syncLibsFromDistDir
         assetGenTask.dependsOn syncAssetsFromDistDir