mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 1378410 - 1. Support BuildFlag annotation for generated bindings; r=snorp
Add a BuildFlag annotation, which when specified for classes, will wrap generated code in `#ifdef` or `#ifndef` blocks. This functionality is used for conditionally excluding generated code when NIghtly becomes Beta, without the need to regenerate bindings. MozReview-Commit-ID: L2NFM8CHKqF --HG-- extra : rebase_source : 6ebc82d11fd1aa4aeb57a46262e678480d23de83
This commit is contained in:
parent
b0873633b7
commit
f0ca31be3a
@ -29,7 +29,7 @@ public class AnnotationProcessor {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// We expect a list of jars on the commandline. If missing, whinge about it.
|
||||
if (args.length <= 2) {
|
||||
if (args.length < 2) {
|
||||
System.err.println("Usage: java AnnotationProcessor outprefix jarfiles ...");
|
||||
System.exit(1);
|
||||
}
|
||||
@ -56,15 +56,19 @@ public class AnnotationProcessor {
|
||||
"#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" +
|
||||
@ -74,8 +78,10 @@ public class AnnotationProcessor {
|
||||
"#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" +
|
||||
|
@ -27,6 +27,7 @@ public class CodeGenerator {
|
||||
|
||||
private final Class<?> cls;
|
||||
private final String clsName;
|
||||
private final ClassWithOptions options;
|
||||
private AnnotationInfo.CallingThread callingThread = null;
|
||||
private int numNativesInits;
|
||||
|
||||
@ -35,9 +36,11 @@ public class CodeGenerator {
|
||||
public CodeGenerator(ClassWithOptions annotatedClass) {
|
||||
this.cls = annotatedClass.wrappedClass;
|
||||
this.clsName = annotatedClass.generatedName;
|
||||
this.options = annotatedClass;
|
||||
|
||||
final String unqualifiedName = Utils.getUnqualifiedName(clsName);
|
||||
header.append(
|
||||
Utils.getIfdefHeader(annotatedClass.ifdef) +
|
||||
"class " + clsName + " : public mozilla::jni::ObjectBase<" +
|
||||
unqualifiedName + ">\n" +
|
||||
"{\n" +
|
||||
@ -49,11 +52,13 @@ public class CodeGenerator {
|
||||
"\n");
|
||||
|
||||
cpp.append(
|
||||
Utils.getIfdefHeader(annotatedClass.ifdef) +
|
||||
"const char " + clsName + "::name[] =\n" +
|
||||
" \"" + cls.getName().replace('.', '/') + "\";\n" +
|
||||
"\n");
|
||||
|
||||
natives.append(
|
||||
Utils.getIfdefHeader(annotatedClass.ifdef) +
|
||||
"template<class Impl>\n" +
|
||||
"class " + clsName + "::Natives : " +
|
||||
"public mozilla::jni::NativeImpl<" + unqualifiedName + ", Impl>\n" +
|
||||
@ -556,6 +561,8 @@ public class CodeGenerator {
|
||||
* @return The bytes to be written to the wrappers file.
|
||||
*/
|
||||
public String getWrapperFileContents() {
|
||||
cpp.append(
|
||||
Utils.getIfdefFooter(options.ifdef));
|
||||
return cpp.toString();
|
||||
}
|
||||
|
||||
@ -580,7 +587,8 @@ public class CodeGenerator {
|
||||
}
|
||||
header.append(
|
||||
"};\n" +
|
||||
"\n");
|
||||
"\n" +
|
||||
Utils.getIfdefFooter(options.ifdef));
|
||||
return header.toString();
|
||||
}
|
||||
|
||||
@ -600,7 +608,8 @@ public class CodeGenerator {
|
||||
"template<class Impl>\n" +
|
||||
"const JNINativeMethod " + clsName + "::Natives<Impl>::methods[] = {" + nativesInits + '\n' +
|
||||
"};\n" +
|
||||
"\n");
|
||||
"\n" +
|
||||
Utils.getIfdefFooter(options.ifdef));
|
||||
return natives.toString();
|
||||
}
|
||||
}
|
||||
|
@ -412,7 +412,8 @@ public class SDKProcessor {
|
||||
StringBuilder headerFile) throws ParseException {
|
||||
String generatedName = clazz.getSimpleName();
|
||||
|
||||
CodeGenerator generator = new CodeGenerator(new ClassWithOptions(clazz, generatedName));
|
||||
CodeGenerator generator = new CodeGenerator(
|
||||
new ClassWithOptions(clazz, generatedName, /* ifdef */ ""));
|
||||
|
||||
generateMembers(generator, clsInfo,
|
||||
sortAndFilterMembers(clazz, clazz.getConstructors()));
|
||||
|
@ -7,9 +7,11 @@ package org.mozilla.gecko.annotationProcessors.classloader;
|
||||
public class ClassWithOptions {
|
||||
public final Class<?> wrappedClass;
|
||||
public final String generatedName;
|
||||
public final String ifdef;
|
||||
|
||||
public ClassWithOptions(Class<?> someClass, String name) {
|
||||
public ClassWithOptions(Class<?> someClass, String name, String ifdef) {
|
||||
wrappedClass = someClass;
|
||||
generatedName = name;
|
||||
this.ifdef = ifdef;
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
package org.mozilla.gecko.annotationProcessors.classloader;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
@ -67,7 +69,27 @@ public class JarClassIterator implements Iterator<ClassWithOptions> {
|
||||
return fillLookAheadIfPossible();
|
||||
}
|
||||
|
||||
lookAhead = new ClassWithOptions(ret, ret.getSimpleName());
|
||||
String ifdef = "";
|
||||
for (final Annotation annotation : ret.getDeclaredAnnotations()) {
|
||||
Class<? extends Annotation> annotationType = annotation.annotationType();
|
||||
if (!annotationType.getName().equals(
|
||||
"org.mozilla.gecko.annotation.BuildFlag")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
final Method valueMethod = annotationType.getDeclaredMethod("value");
|
||||
valueMethod.setAccessible(true);
|
||||
ifdef = (String) valueMethod.invoke(annotation);
|
||||
break;
|
||||
} catch (final Exception e) {
|
||||
System.err.println("Unable to read BuildFlag annotation.");
|
||||
e.printStackTrace(System.err);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
lookAhead = new ClassWithOptions(ret, ret.getSimpleName(), ifdef);
|
||||
return true;
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("Unable to enumerate class: " + className + ". Corrupted jar file?");
|
||||
|
@ -77,8 +77,8 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < candidates.length; ++i) {
|
||||
final GeneratableElementIterator testIterator
|
||||
= new GeneratableElementIterator(new ClassWithOptions(candidates[i], null));
|
||||
final GeneratableElementIterator testIterator = new GeneratableElementIterator(
|
||||
new ClassWithOptions(candidates[i], null, /* ifdef */ ""));
|
||||
if (testIterator.hasNext()
|
||||
|| testIterator.getFilteredInnerClasses() != null) {
|
||||
count++;
|
||||
@ -108,7 +108,9 @@ public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
|
||||
for (Class<?> candidate : candidates) {
|
||||
if (candidate != null) {
|
||||
ret[count++] = new ClassWithOptions(
|
||||
candidate, mClass.generatedName + "::" + candidate.getSimpleName());
|
||||
candidate,
|
||||
mClass.generatedName + "::" + candidate.getSimpleName(),
|
||||
/* ifdef */ "");
|
||||
}
|
||||
}
|
||||
assert ret.length == count;
|
||||
|
@ -327,4 +327,20 @@ public class Utils {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getIfdefHeader(String ifdef) {
|
||||
if (ifdef.isEmpty()) {
|
||||
return "";
|
||||
} else if (ifdef.startsWith("!")) {
|
||||
return "#ifndef " + ifdef.substring(1) + "\n";
|
||||
}
|
||||
return "#ifdef " + ifdef + "\n";
|
||||
}
|
||||
|
||||
public static String getIfdefFooter(String ifdef) {
|
||||
if (ifdef.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
return "#endif // " + ifdef + "\n";
|
||||
}
|
||||
}
|
||||
|
@ -148,6 +148,7 @@ thirdparty_source_dir = TOPSRCDIR + '/mobile/android/thirdparty/'
|
||||
|
||||
constants_jar = add_java_jar('constants')
|
||||
constants_jar.sources += [geckoview_source_dir + 'java/org/mozilla/gecko/' + x for x in [
|
||||
'annotation/BuildFlag.java',
|
||||
'annotation/JNITarget.java',
|
||||
'annotation/ReflectionTarget.java',
|
||||
'annotation/RobocopTarget.java',
|
||||
|
@ -0,0 +1,26 @@
|
||||
/* 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/. */
|
||||
|
||||
package org.mozilla.gecko.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* This annotation is used to tag classes that are conditionally built behind
|
||||
* build flags. Any generated JNI bindings will incorporate the specified build
|
||||
* flags.
|
||||
*/
|
||||
@Target({ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface BuildFlag {
|
||||
/**
|
||||
* Preprocessor macro for conditionally building the generated bindings.
|
||||
* "MOZ_FOO" wraps generated bindings in "#ifdef MOZ_FOO / #endif"
|
||||
* "!MOZ_FOO" wraps generated bindings in "#ifndef MOZ_FOO / #endif"
|
||||
*/
|
||||
String value() default "";
|
||||
}
|
Loading…
Reference in New Issue
Block a user