Home > database >  "Add dependency on module [project].main" for custom sourceset
"Add dependency on module [project].main" for custom sourceset

Time:10-01

This is derived from a bug I just filed on IntJ: https://youtrack.jetbrains.com/issue/IDEA-302732/Gradle-wrapper-builds-jar-from-custom-source-set-without-error-but-intelliJ-fails-import

I don't think it is a real problem in the sense that all this works with gradle, but it produces spurious errors in IntJ and, until the bug (if it be) is fixed, I'm looking for a way around. It could be derived from some unconventional practice of mine, so if you see anything that makes you think "there's a more conventional method here", let me know.

I'm using a custom sourceset to build an executable jar in a library project; it's for a tool that uses the lib but isn't included in it. I know other people use a similar method for demos and integration tests.

I put together a minimal example for the bug report, here's the meat of build.gradle.kts (the whole thing is posted in the report if you want/need):

sourceSets["main"].java.srcDir("src")
sourceSets.create("eg") {
    java.srcDirs("src", "eg")
    compileClasspath = sourceSets["main"].compileClasspath
}

tasks.register<Jar>("foobar") {
    archiveFileName.set("foobar.jar")
    manifest { attributes["Main-Class"] = "FoobarKt" }
    // Not sure why this is necessary here, it isn't in the original project.
    duplicatesStrategy = org.gradle.api.file.DuplicatesStrategy.EXCLUDE
    dependsOn(configurations.runtimeClasspath)
    from(sourceSets["eg"].output)
    from({
        configurations.runtimeClasspath.get().filter {
            it.name.endsWith("jar") }.map { zipTree(it) }
    })
}

src/main/kotlin/Example/Example.kt:

package Example

class Example {
    fun hello () {
        println("hello world")
    }
}

And in eg/Foobar.kt, the entry point for the executable jar:

import Example.Example

fun main () {
    val eg = Example()
    eg.hello()
}

If I run ./gradlew foobar from the project directory, it builds without error and runs via java -jar as expected.

However, in the IntJ editor, Foobar.kt has "unresolved reference" errors for Example on lines 1 and 4. It suggests I "Add dependency on module Problem.main", which is clickable but does nothing.1

I admit to not being much of a gradle fan -- for whatever reason the supposedly (?) intuitive DSL is persistently counter-intuitive with me, I'd much rather just use a more normal API (if the build system is going to be Turing complete, why dress it down inscrutably?) -- and I just don't get what is meant by that.


  1. There's a slew of other reports going back for years about this "add dependency on module..." suggestion doing nothing in various contexts.

CodePudding user response:

Thanks to Andrey for posting a solution in the bug report. Whether it remains a bug to be fixed or an inconsistency to be noted is up to others, but what works is to add the output of the main sourceset to the compileClasspath in the definition of the custom one:

sourceSets.create("eg") {
    java.srcDirs("src", "eg")
    compileClasspath = sourceSets["main"].compileClasspath
    // You can use ' ' as well to combine these in one line.
    compileClasspath  = sourceSets["main"].output
}

You actually only need the output to resolve the problem in the example from the question here, but if the custom sourceset code includes imports of project dependencies declared with implementation or api, you need the main compileClasspath as well.

  • Related