This message was deleted.
# community-support
s
This message was deleted.
a
try taking a look at Example 17 here https://docs.gradle.org/current/userguide/java_testing.html#ex-setting-up-working-integration-tests it’s backwards to what you want (it creates a source set that depends on main, whereas you want main to depend on the created source set), but it should give an idea. comparing it with your code, I think you might be missing an equivalent for this
Copy code
configurations["intTestRuntimeOnly"].extendsFrom(configurations.runtimeOnly.get())
t
I would say the "current best way" would be to reconsider whether you really want such a source set. Maybe it'd be a better idea to create a separate project and simply add a dependency on it? or maybe a "feature variant" rather than a project? or if you want everything inside the same JAR then maybe just put everything into the main source set? What are you trying to achieve with that separate "adapter" source set?
j
in adapter i want an interface, then i will add a different source set for each implementation, each compiled against a different version of a dependency, then i will choose which impl to use at runtime based on the version of the dependency on the classpath
right now i am doign a done of runtime reflection to support multiple versions of the upstream dependency
and this will probably be a better approach
i could do multi module, but this is already a sub build in a composite build and I am trying to avoid a complicated restructuring of everything, and I figured sourceset+configuration will be good enough for just one class i need
yeah @Adam i need the reverse of that example.
i tried the extends from thing:
Copy code
named("implementation"){
        extendsFrom(configurations.named("adapter").get())
    }
i dont want to inherit dependencies from the custom source set's configuration, just the classfiles built from those source sets
oh i think my tests arent using testkit classpath. its deploying to maven local and then pulling in the jar for testing
and the classfiles arent making it to the jar
so i tried
Copy code
sourceSets{
    val adapter by creating {

    }
    val main by getting {
        kotlin {
            compileClasspath += adapter.output
            runtimeClasspath += adapter.output
        }
    }
    val test by getting {
        kotlin {
            compileClasspath += adapter.output
            runtimeClasspath += adapter.output
        }
    }
}

configurations {
    val adapterCompile by getting
    val adapterRuntime by getting
    val mainCompile by getting{
        extendsFrom(adapterCompile)
    }
    val mainRuntime by getting{
        extendsFrom(adapterRuntime)
    }
}
and i get
Copy code
Configuration with name 'adapterCompile' not found.
v
That's probably because you are not on an ancient Gradle version.
...Compile
and
...Runtime
were deprecated many many years and finally removed in Gradle 7. You probably want
adapterImplementation
and
adapterRuntimeOnly
.
j
ah yeah i figured. i tried
Copy code
configurations {
    val adapterImplementation by getting
    val adapterRuntimeOnly by getting
    val implementation by getting {
        extendsFrom(adapterImplementation)
    }
    val runtimeOnly by getting {
        extendsFrom(adapterRuntimeOnly)
    }
}
and still get the issue though
adding this works:
Copy code
tasks.named<Jar>("shadowJar"){
    this.from(sourceSets.named("adapter").get().output.classesDirs)
}
(this is a shadow jar artifact)
a
minor nitpick :) it’s usually better to try and use the Gradle Provider API to convert a
Provider<T>
to a file provider
Provider<File>
. That way Gradle can wire up the tasks properly. By using
.get()
, Gradle will compute the value eagerly.
Copy code
tasks.named<Jar>("shadowJar"){
    this.from(sourceSets.named("adapter").map { it.output.classesDirs })
}
it’s not always possible to do this, because the Gradle itself isn’t fully compatible with the Provider API - hence why you have to use
.get()
for the source set classpaths (e.g.
runtimeClasspath += adapter.map { it.output }.get()
)
t
in adapter i want an interface, then i will add a different source set for each implementation, each compiled against a different version of a dependency, then i will choose which impl to use at runtime based on the version of the dependency on the classpath
Looks like feature variants to me, except you don't want to rely on actual variants in dependency resolution (it's not that easy with plugins). But maybe you could use feature variants and arrange to bundle all variants in the same JAR?
(this is a shadow jar artifact)
If you're using the shadow plugin, then how about using distinct Gradle projects rather than source sets then? Would greatly simplify the setup IMO.
a
Hmmm, I just remembered there’s a section in the docs that might be relevant. It’s related to Gradle Plugin development, where someone can create a different Gradle plugin variant for each Gradle version. https://docs.gradle.org/current/userguide/implementing_gradle_plugins.html#plugin-with-variants I wanted to try implementing it, but I didn’t really understand it so I gave up! Perhaps it’s helpful for you though, @John
v
If you want to revisit that try and struggle @Adam, don't hesitate to ask me once you wrapped your head around the topic it is not so hard, just a steep ramp-up. You basically have multiple feature variants, set their capability to the main capability and set the Gradle version attribute. That shoud it basically be.
j
what I am doing is similar to feature variants, but not based on gradle version. based on another dependency
my updated solution is
Copy code
sourceSets {
    val adapter by creating {
    }
    val main by getting {
        kotlin {
            compileClasspath += adapter.output
            runtimeClasspath += adapter.output
        }
    }
    val test by getting {
        kotlin {
            compileClasspath += adapter.output
            runtimeClasspath += adapter.output
        }
    }
}

tasks.named<Jar>("shadowJar") {
    this.from(sourceSets.named("adapter").map {it.output.classesDirs})
}
i guess i didnt need the block for configurations