Bug 1444546 - Part 2: Build annotationProcessors with Gradle. r=jchen
We want annotationProcessors to be compiled and archived into a JAR at
build time, ready to generate JNI wrappers. (That is, until we turn
the whole thing into a real annotation processor.) But even if we do
use a real annotation processor, we still need to generate SDK
bindings, which is less clearly expressed as an annotation processor.
(It's more of a build step.)
Gradle provides a huge number of ways to organize build logic to
achieve this: see
https://docs.gradle.org/current/userguide/organizing_build_logic.html.
Unfortunately, the best such way -- putting the code into
$topsrcdir/buildSrc -- has key disadvantages:
1) it pollutes the top-level $topsrcdir, and there's no way to change the
location of buildSrc (https://github.com/gradle/gradle/issues/2472);
2) it's complicated to have a dependent project
(mobile/android/annotations) expose its code via a buildSrc project;
3) using buildSrc at all appears to conflict with the Android-Gradle
plugin version that we are using.
Therefore, this commit does something much simpler: it adds a
Java-only project and uses the resulting Gradle "Jar" task and archive
output as input to the existing Gradle "generate JNI wrappers" task.
MozReview-Commit-ID: 2OyYLPneE1M
deleted file mode 100644
--- a/build/annotationProcessors/Makefile.in
+++ /dev/null
@@ -1,10 +0,0 @@
-# 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/.
-
-include $(topsrcdir)/config/rules.mk
-
-# Include Android specific java flags, instead of what's in rules.mk.
-include $(topsrcdir)/config/android-common.mk
-
-export:: annotationProcessors.jar
deleted file mode 100644
--- a/build/annotationProcessors/moz.build
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
-# vim: set filetype=python:
-# 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/.
-
-jar = add_java_jar('annotationProcessors')
-jar.sources += [
- 'AnnotationInfo.java',
- 'AnnotationProcessor.java',
- 'classloader/AnnotatableEntity.java',
- 'classloader/ClassWithOptions.java',
- 'classloader/IterableJarLoadingURLClassLoader.java',
- 'classloader/JarClassIterator.java',
- 'CodeGenerator.java',
- 'SDKProcessor.java',
- 'utils/AlphabeticAnnotatableEntityComparator.java',
- 'utils/GeneratableElementIterator.java',
- 'utils/Utils.java',
-]
-jar.extra_jars += CONFIG['ANDROID_LINT_CLASSPATH'].split()
--- a/build/moz.build
+++ b/build/moz.build
@@ -19,19 +19,16 @@ if CONFIG['OS_ARCH'] == 'WINNT':
CONFIGURE_SUBST_FILES += ['win64/cargo-linker.bat']
else:
DIRS += ['unix']
CRAMTEST_MANIFESTS += [
'tests/cram/cram.ini',
]
-if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android':
- DIRS += ['annotationProcessors']
-
DEFINES['ACCEPTED_MAR_CHANNEL_IDS'] = CONFIG['ACCEPTED_MAR_CHANNEL_IDS']
if CONFIG['MOZ_BUILD_APP'] == 'browser':
PYTHON_UNITTEST_MANIFESTS += [
'compare-mozconfig/python.ini',
]
if CONFIG['ENABLE_TESTS'] or CONFIG['MOZ_DMD']:
--- a/config/recurse.mk
+++ b/config/recurse.mk
@@ -160,19 +160,16 @@ recurse:
@$(RECURSED_COMMAND)
$(LOOP_OVER_DIRS)
ifeq (.,$(DEPTH))
# Interdependencies for parallel export.
js/xpconnect/src/export: dom/bindings/export xpcom/xpidl/export
accessible/xpcom/export: xpcom/xpidl/export
-# The widget binding generator code is part of the annotationProcessors.
-widget/android/bindings/export: build/annotationProcessors/export
-
# .xpt generation needs the xpidl lex/yacc files
xpcom/xpidl/export: xpcom/idl-parser/xpidl/export
# CSS2Properties.webidl needs ServoCSSPropList.py from layout/style
dom/bindings/export: layout/style/export
ifdef ENABLE_CLANG_PLUGIN
$(filter-out config/host build/unix/stdc++compat/% build/clang-plugin/%,$(compile_targets)): build/clang-plugin/target build/clang-plugin/tests/target
new file mode 100644
--- /dev/null
+++ b/mobile/android/annotations/build.gradle
@@ -0,0 +1,11 @@
+buildDir "${topobjdir}/gradle/build/mobile/android/annotations"
+
+apply plugin: 'java'
+
+dependencies {
+ compile 'com.android.tools.lint:lint:25.3.1'
+ compile 'com.android.tools.lint:lint-checks:25.3.1'
+}
+
+sourceCompatibility = JavaVersion.VERSION_1_8
+targetCompatibility = JavaVersion.VERSION_1_8
--- a/mobile/android/gradle/with_gecko_binaries.gradle
+++ b/mobile/android/gradle/with_gecko_binaries.gradle
@@ -114,62 +114,67 @@ ext.configureLibraryVariantWithJNIWrappe
// ...WithPrepareIntermediateJars..., so we make the consuming moz.build
// system invoke this target directly, and force the
// ...WithPrepareIntermediateJars... dependency. The real consumer of the
// JNI wrappers is the moz.build system, which always builds geckoview to
// consume from Fennec, so that dependency likely adds less to the build time.
def jarTask = tasks["transformClassesAndResourcesWithPrepareIntermediateJarsFor${variant.name.capitalize()}"]
def output = jarTask.outputs.files.find({ it.absolutePath.contains('/classes.jar') })
+ def annotationProcessorsJarTask = project(':annotations').jar
+
def wrapperTask
if (System.env.IS_LANGUAGE_REPACK == '1') {
// Single-locale l10n repacks set `IS_LANGUAGE_REPACK=1` and don't
// really have a build environment.
wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}")
} else {
wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}", type: JavaExec) {
- classpath "${topobjdir}/build/annotationProcessors/annotationProcessors.jar"
+ classpath annotationProcessorsJarTask.archivePath
// Configure the classpath at evaluation-time, not at
// configuration-time: see above comment.
doFirst {
classpath variant.javaCompile.classpath
// Include android.jar.
classpath variant.javaCompile.options.bootClasspath
}
main = 'org.mozilla.gecko.annotationProcessors.AnnotationProcessor'
args module
args output
workingDir "${topobjdir}/mobile/android/base"
dependsOn jarTask
+ dependsOn annotationProcessorsJarTask
}
}
if (module == 'Generated') {
tasks["bundle${variant.name.capitalize()}"].dependsOn wrapperTask
} else {
tasks["assemble${variant.name.capitalize()}"].dependsOn wrapperTask
}
}
ext.configureApplicationVariantWithJNIWrappers = { variant, module ->
def jarTask = tasks["bundleAppClasses${variant.name.capitalize()}"]
def output = jarTask.outputs.files.find({ it.absolutePath.contains('/classes.jar') })
+ def annotationProcessorsJarTask = project(':annotations').jar
+
def wrapperTask
if (System.env.IS_LANGUAGE_REPACK == '1') {
// Single-locale l10n repacks set `IS_LANGUAGE_REPACK=1` and don't
// really have a build environment.
wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}")
} else {
wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}", type: JavaExec) {
- classpath "${topobjdir}/build/annotationProcessors/annotationProcessors.jar"
+ classpath annotationProcessorsJarTask.archivePath
// Configure the classpath at evaluation-time, not at
// configuration-time: see above comment.
doFirst {
classpath variant.javaCompile.classpath
// Include android.jar.
classpath variant.javaCompile.options.bootClasspath
}
@@ -177,11 +182,13 @@ ext.configureApplicationVariantWithJNIWr
main = 'org.mozilla.gecko.annotationProcessors.AnnotationProcessor'
args module
args output
workingDir "${topobjdir}/mobile/android/base"
// This forces bundling, which isn't usually part of the assemble* process.
dependsOn jarTask
+
+ dependsOn annotationProcessorsJarTask
}
}
}
--- a/settings.gradle
+++ b/settings.gradle
@@ -9,36 +9,39 @@ proc.consumeProcessOutput(standardOutput
proc.waitFor()
// Only show the output if something went wrong.
if (proc.exitValue() != 0) {
throw new GradleException("Process '${commandLine}' finished with non-zero exit value ${proc.exitValue()}:\n\n${standardOutput.toString()}")
}
import groovy.json.JsonSlurper
+
def slurper = new JsonSlurper()
def json = slurper.parseText(standardOutput.toString())
if (json.substs.MOZ_BUILD_APP != 'mobile/android') {
throw new GradleException("Building with Gradle is only supported for Fennec, i.e., MOZ_BUILD_APP == 'mobile/android'.")
}
// Set the Android SDK location. This is the *least specific* mechanism, which
// is unfortunate: we'd prefer to use the *most specific* mechanism. That is,
// local.properties (first 'sdk.dir', then 'android.dir') and then the
// environment variable ANDROID_HOME will override this. That's unfortunate,
// but it's hard to automatically arrange better.
System.setProperty('android.home', json.substs.ANDROID_SDK_ROOT)
+include ':annotations'
include ':app'
include ':geckoview'
include ':geckoview_example'
include ':omnijar'
include ':thirdparty'
+project(':annotations').projectDir = new File("${json.topsrcdir}/mobile/android/annotations")
project(':app').projectDir = new File("${json.topsrcdir}/mobile/android/app")
project(':geckoview').projectDir = new File("${json.topsrcdir}/mobile/android/geckoview")
project(':geckoview_example').projectDir = new File("${json.topsrcdir}/mobile/android/geckoview_example")
project(':omnijar').projectDir = new File("${json.topsrcdir}/mobile/android/app/omnijar")
project(':thirdparty').projectDir = new File("${json.topsrcdir}/mobile/android/thirdparty")
// The Gradle instance is shared between settings.gradle and all the
// other build.gradle files (see