Gradle 无法使用 annotationProcessor 生成的源代码编译代码
Gradle can not compile the code with the generated sources by annotationProcessor
如何使用 annotationProcessor 生成的源代码使 gradle build/compile 成为一个项目?
我有一个包含 2 个模块的项目
app-annotation -> 是定义一个注解和 AbstractProcessor
后继者的模块
app-api -> 包含带有前一个模块注释的实体
我们的想法是为每个实体生成默认的 CRUD 存储库和服务,如果需要也可以扩展一些服务。
问题是,它会生成所有需要的 java 文件(甚至 Intellij Idea 也能看到这些文件),但是一旦我想扩展其中一项服务,它就会在编译时失败,因为我在编译我的 class 时明白没有它的 superclass 是在之后生成的。
如果我这样做然后只重新编译我的 class 那么就可以了
此外,eclipse 以某种方式编译时完全没有错误,只有当我使用 Idea 或 gradlew build.
构建时
为了修复它,使用了下面的解决方案,但它看起来不太好
configurations {
preProcessAnnotation
}
def defaultSrcDir = "$projectDir/src/main/java"
def entitySources = "$projectDir/src/main/java/com/abcd/app/entity"
def generatedSources = "$buildDir/generated/sources/annotationProcessor/java/main"
def generatedOutputDir = file("$generatedSources")
// Explicitly run the annotation processor against the entities
task preProcessAnnotation (type: JavaCompile) {
source = entitySources
classpath = sourceSets.main.compileClasspath
destinationDirectory = generatedOutputDir
options.sourcepath = sourceSets.main.java.getSourceDirectories()
options.annotationProcessorPath = configurations.getByName("preProcessAnnotation")
options.compilerArgs << "-proc:only"
options.encoding = "ISO-8859-1"
}
// Explicitly specify the files to compile
compileJava {
dependsOn(clean)
dependsOn(preProcessAnnotation)
def files = []
fileTree(defaultSrcDir).visit { FileVisitDetails details ->
files << details.file.path
}
fileTree(generatedSources).visit { FileVisitDetails details ->
files << details.file.path
}
source = files
options.compilerArgs << "-Xlint:deprecation"
options.compilerArgs << "-Xlint:unchecked"
options.encoding = "ISO-8859-1"
}
....
dependencies {
preProcessAnnotation project(':app-annotation')
// Generate the crud repositories and services
compile project(':app-annotation')
implementation project(':app-annotation')
...
}
很好奇Lombok、Dagger2等类似的代码生成框架是如何正常运行的
PS。我觉得应该更简单吧?
如您所知 - 任何代码生成都必须在编译之前完成。
更简洁的方法是将代码生成逻辑/注释作为依赖项。
task codeGen {
// creates under build/genSrc
}
//add to default source set
sourceSets.main.java.srcDir "build/genSrc"
//this has access to all code
compile.dependsOn codeGen
最后,都是我的错,我用错误的方法保存了生成的java文件。
// Wrong!
javax.annotation.processing.Filer#createResource(StandardLocation.SOURCE_OUTPUT, packageName, className + ".java")
// Correct
javax.annotation.processing.Filer#createSourceFile(packageName + "." + className)
如何使用 annotationProcessor 生成的源代码使 gradle build/compile 成为一个项目?
我有一个包含 2 个模块的项目
app-annotation -> 是定义一个注解和 AbstractProcessor
后继者的模块app-api -> 包含带有前一个模块注释的实体
我们的想法是为每个实体生成默认的 CRUD 存储库和服务,如果需要也可以扩展一些服务。
问题是,它会生成所有需要的 java 文件(甚至 Intellij Idea 也能看到这些文件),但是一旦我想扩展其中一项服务,它就会在编译时失败,因为我在编译我的 class 时明白没有它的 superclass 是在之后生成的。 如果我这样做然后只重新编译我的 class 那么就可以了 此外,eclipse 以某种方式编译时完全没有错误,只有当我使用 Idea 或 gradlew build.
构建时为了修复它,使用了下面的解决方案,但它看起来不太好
configurations {
preProcessAnnotation
}
def defaultSrcDir = "$projectDir/src/main/java"
def entitySources = "$projectDir/src/main/java/com/abcd/app/entity"
def generatedSources = "$buildDir/generated/sources/annotationProcessor/java/main"
def generatedOutputDir = file("$generatedSources")
// Explicitly run the annotation processor against the entities
task preProcessAnnotation (type: JavaCompile) {
source = entitySources
classpath = sourceSets.main.compileClasspath
destinationDirectory = generatedOutputDir
options.sourcepath = sourceSets.main.java.getSourceDirectories()
options.annotationProcessorPath = configurations.getByName("preProcessAnnotation")
options.compilerArgs << "-proc:only"
options.encoding = "ISO-8859-1"
}
// Explicitly specify the files to compile
compileJava {
dependsOn(clean)
dependsOn(preProcessAnnotation)
def files = []
fileTree(defaultSrcDir).visit { FileVisitDetails details ->
files << details.file.path
}
fileTree(generatedSources).visit { FileVisitDetails details ->
files << details.file.path
}
source = files
options.compilerArgs << "-Xlint:deprecation"
options.compilerArgs << "-Xlint:unchecked"
options.encoding = "ISO-8859-1"
}
....
dependencies {
preProcessAnnotation project(':app-annotation')
// Generate the crud repositories and services
compile project(':app-annotation')
implementation project(':app-annotation')
...
}
很好奇Lombok、Dagger2等类似的代码生成框架是如何正常运行的
PS。我觉得应该更简单吧?
如您所知 - 任何代码生成都必须在编译之前完成。
更简洁的方法是将代码生成逻辑/注释作为依赖项。
task codeGen {
// creates under build/genSrc
}
//add to default source set
sourceSets.main.java.srcDir "build/genSrc"
//this has access to all code
compile.dependsOn codeGen
最后,都是我的错,我用错误的方法保存了生成的java文件。
// Wrong!
javax.annotation.processing.Filer#createResource(StandardLocation.SOURCE_OUTPUT, packageName, className + ".java")
// Correct
javax.annotation.processing.Filer#createSourceFile(packageName + "." + className)