зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1444546 - Part 3: Use GENERATED_FILES for Android SDK bindings generation. r=froydnj,jchen
MozReview-Commit-ID: 2blmzKTvpj3 --HG-- extra : rebase_source : 0954b407ce6625510eadc67dd9989da949b22110
This commit is contained in:
Родитель
520b63c85e
Коммит
53a4852ffa
|
@ -94,8 +94,6 @@ dnl Configure an Android SDK.
|
|||
dnl Arg 1: compile SDK version, like 23.
|
||||
dnl Arg 2: target SDK version, like 23.
|
||||
dnl Arg 3: list of build-tools versions, like "23.0.3 23.0.1".
|
||||
dnl Arg 4: list of target lint versions, like "25.3.2 25.3.1" (note: we fall back to
|
||||
dnl unversioned lint if this version is not found).
|
||||
AC_DEFUN([MOZ_ANDROID_SDK],
|
||||
[
|
||||
|
||||
|
@ -194,33 +192,6 @@ case "$target" in
|
|||
;;
|
||||
esac
|
||||
|
||||
AC_MSG_CHECKING([for Android lint classpath])
|
||||
ANDROID_LINT_CLASSPATH=""
|
||||
for version in $4; do
|
||||
android_lint_versioned_jar="$ANDROID_SDK_ROOT/tools/lib/lint-$version.jar"
|
||||
if test -e "$android_lint_versioned_jar" ; then
|
||||
ANDROID_LINT_CLASSPATH="$ANDROID_LINT_CLASSPATH $android_lint_versioned_jar"
|
||||
ANDROID_LINT_CLASSPATH="$ANDROID_LINT_CLASSPATH $ANDROID_SDK_ROOT/tools/lib/lint-checks-$version.jar"
|
||||
ANDROID_LINT_CLASSPATH="$ANDROID_LINT_CLASSPATH $ANDROID_SDK_ROOT/tools/lib/sdklib-$version.jar"
|
||||
ANDROID_LINT_CLASSPATH="$ANDROID_LINT_CLASSPATH $ANDROID_SDK_ROOT/tools/lib/repository-$version.jar"
|
||||
ANDROID_LINT_CLASSPATH="$ANDROID_LINT_CLASSPATH $ANDROID_SDK_ROOT/tools/lib/common-$version.jar"
|
||||
ANDROID_LINT_CLASSPATH="$ANDROID_LINT_CLASSPATH $ANDROID_SDK_ROOT/tools/lib/lint-api-$version.jar"
|
||||
ANDROID_LINT_CLASSPATH="$ANDROID_LINT_CLASSPATH $ANDROID_SDK_ROOT/tools/lib/manifest-merger-$version.jar"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if test -z "$ANDROID_LINT_CLASSPATH" ; then
|
||||
android_lint_unversioned_jar="$ANDROID_SDK_ROOT/tools/lib/lint.jar"
|
||||
if test -e "$android_lint_unversioned_jar" ; then
|
||||
ANDROID_LINT_CLASSPATH="$ANDROID_LINT_CLASSPATH $android_lint_unversioned_jar"
|
||||
ANDROID_LINT_CLASSPATH="$ANDROID_LINT_CLASSPATH $ANDROID_SDK_ROOT/tools/lib/lint-checks.jar"
|
||||
else
|
||||
AC_MSG_ERROR([Unable to find android sdk's lint jar. This probably means that you need to update android.m4 to find the latest version of lint-*.jar and all its dependencies. (looked for $android_lint_versioned_jar and $android_lint_unversioned_jar)])
|
||||
fi
|
||||
fi
|
||||
AC_MSG_RESULT([$ANDROID_LINT_CLASSPATH])
|
||||
AC_SUBST(ANDROID_LINT_CLASSPATH)
|
||||
|
||||
MOZ_ARG_WITH_STRING(android-min-sdk,
|
||||
[ --with-android-min-sdk=[VER] Impose a minimum Firefox for Android SDK version],
|
||||
[ MOZ_ANDROID_MIN_SDK_VERSION=$withval ])
|
||||
|
|
|
@ -165,6 +165,10 @@ ifeq (.,$(DEPTH))
|
|||
js/xpconnect/src/export: dom/bindings/export xpcom/xpidl/export
|
||||
accessible/xpcom/export: xpcom/xpidl/export
|
||||
|
||||
# The Android SDK bindings needs to build the Java generator code
|
||||
# source code in order to write the SDK bindings.
|
||||
widget/android/bindings/export: mobile/android/base/export
|
||||
|
||||
# .xpt generation needs the xpidl lex/yacc files
|
||||
xpcom/xpidl/export: xpcom/idl-parser/xpidl/export
|
||||
|
||||
|
|
|
@ -7,16 +7,16 @@ package org.mozilla.gecko.annotationProcessors;
|
|||
/**
|
||||
* Generate C++ bindings for SDK classes using a config file.
|
||||
*
|
||||
* java SDKProcessor <sdkjar> <configfile> <outdir> <fileprefix> <max-sdk-version>
|
||||
* java SDKProcessor <sdkjar> <max-sdk-version> <outdir> [<configfile> <fileprefix>]+
|
||||
*
|
||||
* <sdkjar>: jar file containing the SDK classes (e.g. android.jar)
|
||||
* <configfile>: config file for generating bindings
|
||||
* <outdir>: output directory for generated binding files
|
||||
* <fileprefix>: prefix used for generated binding files
|
||||
* <max-sdk-version>: SDK version for generated class members (bindings will not be
|
||||
* generated for members with SDK versions higher than max-sdk-version)
|
||||
* <outdir>: output directory for generated binding files
|
||||
* <configfile>: config file for generating bindings
|
||||
* <fileprefix>: prefix used for generated binding files
|
||||
*
|
||||
* The config file is a text file following the .ini format:
|
||||
* Each config file is a text file following the .ini format:
|
||||
*
|
||||
* ; comment
|
||||
* [section1]
|
||||
|
@ -226,93 +226,98 @@ public class SDKProcessor {
|
|||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// We expect a list of jars on the commandline. If missing, whinge about it.
|
||||
if (args.length < 5) {
|
||||
System.err.println("Usage: java SDKProcessor sdkjar configfile outdir fileprefix max-sdk-version");
|
||||
if (args.length < 5 || args.length % 2 != 1) {
|
||||
System.err.println("Usage: java SDKProcessor sdkjar max-sdk-version outdir [configfile fileprefix]+");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
System.out.println("Processing platform bindings...");
|
||||
|
||||
String sdkJar = args[0];
|
||||
String outdir = args[2];
|
||||
String generatedFilePrefix = args[3];
|
||||
sMaxSdkVersion = Integer.parseInt(args[4]);
|
||||
final String sdkJar = args[0];
|
||||
sMaxSdkVersion = Integer.parseInt(args[1]);
|
||||
final String outdir = args[2];
|
||||
|
||||
LintCliClient lintClient = new LintCliClient();
|
||||
final LintCliClient lintClient = new LintCliClient();
|
||||
sApiLookup = ApiLookup.get(lintClient);
|
||||
|
||||
// Start the clock!
|
||||
long s = System.currentTimeMillis();
|
||||
for (int argIndex = 3; argIndex < args.length; argIndex += 2) {
|
||||
final String configFile = args[argIndex];
|
||||
final String generatedFilePrefix = args[argIndex + 1];
|
||||
System.out.println("Processing bindings from " + configFile);
|
||||
|
||||
// Get an iterator over the classes in the jar files given...
|
||||
// Iterator<ClassWithOptions> jarClassIterator = IterableJarLoadingURLClassLoader.getIteratorOverJars(args);
|
||||
// Start the clock!
|
||||
long s = System.currentTimeMillis();
|
||||
|
||||
StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT);
|
||||
headerFile.append(
|
||||
"#ifndef " + generatedFilePrefix + "_h__\n" +
|
||||
"#define " + generatedFilePrefix + "_h__\n" +
|
||||
"\n" +
|
||||
"#include \"mozilla/jni/Refs.h\"\n" +
|
||||
"\n" +
|
||||
"namespace mozilla {\n" +
|
||||
"namespace java {\n" +
|
||||
"namespace sdk {\n" +
|
||||
"\n");
|
||||
// Get an iterator over the classes in the jar files given...
|
||||
// Iterator<ClassWithOptions> jarClassIterator = IterableJarLoadingURLClassLoader.getIteratorOverJars(args);
|
||||
|
||||
StringBuilder implementationFile = new StringBuilder(GENERATED_COMMENT);
|
||||
implementationFile.append(
|
||||
"#include \"" + generatedFilePrefix + ".h\"\n" +
|
||||
"#include \"mozilla/jni/Accessors.h\"\n" +
|
||||
"\n" +
|
||||
"namespace mozilla {\n" +
|
||||
"namespace java {\n" +
|
||||
"namespace sdk {\n" +
|
||||
"\n");
|
||||
StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT);
|
||||
headerFile.append(
|
||||
"#ifndef " + generatedFilePrefix + "_h__\n" +
|
||||
"#define " + generatedFilePrefix + "_h__\n" +
|
||||
"\n" +
|
||||
"#include \"mozilla/jni/Refs.h\"\n" +
|
||||
"\n" +
|
||||
"namespace mozilla {\n" +
|
||||
"namespace java {\n" +
|
||||
"namespace sdk {\n" +
|
||||
"\n");
|
||||
|
||||
// Used to track the calls to the various class-specific initialisation functions.
|
||||
ClassLoader loader = null;
|
||||
try {
|
||||
loader = URLClassLoader.newInstance(new URL[] { new URL("file://" + sdkJar) },
|
||||
SDKProcessor.class.getClassLoader());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e.toString());
|
||||
}
|
||||
StringBuilder implementationFile = new StringBuilder(GENERATED_COMMENT);
|
||||
implementationFile.append(
|
||||
"#include \"" + generatedFilePrefix + ".h\"\n" +
|
||||
"#include \"mozilla/jni/Accessors.h\"\n" +
|
||||
"\n" +
|
||||
"namespace mozilla {\n" +
|
||||
"namespace java {\n" +
|
||||
"namespace sdk {\n" +
|
||||
"\n");
|
||||
|
||||
try {
|
||||
final ClassInfo[] classes = getClassList(args[1]);
|
||||
for (final ClassInfo cls : classes) {
|
||||
System.out.println("Looking up: " + cls.name);
|
||||
generateClass(Class.forName(cls.name, true, loader),
|
||||
cls,
|
||||
implementationFile,
|
||||
headerFile);
|
||||
// Used to track the calls to the various class-specific initialisation functions.
|
||||
ClassLoader loader = null;
|
||||
try {
|
||||
loader = URLClassLoader.newInstance(new URL[]{new URL("file://" + sdkJar)},
|
||||
SDKProcessor.class.getClassLoader());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e.toString());
|
||||
}
|
||||
} catch (final IllegalStateException|IOException|ParseException e) {
|
||||
System.err.println("***");
|
||||
System.err.println("*** Error parsing config file: " + args[1]);
|
||||
System.err.println("*** " + e);
|
||||
System.err.println("***");
|
||||
if (e.getCause() != null) {
|
||||
e.getCause().printStackTrace(System.err);
|
||||
|
||||
try {
|
||||
final ClassInfo[] classes = getClassList(configFile);
|
||||
for (final ClassInfo cls : classes) {
|
||||
System.out.println("Looking up: " + cls.name);
|
||||
generateClass(Class.forName(cls.name, true, loader),
|
||||
cls,
|
||||
implementationFile,
|
||||
headerFile);
|
||||
}
|
||||
} catch (final IllegalStateException | IOException | ParseException e) {
|
||||
System.err.println("***");
|
||||
System.err.println("*** Error parsing config file: " + configFile);
|
||||
System.err.println("*** " + e);
|
||||
System.err.println("***");
|
||||
if (e.getCause() != null) {
|
||||
e.getCause().printStackTrace(System.err);
|
||||
}
|
||||
System.exit(1);
|
||||
return;
|
||||
}
|
||||
System.exit(1);
|
||||
return;
|
||||
|
||||
implementationFile.append(
|
||||
"} /* sdk */\n" +
|
||||
"} /* java */\n" +
|
||||
"} /* mozilla */\n");
|
||||
|
||||
headerFile.append(
|
||||
"} /* sdk */\n" +
|
||||
"} /* java */\n" +
|
||||
"} /* mozilla */\n" +
|
||||
"#endif\n");
|
||||
|
||||
writeOutputFiles(outdir, generatedFilePrefix, headerFile, implementationFile);
|
||||
long e = System.currentTimeMillis();
|
||||
System.out.println("SDK processing complete in " + (e - s) + "ms");
|
||||
}
|
||||
|
||||
implementationFile.append(
|
||||
"} /* sdk */\n" +
|
||||
"} /* java */\n" +
|
||||
"} /* mozilla */\n");
|
||||
|
||||
headerFile.append(
|
||||
"} /* sdk */\n" +
|
||||
"} /* java */\n" +
|
||||
"} /* mozilla */\n" +
|
||||
"#endif\n");
|
||||
|
||||
writeOutputFiles(outdir, generatedFilePrefix, headerFile, implementationFile);
|
||||
long e = System.currentTimeMillis();
|
||||
System.out.println("SDK processing complete in " + (e - s) + "ms");
|
||||
}
|
||||
|
||||
private static int getAPIVersion(Class<?> cls, Member m) {
|
||||
|
|
|
@ -168,3 +168,5 @@ libs:: FennecJNIWrappers.cpp
|
|||
|
||||
endif # ifneq (multi,$(AB_CD))
|
||||
endif # ifeq (,$(IS_LANGUAGE_REPACK))
|
||||
|
||||
export:: android_apks
|
||||
|
|
|
@ -5,6 +5,10 @@ apply plugin: 'kotlin-android'
|
|||
|
||||
apply from: "${topsrcdir}/mobile/android/gradle/product_flavors.gradle"
|
||||
|
||||
// The SDK binding generation tasks depend on the JAR creation task of the
|
||||
// :annotations project.
|
||||
evaluationDependsOn(':annotations')
|
||||
|
||||
// Non-official versions are like "61.0a1", where "a1" is the milestone.
|
||||
// This simply strips that off, leaving "61.0" in this example.
|
||||
def getAppVersionWithoutMilestone() {
|
||||
|
@ -327,3 +331,33 @@ afterEvaluate {
|
|||
// Bug 1353055 - Strip 'vars' debugging information to agree with moz.build.
|
||||
apply from: "${topsrcdir}/mobile/android/gradle/debug_level.gradle"
|
||||
android.libraryVariants.all configureVariantDebugLevel
|
||||
|
||||
// There's nothing specific to the :geckoview project here -- this just needs to
|
||||
// be somewhere where the Android plugin is available so that we can fish the
|
||||
// path to "android.jar".
|
||||
task("generateSDKBindings", type: JavaExec) {
|
||||
classpath project(':annotations').jar.archivePath
|
||||
classpath project(':annotations').compileJava.classpath
|
||||
|
||||
// To use the lint APIs: "Lint must be invoked with the System property
|
||||
// com.android.tools.lint.bindir pointing to the ANDROID_SDK tools
|
||||
// directory"
|
||||
systemProperties = [
|
||||
'com.android.tools.lint.bindir': "${android.sdkDirectory}/tools",
|
||||
]
|
||||
|
||||
main = 'org.mozilla.gecko.annotationProcessors.SDKProcessor'
|
||||
args android.bootClasspath
|
||||
args 16
|
||||
args "${topobjdir}/widget/android/bindings"
|
||||
|
||||
// Configure the arguments at evaluation-time, not at configuration-time.
|
||||
doFirst {
|
||||
// From -Pgenerate_sdk_bindings_args=... on command line.
|
||||
args project.generate_sdk_bindings_args.split(':')
|
||||
}
|
||||
|
||||
workingDir "${topsrcdir}/widget/android/bindings"
|
||||
|
||||
dependsOn project(':annotations').jar
|
||||
}
|
||||
|
|
|
@ -101,6 +101,16 @@ def gradle_android_app_tasks(build_config):
|
|||
set_config('GRADLE_ANDROID_APP_TASKS', gradle_android_app_tasks)
|
||||
|
||||
|
||||
@dependable
|
||||
def gradle_android_generate_sdk_bindings_tasks():
|
||||
'''Gradle tasks run by |mach android generate-sdk-bindings|.'''
|
||||
return [
|
||||
'geckoview:generateSDKBindings',
|
||||
]
|
||||
|
||||
set_config('GRADLE_ANDROID_GENERATE_SDK_BINDINGS_TASKS', gradle_android_generate_sdk_bindings_tasks)
|
||||
|
||||
|
||||
@depends(gradle_android_build_config, check_build_environment)
|
||||
@imports(_from='itertools', _import='imap')
|
||||
def gradle_android_app_apks(build_config, build_env):
|
||||
|
@ -204,6 +214,7 @@ set_config('GRADLE_ANDROID_ARCHIVE_GECKOVIEW_TASKS', gradle_android_archive_geck
|
|||
gradle_android_checkstyle_tasks,
|
||||
gradle_android_findbugs_tasks,
|
||||
gradle_android_archive_geckoview_tasks,
|
||||
gradle_android_generate_sdk_bindings_tasks,
|
||||
)
|
||||
@imports(_from='itertools', _import='imap')
|
||||
@imports(_from='itertools', _import='chain')
|
||||
|
|
|
@ -37,3 +37,7 @@ def android(verb, *args):
|
|||
|
||||
def assemble_app(dummy_output_file, *inputs):
|
||||
return android('assemble-app')
|
||||
|
||||
|
||||
def generate_sdk_bindings(dummy_output_file, *args):
|
||||
return android('generate-sdk-bindings', *args)
|
||||
|
|
|
@ -8,6 +8,9 @@
|
|||
// :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
|
||||
|
||||
|
|
|
@ -53,7 +53,6 @@ class MachCommands(MachCommandBase):
|
|||
def android(self):
|
||||
pass
|
||||
|
||||
|
||||
@SubCommand('android', 'assemble-app',
|
||||
"""Assemble Firefox for Android.
|
||||
See http://firefox-source-docs.mozilla.org/build/buildsystem/toolchains.html#firefox-for-android-with-gradle""")
|
||||
|
@ -64,6 +63,25 @@ class MachCommands(MachCommandBase):
|
|||
return ret
|
||||
|
||||
|
||||
@SubCommand('android', 'generate-sdk-bindings',
|
||||
"""Generate SDK bindings used when building GeckoView.""")
|
||||
@CommandArgument('inputs', nargs='+', help='config files, like [/path/to/ClassName-classes.txt]+')
|
||||
@CommandArgument('args', nargs=argparse.REMAINDER)
|
||||
def android_generate_sdk_bindings(self, inputs, args):
|
||||
import itertools
|
||||
|
||||
def stem(input):
|
||||
# Turn "/path/to/ClassName-classes.txt" into "ClassName".
|
||||
return os.path.basename(input).rsplit('-classes.txt', 1)[0]
|
||||
|
||||
bindings_inputs = list(itertools.chain(*((input, stem(input)) for input in inputs)))
|
||||
bindings_args = '-Pgenerate_sdk_bindings_args={}'.format(':'.join(bindings_inputs))
|
||||
|
||||
ret = self.gradle(self.substs['GRADLE_ANDROID_GENERATE_SDK_BINDINGS_TASKS'] + [bindings_args] + args, verbose=True)
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
@SubCommand('android', 'test',
|
||||
"""Run Android local unit tests.
|
||||
See https://developer.mozilla.org/en-US/docs/Mozilla/Android-specific_test_suites#android-test""")
|
||||
|
|
|
@ -2080,7 +2080,7 @@ dnl ========================================================
|
|||
|
||||
case "$MOZ_BUILD_APP" in
|
||||
mobile/android)
|
||||
MOZ_ANDROID_SDK(23, 23, 26.0.2, 26.0.0 26.0.0-dev 25.3.2 25.3.1)
|
||||
MOZ_ANDROID_SDK(23, 23, 26.0.2)
|
||||
;;
|
||||
esac
|
||||
|
||||
|
|
|
@ -1,26 +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/.
|
||||
|
||||
# Bug 1099345 - The SDK's lint code (used by the code generator) does not enjoy
|
||||
# concurrent access to a cache that it generates.
|
||||
.NOTPARALLEL:
|
||||
|
||||
annotation_processor_jar_files := \
|
||||
$(DEPTH)/build/annotationProcessors/annotationProcessors.jar \
|
||||
$(ANDROID_LINT_CLASSPATH) \
|
||||
$(NULL)
|
||||
|
||||
sdk_processor := \
|
||||
$(JAVA) \
|
||||
-Dcom.android.tools.lint.bindir='$(ANDROID_TOOLS)' \
|
||||
-classpath $(subst $(NULL) ,:,$(strip $(annotation_processor_jar_files))) \
|
||||
org.mozilla.gecko.annotationProcessors.SDKProcessor
|
||||
|
||||
# For the benefit of readers: the following pattern rule says that,
|
||||
# for example, MediaCodec.cpp and MediaCodec.h can be produced from
|
||||
# MediaCodec-classes.txt. This formulation invokes the SDK processor
|
||||
# at most once.
|
||||
|
||||
%.cpp %.h: $(ANDROID_SDK)/android.jar %-classes.txt $(annotation_processor_jar_files)
|
||||
$(sdk_processor) $(ANDROID_SDK)/android.jar $(srcdir)/$*-classes.txt $(CURDIR) $* 16
|
|
@ -23,9 +23,6 @@ SOURCES += ['!%s.cpp' % stem for stem in generated]
|
|||
|
||||
EXPORTS += ['!%s.h' % stem for stem in generated]
|
||||
|
||||
# We'd like to add these to a future GENERATED_EXPORTS list, but for now we mark
|
||||
# them as generated here and manually install them in Makefile.in.
|
||||
GENERATED_FILES += [stem + '.h' for stem in generated]
|
||||
|
||||
# There is an unfortunate race condition when using generated SOURCES and
|
||||
# pattern rules (see Makefile.in) that manifests itself as a VPATH resolution
|
||||
|
@ -35,7 +32,19 @@ GENERATED_FILES += [stem + '.h' for stem in generated]
|
|||
# to be built at export time, which is before MediaCodec.o needs them; and by
|
||||
# the time MediaCodec.o is built, the source is in place and the VPATH
|
||||
# resolution works as expected.
|
||||
GENERATED_FILES += [f[1:] for f in SOURCES]
|
||||
GENERATED_FILES += ['%s.h' % stem for stem in generated]
|
||||
|
||||
# The recursive make backend treats the first output specially: it's passed as
|
||||
# an open FileAvoidWrite to the invoked script. That doesn't work well with
|
||||
# the Gradle task that generates all of the outputs, so we add a dummy first
|
||||
# output.
|
||||
t = tuple(['sdk_bindings'] +
|
||||
['%s.cpp' % stem for stem in generated] +
|
||||
['%s.h' % stem for stem in generated])
|
||||
|
||||
GENERATED_FILES += [t]
|
||||
GENERATED_FILES[t].script = '/mobile/android/gradle.py:generate_sdk_bindings'
|
||||
GENERATED_FILES[t].inputs += ['%s-classes.txt' % stem for stem in generated]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче