Bug 1411654 - Part 3: Make each variant handle source from moz.build. r=maliu
☠☠ backed out by 64f824603458 ☠ ☠
authorNick Alexander <nalexander@mozilla.com>
Thu, 09 Nov 2017 13:47:46 -0800
changeset 450897 6ff0cdf46a3df61ee10b79b35669bb3193ff78e9
parent 450896 0e493bacc5e396aba37213caae165c8984dedcbc
child 450898 56538ed998cfdb84d6f648f7234e2180a3b91537
push id8543
push userryanvm@gmail.com
push dateTue, 16 Jan 2018 14:33:22 +0000
treeherdermozilla-beta@a6525ed16a32 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmaliu
bugs1411654
milestone59.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 1411654 - Part 3: Make each variant handle source from moz.build. r=maliu The advantage of doing this per-variant is that we can really separate the 'local' behaviour (re-generate via re-entrant |mach build| invocations) from the 'official' behaviour (never re-generate via re-entrance). This also uses new Android-Gradle plugin 3.0+ APIs to integrate the generated resources and Java code. MozReview-Commit-ID: 4pd2iw1nJSb
mobile/android/app/build.gradle
--- a/mobile/android/app/build.gradle
+++ b/mobile/android/app/build.gradle
@@ -156,48 +156,33 @@ android {
                 } else {
                     exclude 'org/mozilla/gecko/mma/MmaLeanplumImp.java'
                 }
 
                 if (!mozconfig.substs.MOZ_ANDROID_GCM) {
                     exclude 'org/mozilla/gecko/gcm/**/*.java'
                     exclude 'org/mozilla/gecko/push/**/*.java'
                 }
-
-                srcDir "${project.buildDir}/generated/source/preprocessed_code" // See syncPreprocessedCode.
             }
 
             res {
                 srcDir "${topsrcdir}/${mozconfig.substs.MOZ_BRANDING_DIRECTORY}/res"
-                srcDir "${project.buildDir}/generated/source/preprocessed_resources" // See syncPreprocessedResources.
                 srcDir "${topsrcdir}/mobile/android/services/src/main/res"
                 if (mozconfig.substs.MOZ_CRASHREPORTER) {
                     srcDir "${topsrcdir}/mobile/android/base/crashreporter/res"
                 }
             }
 
             assets {
                 if (mozconfig.substs.MOZ_ANDROID_DISTRIBUTION_DIRECTORY) {
                     srcDir "${mozconfig.substs.MOZ_ANDROID_DISTRIBUTION_DIRECTORY}/assets"
                 }
             }
         }
 
