【问题标题】:endPosTable already set when adding sourceSet添加 sourceSet 时已设置 endPosTable
【发布时间】:2024-05-01 21:30:02
【问题描述】:

我正在使用自定义注释处理器并且遇到了一个新问题。 我正在使用 Gradle (3.1.1),当我将由我的处理器生成的文件的路径添加到 sourceSet 时,我遇到了奇怪的问题。

之后我执行gradle clean build,然后执行gradle build,构建被破坏。 令我惊讶的是,我得到的堆栈跟踪非常常见。

An exception has occurred in the compiler (1.8.0_91). Please file a bug against the Java compiler via the Java bug reporting page (http://bugreport.java.com) after checking the Bug Database (http://bugs.java.com) for duplicates. Include your program and the following diagnostic in your report. Thank you.
java.lang.IllegalStateException: endPosTable already set
    at com.sun.tools.javac.util.DiagnosticSource.setEndPosTable(DiagnosticSource.java:136)
    at com.sun.tools.javac.util.Log.setEndPosTable(Log.java:350)
    at com.sun.tools.javac.main.JavaCompiler.parse(JavaCompiler.java:667)
    at com.sun.tools.javac.main.JavaCompiler.parseFiles(JavaCompiler.java:950)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.<init>(JavacProcessingEnvironment.java:892)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment$Round.next(JavacProcessingEnvironment.java:921)
    at com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1187)
    at com.sun.tools.javac.main.JavaCompiler.processAnnotations(JavaCompiler.java:1170)
    at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856)
    at com.sun.tools.javac.main.Main.compile(Main.java:523)
    at com.sun.tools.javac.main.Main.compile(Main.java:381)
    at com.sun.tools.javac.main.Main.compile(Main.java:370)
    at com.sun.tools.javac.main.Main.compile(Main.java:361)
    at com.sun.tools.javac.Main.compile(Main.java:56)
    at com.sun.tools.javac.Main.main(Main.java:42)

如果我总是在构建之前清理我没有问题,那么当我不添加 sourceSet 时构建总是成功的。 我什至尝试在我的注释处理器中创建新生成的文件之前删除该文件,但这也没有成功。

在研究过程中,我还发现了这个有趣的链接: JDK Bug report

但是考虑到我要么必须始终先清理,要么将其从我的 sourceSet 中排除,这并不是很好。由于 Eclipse 不喜欢找不到按惯例应该存在的文件。

你对如何解决这个问题有什么建议吗?

【问题讨论】:

    标签: java eclipse gradle preprocessor


    【解决方案1】:

    由于这是 JDK 8 的官方错误,旨在在 JDK 9 中解决,因此我实施了一种解决方法,即使用 gradle 删除已存在的文件。处理器不再有问题,我可以将它保存在我的 sourceSet 中。

    你好 :)

    编辑:解决方法本身。

    gradle.ext.generatedQueriesDir = 'build/generated-sources/local/query'
    /*
     * This is a workaround to delete the file that will be created by the annotation processor if it already exists.
     * There is a known bug in the Java compiler and JDK 8 which should be fixed at JDK 9.
     * http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8067747 <-- Master report
     * http://bugs.java.com/bugdatabase/view_bug.do?bug_id=8146348 <-- duplicates master report
     */
    if ( file( gradle.ext.generatedQueriesDir ).exists() ) {
      FileCollection collection = files { file( gradle.ext.generatedQueriesDir ).listFiles() }
      collection.each { delete it }
    }
    

    我们使用 gradle,所以这是 gradle 脚本的一种解决方法。但基本上解决方法意味着在开始编译和预编译步骤之前删除将生成的文件。

    【讨论】:

      【解决方案2】:

      我正在尝试在我的 Android 应用程序的测试源集中使用生成的 Dagger* 文件。我在@Nico 的解决方法中更改了几处,现在一切对我来说都很好。

      /build.gradle:

      ext {
          generatedSourcesDir = 'build/generated/source/apt/test/debug'
      }
      

      /app/build.gradle

      android {
          sourceSets {
              test.java.srcDirs += generatedSourcesDir
          }
      }
      
      tasks.withType(JavaCompile) {
         if (file(generatedSourcesDir).exists()) {
             FileCollection collection = files { file(generatedSourcesDir).listFiles() }
             collection.each { delete it }
         }
      }
      
      dependencies {
          ...
      }
      

      【讨论】:

      • 很棒的收获!
      • 它救了我的命.. :D