Bug 1448428 - Part 1a: Split generated JNI wrappers into multiple files. r=snorp,geckoview-reviewers

This handles the build system bits.

The subsequent patch will restore the "unified"
GeneratedJNI{Natives,Wrappers}.h header files, and will be folded into
this one before landing.

What will still remain is to update the consumers of the .h files (all
the current #include lines) to use the fine-grained imports.  At that
time the "unified" header files can be removed entirely.

Differential Revision: https://phabricator.services.mozilla.com/D58572
This commit is contained in:
Nick Alexander 2020-05-13 17:46:46 +00:00
parent ef3ac906a2
commit fe6281cdc0
3 changed files with 167 additions and 75 deletions

View File

@ -29,10 +29,6 @@ public class AnnotationProcessor {
"// will cause your build to fail.\n" +
"\n";
private static final StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT);
private static final StringBuilder implementationFile = new StringBuilder(GENERATED_COMMENT);
private static final StringBuilder nativesFile = new StringBuilder(GENERATED_COMMENT);
public static void main(String[] args) {
// We expect a list of jars on the commandline. If missing, whinge about it.
if (args.length < 2) {
@ -41,9 +37,6 @@ public class AnnotationProcessor {
}
final String OUTPUT_PREFIX = args[0];
final String SOURCE_FILE = OUTPUT_PREFIX + "JNIWrappers.cpp";
final String HEADER_FILE = OUTPUT_PREFIX + "JNIWrappers.h";
final String NATIVES_FILE = OUTPUT_PREFIX + "JNINatives.h";
System.out.println("Processing annotations...");
@ -55,83 +48,96 @@ public class AnnotationProcessor {
// Start the clock!
long s = System.currentTimeMillis();
int ret = 0;
// Get an iterator over the classes in the jar files given...
Iterator<ClassWithOptions> jarClassIterator = IterableJarLoadingURLClassLoader.getIteratorOverJars(jars);
headerFile.append(
"#ifndef " + getHeaderGuardName(HEADER_FILE) + "\n" +
"#define " + getHeaderGuardName(HEADER_FILE) + "\n" +
"\n" +
"#ifndef MOZ_PREPROCESSOR\n" +
"#include \"mozilla/jni/Refs.h\"\n" +
"#endif\n" +
"\n" +
"namespace mozilla {\n" +
"namespace java {\n" +
"\n");
implementationFile.append(
"#ifndef MOZ_PREPROCESSOR\n" +
"#include \"" + HEADER_FILE + "\"\n" +
"#include \"mozilla/jni/Accessors.h\"\n" +
"#endif\n" +
"\n" +
"namespace mozilla {\n" +
"namespace java {\n" +
"\n");
nativesFile.append(
"#ifndef " + getHeaderGuardName(NATIVES_FILE) + "\n" +
"#define " + getHeaderGuardName(NATIVES_FILE) + "\n" +
"\n" +
"#ifndef MOZ_PREPROCESSOR\n" +
"#include \"" + HEADER_FILE + "\"\n" +
"#include \"mozilla/jni/Natives.h\"\n" +
"#endif\n" +
"\n" +
"namespace mozilla {\n" +
"namespace java {\n" +
"\n");
while (jarClassIterator.hasNext()) {
generateClass(jarClassIterator.next());
final ClassWithOptions annotatedClass = jarClassIterator.next();
if (!annotatedClass.hasGenerated()) {
continue;
}
final String sourceFileName = OUTPUT_PREFIX + annotatedClass.generatedName + "JNIWrappers.cpp";
final String headerFileName = OUTPUT_PREFIX + annotatedClass.generatedName + "JNIWrappers.h";
final String nativesFileName = OUTPUT_PREFIX + annotatedClass.generatedName + "JNINatives.h";
final StringBuilder headerFile = new StringBuilder(GENERATED_COMMENT);
final StringBuilder implementationFile = new StringBuilder(GENERATED_COMMENT);
final StringBuilder nativesFile = new StringBuilder(GENERATED_COMMENT);
headerFile.append(
"#ifndef " + getHeaderGuardName(headerFileName) + "\n" +
"#define " + getHeaderGuardName(headerFileName) + "\n" +
"\n" +
"#ifndef MOZ_PREPROCESSOR\n" +
"#include \"mozilla/jni/Refs.h\"\n" +
"#endif\n" +
"\n" +
"namespace mozilla {\n" +
"namespace java {\n" +
"\n");
implementationFile.append(
"#ifndef MOZ_PREPROCESSOR\n" +
"#include \"" + headerFileName + "\"\n" +
"#include \"mozilla/jni/Accessors.h\"\n" +
"#endif\n" +
"\n" +
"namespace mozilla {\n" +
"namespace java {\n" +
"\n");
nativesFile.append(
"#ifndef " + getHeaderGuardName(nativesFileName) + "\n" +
"#define " + getHeaderGuardName(nativesFileName) + "\n" +
"\n" +
"#ifndef MOZ_PREPROCESSOR\n" +
"#include \"" + headerFileName + "\"\n" +
"#include \"mozilla/jni/Natives.h\"\n" +
"#endif\n" +
"\n" +
"namespace mozilla {\n" +
"namespace java {\n" +
"\n");
generateClass(annotatedClass, headerFile, implementationFile, nativesFile);
implementationFile.append(
"} /* java */\n" +
"} /* mozilla */\n");
headerFile.append(
"} /* java */\n" +
"} /* mozilla */\n" +
"#endif // " + getHeaderGuardName(headerFileName) + "\n");
nativesFile.append(
"} /* java */\n" +
"} /* mozilla */\n" +
"#endif // " + getHeaderGuardName(nativesFileName) + "\n");
ret |= writeOutputFile(sourceFileName, implementationFile);
ret |= writeOutputFile(headerFileName, headerFile);
ret |= writeOutputFile(nativesFileName, nativesFile);
}
implementationFile.append(
"} /* java */\n" +
"} /* mozilla */\n");
headerFile.append(
"} /* java */\n" +
"} /* mozilla */\n" +
"#endif // " + getHeaderGuardName(HEADER_FILE) + "\n");
nativesFile.append(
"} /* java */\n" +
"} /* mozilla */\n" +
"#endif // " + getHeaderGuardName(NATIVES_FILE) + "\n");
int ret = 0;
ret |= writeOutputFile(SOURCE_FILE, implementationFile);
ret |= writeOutputFile(HEADER_FILE, headerFile);
ret |= writeOutputFile(NATIVES_FILE, nativesFile);
long e = System.currentTimeMillis();
System.out.println("Annotation processing complete in " + (e - s) + "ms");
System.exit(ret);
}
private static void generateClass(final ClassWithOptions annotatedClass) {
private static void generateClass(final ClassWithOptions annotatedClass,
final StringBuilder headerFile,
final StringBuilder implementationFile,
final StringBuilder nativesFile) {
// Get an iterator over the appropriately generated methods of this class
final GeneratableElementIterator methodIterator
= new GeneratableElementIterator(annotatedClass);
final ClassWithOptions[] innerClasses = methodIterator.getInnerClasses();
if (!methodIterator.hasNext() && innerClasses.length == 0) {
return;
}
final CodeGenerator generatorInstance = new CodeGenerator(annotatedClass);
generatorInstance.generateClasses(innerClasses);
@ -159,7 +165,7 @@ public class AnnotationProcessor {
nativesFile.append(generatorInstance.getNativesFileContents());
for (ClassWithOptions innerClass : innerClasses) {
generateClass(innerClass);
generateClass(innerClass, headerFile, implementationFile, nativesFile);
}
}

View File

@ -4,6 +4,8 @@
package org.mozilla.gecko.annotationProcessors.classloader;
import org.mozilla.gecko.annotationProcessors.utils.GeneratableElementIterator;
public class ClassWithOptions {
public final Class<?> wrappedClass;
public final String generatedName;
@ -14,4 +16,22 @@ public class ClassWithOptions {
generatedName = name;
this.ifdef = ifdef;
}
public boolean hasGenerated() {
final GeneratableElementIterator methodIterator
= new GeneratableElementIterator(this);
if (methodIterator.hasNext()) {
return true;
}
final ClassWithOptions[] innerClasses = methodIterator.getInnerClasses();
for (ClassWithOptions innerClass : innerClasses) {
if (innerClass.hasGenerated()) {
return true;
}
}
return false;
}
}

View File

@ -26,11 +26,72 @@ EXPORTS += [
'AndroidBridge.h',
]
EXPORTS += [
'!GeneratedJNINatives.h',
'!GeneratedJNIWrappers.h',
classes_with_WrapForJNI = [
'AndroidGamepadManager',
'Base64Utils',
'Clipboard',
'CodecProxy',
'EventCallback',
'EventDispatcher',
'GeckoAppShell',
'GeckoAudioInfo',
'GeckoBatteryManager',
'GeckoBundle',
'GeckoEditableChild',
'GeckoHLSDemuxerWrapper',
'GeckoHLSResourceWrapper',
'GeckoHLSSample',
'GeckoInputStream',
'GeckoJavaSampler',
'GeckoNetworkManager',
'GeckoProcessManager',
'GeckoResult',
'GeckoRuntime',
'GeckoScreenOrientation',
'GeckoServiceChildProcess',
'GeckoSession',
'GeckoSurface',
'GeckoSurfaceTexture',
'GeckoSystemStateListener',
'GeckoThread',
'GeckoVRManager',
'GeckoVideoInfo',
'GeckoWebExecutor',
'HardwareCodecCapabilityUtils',
'ImageDecoder',
'MediaDrmProxy',
'PanZoomController',
'PrefsHelper',
'RuntimeTelemetry',
'Sample',
'SampleBuffer',
'ScreenManagerHelper',
'SessionAccessibility',
'SessionKeyInfo',
'SessionTextInput',
'SpeechSynthesisService',
'StackScroller',
'SurfaceAllocator',
'SurfaceTextureListener',
'TelemetryUtils',
'VsyncSource',
'WebAuthnTokenManager',
'WebMessage',
'WebNotification',
'WebNotificationDelegate',
'WebRequest',
'WebRequestError',
'WebResponse',
'XPCOMEventTarget',
]
headers_from_WrapForJNI = sorted(
['Generated{}JNINatives.h'.format(c) for c in classes_with_WrapForJNI] +
['Generated{}JNIWrappers.h'.format(c) for c in classes_with_WrapForJNI])
sources_from_WrapForJNI = sorted(
'Generated{}JNIWrappers.cpp'.format(c) for c in classes_with_WrapForJNI)
EXPORTS.mozilla.widget += [
'AndroidCompositorWidget.h',
'AndroidUiThread.h',
@ -38,8 +99,11 @@ EXPORTS.mozilla.widget += [
'nsWindow.h',
]
EXPORTS += ['!{}'.format(c) for c in headers_from_WrapForJNI]
SOURCES += ['!{}'.format(c) for c in sources_from_WrapForJNI]
SOURCES += [
'!GeneratedJNIWrappers.cpp',
'MediaKeysEventSourceFactory.cpp',
]
@ -79,9 +143,11 @@ include('/ipc/chromium/chromium-config.mozbuild')
# 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.
GeneratedFile(
'generated_jni_wrappers', 'GeneratedJNINatives.h', 'GeneratedJNIWrappers.h',
'GeneratedJNIWrappers.cpp', script='/mobile/android/gradle.py',
t = tuple(['generated_jni_wrappers'] + headers_from_WrapForJNI + sources_from_WrapForJNI)
GeneratedFile(*t,
script='/mobile/android/gradle.py',
entry_point='generate_generated_jni_wrappers')
FINAL_LIBRARY = 'xul'