-        // Every configuration needs the stub manifest at
-        // src/main/AndroidManifest.xml and the generated manifest.  We can't
-        // use the main sourceSet without losing the stub, so we cover all the
-        // configurations by enumerating the buildTypes here.
-        debug {
-            manifest.srcFile "${project.buildDir}/generated/source/preprocessed_manifest/AndroidManifest.xml"
-        }
-
-        release {
-            manifest.srcFile "${project.buildDir}/generated/source/preprocessed_manifest/AndroidManifest.xml"
-        }
-
         test {
             java {
                 // Bug 1229149 tracks pushing this into a :services Gradle project.
                 srcDir "${topsrcdir}/mobile/android/services/src/test/java"
 
                 if (!mozconfig.substs.MOZ_ANDROID_GCM) {
                     exclude 'org/mozilla/gecko/gcm/**/*.java'
                     exclude 'org/mozilla/gecko/push/**/*.java'
@@ -297,60 +282,89 @@ task checkstyle(type: Checkstyle) {
     // TODO: should use sourceSets from project instead of hard-coded str.
     source = ['../base/java/','../geckoview/src/main/java/']
     // TODO: This ignores our pre-processed resources.
     include '**/*.java'
     // TODO: classpath should probably be something.
     classpath = files()
 }
 
-task syncPreprocessedCode(type: Sync, dependsOn: rootProject.generateCodeAndResources) {
-    into("${project.buildDir}/generated/source/preprocessed_code")
-    from("${topobjdir}/mobile/android/base/generated/preprocessed")
-}
-
 // The localization system uses the moz.build preprocessor to interpolate a .dtd
 // file of XML entity definitions into an XML file of elements referencing those
 // entities.  (Each locale produces its own .dtd file, backstopped by the en-US
 // .dtd file in tree.)  Android Studio (and IntelliJ) don't handle these inline
 // entities smoothly.  This filter merely expands the entities in place, making
 // them appear properly throughout the IDE.  Be aware that this assumes that the
 // JVM's file.encoding is utf-8.  See comments in
 // mobile/android/mach_commands.py.
 class ExpandXMLEntitiesFilter extends FilterReader {
     ExpandXMLEntitiesFilter(Reader input) {
         // Extremely inefficient, but whatever.
         super(new StringReader(groovy.xml.XmlUtil.serialize(new XmlParser(false, false, true).parse(input))))
     }
 }
 
-task syncPreprocessedResources(type: Sync, dependsOn: rootProject.generateCodeAndResources) {
-    into("${project.buildDir}/generated/source/preprocessed_resources")
-    from("${topobjdir}/mobile/android/base/res")
-    filesMatching('**/strings.xml') {
-        filter(ExpandXMLEntitiesFilter)
-    }
-}
-
-// 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.
-task rewriteManifestPackage(type: Copy, dependsOn: rootProject.generateCodeAndResources) {
-    into("${project.buildDir}/generated/source/preprocessed_manifest")
-    from("${topobjdir}/mobile/android/base/AndroidManifest.xml")
-    filter { it.replaceFirst(/package=".*?"/, 'package="org.mozilla.gecko"') }
-}
-
 apply from: "${topsrcdir}/mobile/android/gradle/with_gecko_binaries.gradle"
 
 android.applicationVariants.all { variant ->
+    def syncPreprocessedJava = task("syncPreprocessedJavaFor${variant.name.capitalize()}", type: Sync) {
+        into("${project.buildDir}/moz.build/src/${variant.name}/java")
+        from("${topobjdir}/mobile/android/base/generated/preprocessed")
+        exclude('**/*.mkdir.done')
+    }
+    // This is an Android-Gradle plugin 3+-ism.  Culted from reading the source,
+    // searching for "registerJavaGeneratingTask", and finding
+    // https://github.com/GoogleCloudPlatform/endpoints-framework-gradle-plugin/commit/2f2b91476fb1c6647791e2c6fe531a47615a1e85.
+    // The added directory doesn't appear in the paths listed by the
+    // `sourceSets` task, for reasons unknown.
+    variant.registerJavaGeneratingTask(syncPreprocessedJava, syncPreprocessedJava.destinationDir)
+
+    def syncPreprocessedRes = task("syncPreprocessedResFor${variant.name.capitalize()}", type: Sync) {
+        into("${project.buildDir}/moz.build/src/${variant.name}/res")
+        from("${topobjdir}/mobile/android/base/res")
+        filesMatching('**/strings.xml') {
+            filter(ExpandXMLEntitiesFilter)
+        }
+        exclude('**/*.mkdir.done')
+    }
+    // This is an Android-Gradle plugin 3+-ism.  Determined by reading the
+    // source.  The added directory doesn't appear in the paths listed by the
+    // `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) {
+        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
+    // the main sourceSet without losing the stub, so we cover all the
+    // configurations here.
+    android.sourceSets."${variant.name}".manifest.srcFile "${rewriteManifestPackage.destinationDir}/AndroidManifest.xml"
     variant.preBuild.dependsOn rewriteManifestPackage
-    variant.preBuild.dependsOn syncPreprocessedCode
-    variant.preBuild.dependsOn syncPreprocessedResources
+
+
+    // 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 (!((variant.productFlavors*.name).contains('official'))) {
+        syncPreprocessedJava.dependsOn rootProject.generateCodeAndResources
+        syncPreprocessedRes.dependsOn rootProject.generateCodeAndResources
+        rewriteManifestPackage.dependsOn rootProject.generateCodeAndResources
+    }
 
     // Official automation builds don't include Gecko binaries, since those binaries are not
     // produced until after build time (at package time).  official Therefore, automation builds
     // include the Gecko binaries into the APK at package time.  The "withGeckoBinaries" variant of
     // the :geckoview project also does this.  (It does what it says on the tin!)  For notes on this
     // approach, see mobile/android/gradle/with_gecko_binaries.gradle.
 
     // Like 'local' or 'localOld'.