简体   繁体   中英

Annotation processor in Gradle outputs source files to build/classes making javadoc fail. How to fix it?

I have an annotation processor that is automatically picked up by the Java compiler at build time (using SPI). During a gradle build, the generated java sources of this annotation processor are put in build/classes as Gradle tells the annotation processor that this is the place to output generated source files.

When the standard javadoc task is run, it tries to create javadoc for all files in build/classes, including *.java. This failes because javadoc only expects *.class files, making the whole build fail.

So my question is:

Is this a Gradle bug/feature? How do I fix it/make it work?

It seems the problem is that the generated source files are not picked up, making the javadoc fail because it had nothing to process.

I'm posting the solution here in case somebody is experiencing the same problem:

The problem with compile time source generation in gradle is that the outputted sources are not automatically picked up by the javadoc. This is a problem if all your sources are auto generated. The build will fail with an error saying that no sources could be processed. In the other case your build will succeed but you will have no javadoc of your generated java sources.

The root problem here is gradle's poor integration with generating sources that are both generated and compiled during the same compile step. To remedy this I changed my build files to this.

project layout:

  • rootproject
  • rootproject/annotationProcessor
  • rootproect/userOfAnnotationProcessor

build file of 文件

def generatedSources = "$buildDir/generated-src"
def generatedOutputDir = file("$generatedSources")

compileJava {
    doFirst {
        generatedOutputDir.exists() || generatedOutputDir.mkdirs()
        options.compilerArgs = [
                '-s', "${generatedSources}"
        ]
    }
}


sourceSets {
    main {
        java {
            srcDirs += generatedOutputDir
        }
    }
}

javadoc {
    source = sourceSets.main.resources
}
compileJava.dependsOn clean

The trick here is to not add your generated sources to a custom sources set, else we'll run into troubles when trying to build aggregated javadoc in our root project. However this solution has the nasty side effect that our generated sources or added twice for some reason when trying to build after a first clean+build. The solution here is to always do a clean+build.

Now when doing an aggregate javadoc build, we'd like our generated source javadoc to be part of it as well.

This is how our build file looks like: 构建文件的样子:

def exportedProjects = [
        ":annotationProcessor",
        ":userOfAnnotationProcessor",
]

task alljavadoc(type: Javadoc) {
    source exportedProjects.collect { project(it).sourceSets.main.allJava }
    classpath = files(exportedProjects.collect { project(it).sourceSets.main.compileClasspath })
    destinationDir = file("${buildDir}/docs/javadoc")
}


alljavadoc.dependsOn(":userOfAnnotationProcessor:compileJava")

If we had used a custom source set previously, gradle would now start complaining about source set properties not being found. Why? I don't know... A last important thing to notice is that our alljavadoc depeonds on the compilation step of , this is needed to make sure our generated source files are there when the aggregated javadoc is build. 的编译步骤,这是需要确保我们生成的源文件都存在时,聚集的javadoc是建立。

I hope I've helped sombody with this explanation!

I am not quite sure weather it is a bug or not. But as a workaround just filter the sources of javadoc.

Depending on how your build script looks like, it should look something like thistask

myJavadocs(type: Javadoc) {
  classpath = sourceSets.main.output.filter { it -> !it.name.endsWith('.java') }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM