kotlingradleintellij-ideakapt

Gradle: Proper way to add KAPT-generated Kotlin sources to sources JAR


I use KAPT to generate some code for my project and I want to include this generated code to sources.jar artifact.

Usual tip for that is to add generated folder to main source set, however this does not work: KAPT uses sources to do the generation and that would create a circular dependency.

I've managed to create this piece of build script:

kapt {
    annotationProcessor("com.example.MyGenerator")
}

sourceSets {
    create("generated") {
        kotlin {
           srcDir("${buildDir}/generated/source/kaptKotlin/main")
        }
    }
}

tasks.named<Jar>("sourcesJar").configure {
    dependsOn("jar") // A bit of overkill, but will do for the sake of example
    archiveClassifier = "sources"
    // main source set is already there
    from(sourceSets.named("generated").get().allSource)
}

This even works as expected: all the sources are in the JAR, however when I load the project into IntelliJ IDEA it shows the following warning:

Duplicate content roots detected
Path [C:/Users/gagar/IdeaProjects/example/example-module/build/generated/source/kaptKotlin/main] of module [example.example-module.generated] was removed from modules [example.example-module.main]

This leads me to a thought that generated sources are already on main sourceSet. However, when I try to generate sourcesJar from main source set, there are no generated sources. Debugging the build with println does not give me anything: for the main source set there is no generated folder and there are no other source sets besides test.

I wonder, is there a better way to fetch this generated source set from a build script?


Solution

  • Turns out, adding generated directory to the main source set is the right way after all. Also you need to declare kaptKotlin dependency to sourcesJar task:

    kapt {
        annotationProcessor("com.example.MyGenerator")
    }
    
    sourceSets {
        main {
            kotlin.srcDir("${layout.buildDirectory.get()}/generated/source/kaptKotlin/main")
        }
    }
    
    tasks.named<Jar>("sourcesJar").configure {
        dependsOn("kaptKotlin")
    }