diff options
author | Sven Gothel <[email protected]> | 2014-05-11 03:03:36 +0200 |
---|---|---|
committer | Sven Gothel <[email protected]> | 2014-05-11 03:03:36 +0200 |
commit | 1e53a38eb06aa8ff50660fdf7bd8570b27f27c56 (patch) | |
tree | f061dfb77af5b4c1f27da78b4dbd1881b400abc3 /src/java/com/jogamp | |
parent | 598da96b3d2ffc3e0915f73749cbafa5fa5cea90 (diff) |
Bug 923: Remove dependency of CStruct annotation processor _generation_ and generated_class_user due to Java8 issues.
Java8's annotation processor as embedded within javac does not allow
referencing not-yet existing generated classes in a class source code
which will produce these generated classes via the annotation process.
Example:
+++
import com.jogamp.gluegen.structgen.CStruct;
public class Lala {
@CStruct(name="RenderingConfig", header="TestStruct01.h")
public RenderingConfig config;
}
+++
Above example illustrates that the type 'RenderingConfig'
does not exist at time of processing the annotation.
The type will be created via the annotation process itself.
Even though we pass '-proc:only', i.e. skip java compilation,
Java8's annotation processing via javac fails in such case.
We see this as a bug within javac's annotation processing itself!
+++
This workaround splits the annotation process and using the class as
generated by the former.
To allow this to work, CStruct receives a new field 'jname'
allowing to enforce the java-name of the structure
using a dummy field type like boolean.
@CStruct(name="RenderingConfig", jname="RenderingConfig", header="TestStruct01.h")
public boolean dummy;
Further more CStruct can be annotated on the package, i.e. 'package-info.java',
avoiding the dependency problem altogether.
To support multiple header files and types,
'CStructs' has been introduced using an array of 'CStruct'.
@CStructs({@CStruct(name="RenderingConfig", header="TestStruct01.h"), @CStruct(name="Pixel", header="TestStruct02.h")})
package com.jogamp.gluegen.test.junit.structgen;
Tests:
- Build w/ Java7 and Java8
- Validated 'major version 50' (Java 6) class files (OK)
Diffstat (limited to 'src/java/com/jogamp')
4 files changed, 281 insertions, 177 deletions
diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java index ec8757c..3f4fa9e 100644 --- a/src/java/com/jogamp/gluegen/JavaEmitter.java +++ b/src/java/com/jogamp/gluegen/JavaEmitter.java @@ -836,69 +836,74 @@ public class JavaEmitter implements GlueEmitter { } } - String structClassPkg = cfg.packageForStruct(name); - PrintWriter writer = null; - PrintWriter newWriter = null; + final String structClassPkg = cfg.packageForStruct(name); + final PrintWriter javaWriter; + final PrintWriter jniWriter; try { - writer = openFile( - cfg.javaOutputDir() + File.separator + - CodeGenUtils.packageAsPath(structClassPkg) + - File.separator + containingTypeName + ".java", containingTypeName); - CodeGenUtils.emitAutogeneratedWarning(writer, this); - if (needsNativeCode) { - String nRoot = cfg.nativeOutputDir(); - if (cfg.nativeOutputUsesJavaHierarchy()) { - nRoot += File.separator + CodeGenUtils.packageAsPath(cfg.packageName()); + javaWriter = openFile(cfg.javaOutputDir() + File.separator + + CodeGenUtils.packageAsPath(structClassPkg) + + File.separator + containingTypeName + ".java", containingTypeName); + if( null == javaWriter ) { + // suppress output if openFile deliberately returns null. + return; + } + CodeGenUtils.emitAutogeneratedWarning(javaWriter, this); + if (needsNativeCode) { + String nRoot = cfg.nativeOutputDir(); + if (cfg.nativeOutputUsesJavaHierarchy()) { + nRoot += File.separator + CodeGenUtils.packageAsPath(cfg.packageName()); + } + jniWriter = openFile(nRoot + File.separator + containingTypeName + "_JNI.c", containingTypeName); + CodeGenUtils.emitAutogeneratedWarning(jniWriter, this); + emitCHeader(jniWriter, containingTypeName); + } else { + jniWriter = null; } - newWriter = openFile(nRoot + File.separator + containingTypeName + "_JNI.c", containingTypeName); - CodeGenUtils.emitAutogeneratedWarning(newWriter, this); - emitCHeader(newWriter, containingTypeName); - } } catch(Exception e) { - throw new RuntimeException("Unable to open files for emission of struct class", e); + throw new RuntimeException("Unable to open files for emission of struct class", e); } - writer.println(); - writer.println("package " + structClassPkg + ";"); - writer.println(); - writer.println("import java.nio.*;"); - writer.println(); + javaWriter.println(); + javaWriter.println("package " + structClassPkg + ";"); + javaWriter.println(); + javaWriter.println("import java.nio.*;"); + javaWriter.println(); - writer.println("import " + cfg.gluegenRuntimePackage() + ".*;"); - writer.println("import " + DynamicLookupHelper.class.getPackage().getName() + ".*;"); - writer.println("import " + Buffers.class.getPackage().getName() + ".*;"); - writer.println("import " + MachineDescriptionRuntime.class.getName() + ";"); - writer.println(); + javaWriter.println("import " + cfg.gluegenRuntimePackage() + ".*;"); + javaWriter.println("import " + DynamicLookupHelper.class.getPackage().getName() + ".*;"); + javaWriter.println("import " + Buffers.class.getPackage().getName() + ".*;"); + javaWriter.println("import " + MachineDescriptionRuntime.class.getName() + ";"); + javaWriter.println(); List<String> imports = cfg.imports(); for (String str : imports) { - writer.print("import "); - writer.print(str); - writer.println(";"); + javaWriter.print("import "); + javaWriter.print(str); + javaWriter.println(";"); } - writer.println(); + javaWriter.println(); List<String> javadoc = cfg.javadocForClass(containingTypeName); for (String doc : javadoc) { - writer.println(doc); + javaWriter.println(doc); } - writer.print("public class " + containingTypeName + " "); + javaWriter.print("public class " + containingTypeName + " "); boolean firstIteration = true; List<String> userSpecifiedInterfaces = cfg.implementedInterfaces(containingTypeName); for (String userInterface : userSpecifiedInterfaces) { if (firstIteration) { - writer.print("implements "); + javaWriter.print("implements "); } firstIteration = false; - writer.print(userInterface); - writer.print(" "); - } - writer.println("{"); - writer.println(); - writer.println(" StructAccessor accessor;"); - writer.println(); - writer.println(" private static final int mdIdx = MachineDescriptionRuntime.getStatic().ordinal();"); - writer.println(); + javaWriter.print(userInterface); + javaWriter.print(" "); + } + javaWriter.println("{"); + javaWriter.println(); + javaWriter.println(" StructAccessor accessor;"); + javaWriter.println(); + javaWriter.println(" private static final int mdIdx = MachineDescriptionRuntime.getStatic().ordinal();"); + javaWriter.println(); // generate all offset and size arrays - generateOffsetAndSizeArrays(writer, containingTypeName, structType, null); /* w/o offset */ + generateOffsetAndSizeArrays(javaWriter, containingTypeName, structType, null); /* w/o offset */ for (int i = 0; i < structType.getNumFields(); i++) { final Field field = structType.getField(i); final Type fieldType = field.getType(); @@ -917,14 +922,14 @@ public class JavaEmitter implements GlueEmitter { field + "\" in type \"" + name + "\")"); } - generateOffsetAndSizeArrays(writer, fieldName, fieldType, field); + generateOffsetAndSizeArrays(javaWriter, fieldName, fieldType, field); } else if (fieldType.isArray()) { Type baseElementType = field.getType().asArray().getBaseElementType(); if(!baseElementType.isPrimitive()) break; - generateOffsetAndSizeArrays(writer, fieldName, null, field); /* w/o size */ + generateOffsetAndSizeArrays(javaWriter, fieldName, null, field); /* w/o size */ } else { JavaType externalJavaType = null; try { @@ -936,7 +941,7 @@ public class JavaEmitter implements GlueEmitter { } if (externalJavaType.isPrimitive()) { // Primitive type - generateOffsetAndSizeArrays(writer, fieldName, null, field); /* w/o size */ + generateOffsetAndSizeArrays(javaWriter, fieldName, null, field); /* w/o size */ } else { // FIXME LOG.log(WARNING, "Complicated fields (field \"{0}\" of type \"{1}\") not implemented yet", new Object[]{field, name}); @@ -946,27 +951,27 @@ public class JavaEmitter implements GlueEmitter { } } } - writer.println(); - - writer.println(" public static int size() {"); - writer.println(" return "+containingTypeName+"_size[mdIdx];"); - writer.println(" }"); - writer.println(); - writer.println(" public static " + containingTypeName + " create() {"); - writer.println(" return create(Buffers.newDirectByteBuffer(size()));"); - writer.println(" }"); - writer.println(); - writer.println(" public static " + containingTypeName + " create(java.nio.ByteBuffer buf) {"); - writer.println(" return new " + containingTypeName + "(buf);"); - writer.println(" }"); - writer.println(); - writer.println(" " + containingTypeName + "(java.nio.ByteBuffer buf) {"); - writer.println(" accessor = new StructAccessor(buf);"); - writer.println(" }"); - writer.println(); - writer.println(" public java.nio.ByteBuffer getBuffer() {"); - writer.println(" return accessor.getBuffer();"); - writer.println(" }"); + javaWriter.println(); + + javaWriter.println(" public static int size() {"); + javaWriter.println(" return "+containingTypeName+"_size[mdIdx];"); + javaWriter.println(" }"); + javaWriter.println(); + javaWriter.println(" public static " + containingTypeName + " create() {"); + javaWriter.println(" return create(Buffers.newDirectByteBuffer(size()));"); + javaWriter.println(" }"); + javaWriter.println(); + javaWriter.println(" public static " + containingTypeName + " create(java.nio.ByteBuffer buf) {"); + javaWriter.println(" return new " + containingTypeName + "(buf);"); + javaWriter.println(" }"); + javaWriter.println(); + javaWriter.println(" " + containingTypeName + "(java.nio.ByteBuffer buf) {"); + javaWriter.println(" accessor = new StructAccessor(buf);"); + javaWriter.println(" }"); + javaWriter.println(); + javaWriter.println(" public java.nio.ByteBuffer getBuffer() {"); + javaWriter.println(" return accessor.getBuffer();"); + javaWriter.println(" }"); for (int i = 0; i < structType.getNumFields(); i++) { final Field field = structType.getField(i); @@ -983,12 +988,12 @@ public class JavaEmitter implements GlueEmitter { FunctionSymbol funcSym = new FunctionSymbol(fieldName, funcType); MethodBinding binding = bindFunction(funcSym, containingType, containingCType, machDescJava); binding.findThisPointer(); // FIXME: need to provide option to disable this on per-function basis - writer.println(); + javaWriter.println(); // Emit public Java entry point for calling this function pointer JavaMethodBindingEmitter emitter = new JavaMethodBindingEmitter(binding, - writer, + javaWriter, cfg.runtimeExceptionType(), cfg.unsupportedExceptionType(), true, @@ -1008,7 +1013,7 @@ public class JavaEmitter implements GlueEmitter { // Emit private native Java entry point for calling this function pointer emitter = new JavaMethodBindingEmitter(binding, - writer, + javaWriter, cfg.runtimeExceptionType(), cfg.unsupportedExceptionType(), false, @@ -1029,7 +1034,7 @@ public class JavaEmitter implements GlueEmitter { // Emit (private) C entry point for calling this function pointer CMethodBindingEmitter cEmitter = new CMethodBindingEmitter(binding, - newWriter, + jniWriter, structClassPkg, containingTypeName, true, // FIXME: this is optional at this point @@ -1052,12 +1057,12 @@ public class JavaEmitter implements GlueEmitter { field + "\" in type \"" + name + "\")"); } - writer.println(); - generateGetterSignature(writer, false, fieldType.getName(), capitalizeString(fieldName)); - writer.println(" {"); - writer.println(" return " + fieldType.getName() + ".create( accessor.slice( " + + javaWriter.println(); + generateGetterSignature(javaWriter, false, fieldType.getName(), capitalizeString(fieldName)); + javaWriter.println(" {"); + javaWriter.println(" return " + fieldType.getName() + ".create( accessor.slice( " + fieldName+"_offset[mdIdx], "+fieldName+"_size[mdIdx] ) );"); - writer.println(" }"); + javaWriter.println(" }"); } else if (fieldType.isArray()) { @@ -1070,18 +1075,18 @@ public class JavaEmitter implements GlueEmitter { String capitalized = capitalizeString(fieldName); // Setter - writer.println(); - generateSetterSignature(writer, false, containingTypeName, capitalized, paramType+"[]"); - writer.println(" {"); - writer.print (" accessor.set" + capitalizeString(paramType) + "sAt(" + fieldName+"_offset[mdIdx], val);"); - writer.println(" return this;"); - writer.println(" }"); - writer.println(); + javaWriter.println(); + generateSetterSignature(javaWriter, false, containingTypeName, capitalized, paramType+"[]"); + javaWriter.println(" {"); + javaWriter.print (" accessor.set" + capitalizeString(paramType) + "sAt(" + fieldName+"_offset[mdIdx], val);"); + javaWriter.println(" return this;"); + javaWriter.println(" }"); + javaWriter.println(); // Getter - generateGetterSignature(writer, false, paramType+"[]", capitalized); - writer.println(" {"); - writer.print (" return accessor.get" + capitalizeString(paramType) + "sAt(" + fieldName+"_offset[mdIdx], new " +paramType+"["+fieldType.asArray().getLength()+"]);"); - writer.println(" }"); + generateGetterSignature(javaWriter, false, paramType+"[]", capitalized); + javaWriter.println(" {"); + javaWriter.print (" return accessor.get" + capitalizeString(paramType) + "sAt(" + fieldName+"_offset[mdIdx], new " +paramType+"["+fieldType.asArray().getLength()+"]);"); + javaWriter.println(" }"); } else { JavaType javaType = null; @@ -1111,40 +1116,40 @@ public class JavaEmitter implements GlueEmitter { ", sizeDenominator "+sizeDenominator); } - writer.println(); + javaWriter.println(); // Setter - generateSetterSignature(writer, false, containingTypeName, capFieldName, javaTypeName); - writer.println(" {"); + generateSetterSignature(javaWriter, false, containingTypeName, capFieldName, javaTypeName); + javaWriter.println(" {"); if( fieldTypeNativeSizeFixed ) { - writer.println(" accessor.set" + capJavaTypeName + "At(" + fieldName+"_offset[mdIdx], val);"); + javaWriter.println(" accessor.set" + capJavaTypeName + "At(" + fieldName+"_offset[mdIdx], val);"); } else { - writer.println(" accessor.set" + capJavaTypeName + "At(" + fieldName+"_offset[mdIdx], val, MachineDescriptionRuntime.getStatic().md."+sizeDenominator+"SizeInBytes());"); + javaWriter.println(" accessor.set" + capJavaTypeName + "At(" + fieldName+"_offset[mdIdx], val, MachineDescriptionRuntime.getStatic().md."+sizeDenominator+"SizeInBytes());"); } - writer.println(" return this;"); - writer.println(" }"); - writer.println(); + javaWriter.println(" return this;"); + javaWriter.println(" }"); + javaWriter.println(); // Getter - generateGetterSignature(writer, false, javaTypeName, capFieldName); - writer.println(" {"); - writer.print (" return "); + generateGetterSignature(javaWriter, false, javaTypeName, capFieldName); + javaWriter.println(" {"); + javaWriter.print (" return "); if( fieldTypeNativeSizeFixed ) { - writer.println("accessor.get" + capJavaTypeName + "At(" + fieldName+"_offset[mdIdx]);"); + javaWriter.println("accessor.get" + capJavaTypeName + "At(" + fieldName+"_offset[mdIdx]);"); } else { - writer.println("accessor.get" + capJavaTypeName + "At(" + fieldName+"_offset[mdIdx], MachineDescriptionRuntime.getStatic().md."+sizeDenominator+"SizeInBytes());"); + javaWriter.println("accessor.get" + capJavaTypeName + "At(" + fieldName+"_offset[mdIdx], MachineDescriptionRuntime.getStatic().md."+sizeDenominator+"SizeInBytes());"); } - writer.println(" }"); + javaWriter.println(" }"); } } } } - emitCustomJavaCode(writer, containingTypeName); - writer.println("}"); - writer.flush(); - writer.close(); + emitCustomJavaCode(javaWriter, containingTypeName); + javaWriter.println("}"); + javaWriter.flush(); + javaWriter.close(); if (needsNativeCode) { - newWriter.flush(); - newWriter.close(); + jniWriter.flush(); + jniWriter.close(); } } @Override @@ -1415,17 +1420,15 @@ public class JavaEmitter implements GlueEmitter { /** * @param filename the class's full filename to open w/ write access * @param simpleClassName the simple class name, i.e. w/o package name - * @return a {@link PrintWriter} instance to write the class source file + * @return a {@link PrintWriter} instance to write the class source file or <code>null</code> to suppress output! * @throws IOException */ protected PrintWriter openFile(String filename, String simpleClassName) throws IOException { //System.out.println("Trying to open: " + filename); - File file = new File(filename); - String parentDir = file.getParent(); - if (parentDir != null) - { - File pDirFile = new File(parentDir); - pDirFile.mkdirs(); + final File file = new File(filename); + final String parentDir = file.getParent(); + if (parentDir != null) { + new File(parentDir).mkdirs(); } return new PrintWriter(new BufferedWriter(new FileWriter(file))); } diff --git a/src/java/com/jogamp/gluegen/structgen/CStruct.java b/src/java/com/jogamp/gluegen/structgen/CStruct.java index 9d57196..be72cd8 100644 --- a/src/java/com/jogamp/gluegen/structgen/CStruct.java +++ b/src/java/com/jogamp/gluegen/structgen/CStruct.java @@ -33,21 +33,32 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** - * - * @author Michael Bien - * @author Sven Gothel, et.al. + * @author Michael Bien, et al. */ -@Target(value = {ElementType.FIELD, ElementType.LOCAL_VARIABLE}) +@Target(value = {ElementType.TYPE, ElementType.PACKAGE, ElementType.FIELD, ElementType.LOCAL_VARIABLE}) @Retention(value = RetentionPolicy.SOURCE) public @interface CStruct { /** * Relative path to the header file. + * <p> + * Mandatory. + * </p> */ String header(); /** * The name of the struct. + * <p> + * Mandatory for {@link ElementType.TYPE} and {@link ElementType.PACKAGE} annotations + * otherwise optional. + * </p> */ String name() default "_default_"; + + /** + * The optional java name of the struct. + */ + String jname() default "_default_"; + } diff --git a/src/java/com/jogamp/gluegen/structgen/CStructAnnotationProcessor.java b/src/java/com/jogamp/gluegen/structgen/CStructAnnotationProcessor.java index ee761a3..7b24967 100644 --- a/src/java/com/jogamp/gluegen/structgen/CStructAnnotationProcessor.java +++ b/src/java/com/jogamp/gluegen/structgen/CStructAnnotationProcessor.java @@ -30,12 +30,20 @@ package com.jogamp.gluegen.structgen; import com.jogamp.common.util.PropertyAccess; import com.jogamp.gluegen.GlueGen; import com.jogamp.gluegen.JavaEmitter; + +import java.io.BufferedReader; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; +import java.io.Reader; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; + import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.Filer; import javax.annotation.processing.Messager; @@ -76,11 +84,11 @@ import jogamp.common.Debug; * * @author Michael Bien, et al. */ -@SupportedAnnotationTypes(value = {"com.jogamp.gluegen.structgen.CStruct"}) +@SupportedAnnotationTypes(value = {"com.jogamp.gluegen.structgen.CStruct", "com.jogamp.gluegen.structgen.CStructs"}) @SupportedSourceVersion(SourceVersion.RELEASE_6) public class CStructAnnotationProcessor extends AbstractProcessor { private static final String DEFAULT = "_default_"; - private static final boolean DEBUG; + static final boolean DEBUG; static { Debug.initSingleton(); @@ -131,71 +139,96 @@ public class CStructAnnotationProcessor extends AbstractProcessor { public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) { final String user_dir = System.getProperty("user.dir"); - final Set<? extends Element> elements = env.getElementsAnnotatedWith(CStruct.class); - - for (Element element : elements) { - - final String packageName = eltUtils.getPackageOf(element).toString(); + final Set<? extends Element> cStructsElements = env.getElementsAnnotatedWith(CStructs.class); + for (Element structsElement : cStructsElements) { + final String packageName = eltUtils.getPackageOf(structsElement).toString(); + final CStructs cstructs = structsElement.getAnnotation(CStructs.class); + if( null != cstructs ) { + final CStruct[] cstructArray = cstructs.value(); + for(CStruct cstruct : cstructArray) { + processCStruct(cstruct, structsElement, packageName, user_dir); + } + } + } - try { - final CStruct struct = element.getAnnotation(CStruct.class); - final String headerRelPath = struct.header(); - final Element enclElement = element.getEnclosingElement(); + final Set<? extends Element> cStructElements = env.getElementsAnnotatedWith(CStruct.class); + for (Element structElement : cStructElements) { + final String packageName = eltUtils.getPackageOf(structElement).toString(); + final CStruct cstruct = structElement.getAnnotation(CStruct.class); + if( null != cstruct ) { + processCStruct(cstruct, structElement, packageName, user_dir); + } + } + return true; + } - System.err.println("CStruct: "+struct+", package "+packageName+", header "+headerRelPath); - if(DEBUG) { - System.err.println("CStruct.0: user.dir: "+user_dir); - System.err.println("CStruct.0: element: "+element+", .simpleName "+element.getSimpleName()); - System.err.println("CStruct.0: enclElement: "+enclElement+", .simpleName "+enclElement.getSimpleName()+", .package "+eltUtils.getPackageOf(enclElement).toString()); + private void processCStruct(final CStruct struct, final Element element, final String packageName, final String user_dir) { + try { + final String headerRelPath = struct.header(); + final Element enclElement = element.getEnclosingElement(); + final boolean isPackageOrType = null == enclElement; + + System.err.println("CStruct: "+struct+", package "+packageName+", header "+headerRelPath); + if(DEBUG) { + System.err.println("CStruct.0: user.dir: "+user_dir); + System.err.println("CStruct.0: element: "+element+", .simpleName "+element.getSimpleName()); + System.err.print("CStruct.0: isPackageOrType "+isPackageOrType+", enclElement: "+enclElement); + if( !isPackageOrType ) { + System.err.println(", .simpleName "+enclElement.getSimpleName()+", .package "+eltUtils.getPackageOf(enclElement).toString()); + } else { + System.err.println(""); } + } + if( isPackageOrType && struct.name().equals(DEFAULT) ) { + throw new IllegalArgumentException("CStruct annotation on package or type must have name specified: "+struct+" @ "+element); + } - final File headerFile; - { - File f = locateSource(packageName, headerRelPath); + final File headerFile; + { + File f = locateSource(packageName, headerRelPath); + if( null == f ) { + f = locateSource("", headerRelPath); if( null == f ) { - f = locateSource("", headerRelPath); - if( null == f ) { - // bail out - throw new RuntimeException("Could not locate header "+headerRelPath+", package "+packageName); - } + // bail out + throw new RuntimeException("Could not locate header "+headerRelPath+", package "+packageName); } - headerFile = f; } + headerFile = f; + } - final String root; - { - String root0 = headerFile.getAbsolutePath(); - root0 = root0.substring(0, root0.length()-headerFile.getName().length()-1); - root = root0.substring(0, root0.length()-packageName.length()) +".."; - } - System.err.println("CStruct: "+headerFile+", abs: "+headerFile.isAbsolute()+", root "+root); - - generateStructBinding(element, struct, root, packageName, headerFile); - } catch (IOException ex) { - throw new RuntimeException("IOException while processing!", ex); + final String rootOut, headerParent; + { + final String root0 = headerFile.getAbsolutePath(); + headerParent = root0.substring(0, root0.length()-headerFile.getName().length()-1); + rootOut = headerParent.substring(0, headerParent.length()-packageName.length()) + ".."; } + System.err.println("CStruct: "+headerFile+", abs: "+headerFile.isAbsolute()+", headerParent "+headerParent+", rootOut "+rootOut); + + generateStructBinding(element, struct, isPackageOrType, rootOut, packageName, headerFile, headerParent); + } catch (IOException ex) { + throw new RuntimeException("IOException while processing!", ex); } - return true; } - private void generateStructBinding(Element element, CStruct struct, String root, String pakage, File header) throws IOException { + private void generateStructBinding(Element element, CStruct struct, boolean isPackageOrType, String rootOut, String pakage, File header, String headerParent) throws IOException { final String declaredType = element.asType().toString(); - final String structName = struct.name().equals(DEFAULT) ? declaredType : struct.name(); - - if( generatedStructs.contains(structName) ) { - messager.printMessage(Kind.WARNING, "struct "+structName+" already defined elsewhere.", element); + final boolean useStructName = !struct.name().equals(DEFAULT); + final String structName = useStructName ? struct.name() : declaredType; + final boolean useJavaName = !struct.jname().equals(DEFAULT); + + final String finalType = useJavaName ? struct.jname() : ( !isPackageOrType ? declaredType : structName ); + System.err.println("CStruct: Generating struct accessor for struct: "+structName+" -> "+finalType+" [struct.name "+struct.name()+", struct.jname "+struct.jname()+", declaredType "+declaredType+"]"); + if( generatedStructs.contains(finalType) ) { + messager.printMessage(Kind.NOTE, "struct "+structName+" already defined elsewhere, skipping.", element); return; } - System.out.println("generating struct accessor for struct: "+structName); - - generatedStructs.add(structName); final boolean outputDirAbs; { final File outputDirFile = new File(outputPath); outputDirAbs = outputDirFile.isAbsolute(); } - final String outputPath1 = outputDirAbs ? outputPath : root + File.separator + outputPath; + final String outputPath1 = outputDirAbs ? outputPath : rootOut + File.separator + outputPath; final String config = outputPath1 + File.separator + header.getName() + ".cfg"; final File configFile = new File(config); if(DEBUG) { @@ -209,7 +242,8 @@ public class CStructAnnotationProcessor extends AbstractProcessor { writer = new FileWriter(configFile); writer.write("Package "+pakage+"\n"); writer.write("EmitStruct "+structName+"\n"); - if(!struct.name().equals(DEFAULT)) { + if( finalType != structName ) { + // We allow renaming the structType to the element's declaredType (FIELD annotation only) writer.write("RenameJavaType " + struct.name()+" " + declaredType +"\n"); } } finally { @@ -217,16 +251,23 @@ public class CStructAnnotationProcessor extends AbstractProcessor { writer.close(); } } - - // TODO: Handle exceptions .. suppressed by Gluegen.main(..) ? - GlueGen.main( - // "-I"+path+"/build/", - "-O" + outputPath1, - "-E" + AnnotationProcessorJavaStructEmitter.class.getName(), - "-C" + config, - header.getPath()); + final List<String> cfgFiles = new ArrayList<String>(); + cfgFiles.add(config); + final List<String> includePaths = new ArrayList<String>(); + includePaths.add(headerParent); + includePaths.add(outputPath1); + final Reader reader; + final String filename = header.getPath(); + try { + reader = new BufferedReader(new FileReader(filename)); + } catch (FileNotFoundException ex) { + throw new RuntimeException("input file not found", ex); + } + new GlueGen().run(reader, filename, AnnotationProcessorJavaStructEmitter.class, + includePaths, cfgFiles, outputPath1, false /* copyCPPOutput2Stderr */); configFile.delete(); + generatedStructs.add(finalType); } public static class AnnotationProcessorJavaStructEmitter extends JavaEmitter { @@ -234,14 +275,17 @@ public class CStructAnnotationProcessor extends AbstractProcessor { @Override protected PrintWriter openFile(String filename, String simpleClassName) throws IOException { + if( generatedStructs.contains(simpleClassName) ) { + System.err.println("skipping -> " + simpleClassName); + return null; + } + // look for recursive generated structs... keep it DRY if( !simpleClassName.endsWith("32") && !simpleClassName.endsWith("64") ) { - - System.out.println("generating -> " + simpleClassName); + System.err.println("generating -> " + simpleClassName); generatedStructs.add(simpleClassName); } - return super.openFile(filename, simpleClassName); } diff --git a/src/java/com/jogamp/gluegen/structgen/CStructs.java b/src/java/com/jogamp/gluegen/structgen/CStructs.java new file mode 100644 index 0000000..1023d3e --- /dev/null +++ b/src/java/com/jogamp/gluegen/structgen/CStructs.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2010, Michael Bien. All rights reserved. + * Copyright (c) 2013 JogAmp Community. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Michael Bien nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Michael Bien BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package com.jogamp.gluegen.structgen; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Multiple {@link CStruct} elements + */ +@Target(value = {ElementType.TYPE, ElementType.PACKAGE, ElementType.FIELD, ElementType.LOCAL_VARIABLE}) +@Retention(value = RetentionPolicy.SOURCE) +public @interface CStructs { + + /** + * Multiple {@link CStruct} elements. + */ + CStruct[] value(); +} |