我有一些代码在编译时通过 java APT 生成一些服务,在 java9 之前,我通过 APT 生成 java 源代码,并使用 Google AutoService 在 META-INF/services 文件夹下生成服务文件,现在我想升级它以使用Java9模块描述(module-info)放服务定义,但我失败了,见下面的代码:
final String MODULE_FILE_NAME = "module-info";
Writer srcWriter = null;
try {
this._logger.info("Generate module file for -> {}", module.getName());
JavaFileObject fileObj = builderContext.getFiler().createSourceFile(MODULE_FILE_NAME);
// FileObject fileObj = builderContext.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", MODULE_FILE_NAME);
srcWriter = fileObj.openWriter();
temp.process(model, srcWriter);
} catch (Exception ex) {
......
编译代码,下面会抛出异常:
> Task :uapi.service:compileJava
注: Loading external handlers...
注: uapi.annotation.internal.ModuleHandler
注: uapi.annotation.internal.NotNullHandler
注: Start processing annotations...
注: Annotation Module on [uapi.service]
注: Generating sources...
注: Generate module file for -> uapi.service
错误: An error was risen when generate module for - uapi.service
错误: Illegal name module-info
错误: jdk.compiler/com.sun.tools.javac.processing.JavacFiler.checkName(JavacFiler.java:695)
jdk.compiler/com.sun.tools.javac.processing.JavacFiler.checkNameAndExistence(JavacFiler.java:715)
jdk.compiler/com.sun.tools.javac.processing.JavacFiler.createSourceOrClassFile(JavacFiler.java:489)
jdk.compiler/com.sun.tools.javac.processing.JavacFiler.createSourceFile(JavacFiler.java:426)
uapi.codegen.internal.AnnotationProcessor.generateModule(AnnotationProcessor.java:164)
uapi.codegen.internal.AnnotationProcessor.process(AnnotationProcessor.java:142)
org.gradle.api.internal.tasks.compile.processing.DelegatingProcessor.process(DelegatingProcessor.java:62)
org.gradle.api.internal.tasks.compile.processing.NonIncrementalProcessor.process(NonIncrementalProcessor.java:45)
org.gradle.api.internal.tasks.compile.processing.DelegatingProcessor.process(DelegatingProcessor.java:62)
org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor.access$401(TimeTrackingProcessor.java:37)
org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor$5.create(TimeTrackingProcessor.java:99)
org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor$5.create(TimeTrackingProcessor.java:96)
org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor.track(TimeTrackingProcessor.java:117)
org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor.process(TimeTrackingProcessor.java:96)
jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:980)
jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.discoverAndRunProcs(JavacProcessingEnvironment.java:896)
jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.run(JavacProcessingEnvironment.java:1222)
jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1334)
jdk.compiler/com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1258)
jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:936)
jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.lambda$doCall$0(JavacTaskImpl.java:104)
jdk.compiler/com.sun.tools.javac.api.JavacTaskImpl.handleExceptions(JavacTaskImpl.java:147)
...
如果我使用builderContext.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", MODULE_FILE_NAME)
生成模块信息文件,可以创建该文件,但似乎 javac 不编译它。
我检查了 Filer 接口的 javadoc,它说:
文件创建方法采用可变数量的参数,以允许将原始元素作为提示提供给工具基础架构,以更好地管理依赖关系。原始元素是导致注释处理器尝试创建新文件的类型或包(表示包信息文件)或模块(表示模块信息文件)。
但是createSourceFile和createClassFile似乎都只支持 java 类型和包(package-info):
创建一个新的源文件并返回一个对象以允许对其进行写入。可以创建类型或包的源文件。
那么如何在编译时生成模块信息文件呢?或者我必须在编译时使用像 ASM 这样的字节码工具来生成 module-info.class 文件?