Search code examples
kotlingradlegradle-kotlin-dsl

Include dependency for custom sourceSet


I have a build.gradle.kts for a small, pure kotlin project (I am aware I am using slightly non-standard source paths):

plugins {
    kotlin("jvm") version "1.3.72"
}

repositories { mavenCentral() }

dependencies {
    implementation(kotlin("stdlib-jdk8"))
    testImplementation("org.jetbrains.kotlin:kotlin-test")
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
}

sourceSets["main"].java.srcDir("src")
sourceSets["test"].java.srcDirs("test")
sourceSets {
    create("demo")?.let {
        it.java.srcDir("demo")
        // Also tried:  it.java.srcDirs("src", "demo")
        it.compileClasspath += main.get().output
        it.runtimeClasspath += main.get().output
    }
}

tasks {
    compileKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }
    compileTestKotlin {
        kotlinOptions.jvmTarget = "1.8"
    }
}

listOf("InteractiveClient", "LockingBufferDemo").forEach {
    tasks.register<Jar>(it) {
        manifest { attributes["Main-Class"] = "${it}Kt" }
        from(sourceSets.main.get().output)
        from(sourceSets["demo"].output) {
            include("**/${it}Kt.class")
        }
        dependsOn(configurations.runtimeClasspath)
        from({
            configurations.runtimeClasspath.get().filter {
                it.name.endsWith("jar") }.map { zipTree(it) }
        })
    }

}

When I try to run one of the "demo" sourceSet based jar tasks ("InteractiveClient" and "LockingBufferDemo"),1 I get a the long list of "Cannot access built-in..." errors indicating the kotlin stdlib is not properly in play.

The actual failing task is compileDemoKotlin, so I tried adding mimetically to the tasks block:

withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
    this.kotlinOptions.jvmTarget = "1.8"
}

Which makes no difference.

What's strange to me is that the demo stuff was originally in the test sourceSet, and changing the above back to that (by removing the definition, changing from(sourceSets["demo"]... to from(sourceSets.test... in the jar task(s), and moving the source file) makes the problem disappear. It works.

I don't want this stuff in with automated tests. I imagine I could put them in branches of the main or test set and then use a from() { exclude(... pattern in building the jars, but that seems awkward and unnecessary.

How do I get a custom source set to compile against the default project dependencies?


  1. See this other recent question of mine about the from(... include( in the jar tasks.

Solution

  • It looks to me like you are missing the configurations that will make the demo source sets use the same dependencies as the main set. Something like this:

    configurations["demoImplementation"].extendsFrom(configurations.implementation.get())
    configurations["demoRuntimeOnly"].extendsFrom(configurations.runtimeOnly.get())
    

    There is an example in the user guide here that seems to have a very similar use case as yours.

    Also, from the issue you created in the Gradle repository, you mentioned it failed with:

    Unresolved reference: printlin

    I am pretty sure this is a typo of println.