【问题标题】:Gradle can not compile the code with the generated sources by annotationProcessorGradle 无法使用 annotationProcessor 生成的源编译代码
【发布时间】:2023-03-14 16:50:01
【问题描述】:

如何让 gradle 使用 annotationProcessor 生成的源代码构建/编译项目?

我有一个包含 2 个模块的项目

app-annotation -> 是一个定义一个注解和 AbstractProcessor 的后继者的模块

app-api -> 包含上一个模块中带有注释的实体

这个想法是为每个实体生成默认的 CRUD 存储库和服务,如果需要,也可以扩展一些服务。

问题是,它会生成所有需要的 java 文件(甚至 Intellij Idea 也会看到这些文件),但是一旦我想扩展其中一项服务,它就会在编译时失败,因为据我所知,在编译时我的班级没有之后生成的超类。 如果我这样做了,那么只重新编译我的类就可以了 此外,只有当我使用 Idea 或 gradlew build 构建时,eclipse 才能以某种方式编译而完全没有错误。

为了解决这个问题,使用了下面的解决方案,但它看起来不是很好

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。我觉得它应该简单得多,不是吗?

【问题讨论】:

  • 我将回答有关 Lombok 的工作原理。我们需要添加 lombok 依赖项 + 我们需要将其安装到任何 IDE(Intellij、Eclipse)以进行识别。也许你错过了一个重要的依赖?或者您需要在 IDE 中为您的注释启用它?
  • 好的,那么 Dagger2 是如何工作的?只需为 Dagger2 添加 implementation 和 annotationProcessor 就足够了,在它第一次构建后,它会根据开发人员添加的 AppComponent 生成像 DaggerAppComponent 这样的 java 源代码。

标签: java gradle annotation-processor


【解决方案1】:

最后,我忘了添加这个:

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

还有这个(但我相信这可以进一步改进)

sourceSets {
    main.java.srcDirs += "${projectDir}/src/main/generated/"
}

所有这些都可以删除

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"
}

【讨论】:

    【解决方案2】:

    正如您所意识到的 - 任何代码生成都必须在编译之前完成。

    更简洁的方法是将代码生成逻辑/注释作为依赖项。

    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
    

    【讨论】:

      猜你喜欢
      • 2020-07-27
      • 2021-09-13
      • 1970-01-01
      • 2018-03-29
      • 2018-01-14
      • 1970-01-01
      • 2015-12-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多