Jeff Lockhart
05/12/2023, 7:11 PMcompileOnly
dependency that allows the consumer to use one of a couple variations of a dependency by explicitly declaring which implementation to use. I'd like to test my project against both variations though. What's the best way to configure gradle to do this?
kotlin {
...
sourceSets {
val commonMain by getting {
dependencies {
compileOnly("variantA")
}
}
val commonTest by getting {
dependencies {
implementation("variantA") // would also like the same tests to run with "variantB" too
}
}
}
}
ephemient
05/13/2023, 10:31 AMcompileOnly
, but rather model it properly with https://docs.gradle.org/current/userguide/feature_variants.htmlephemient
05/13/2023, 10:31 AMephemient
05/13/2023, 10:35 AMcompileOnly
isn't supported on KMP anyway, https://youtrack.jetbrains.com/issue/KT-46760Jeff Lockhart
05/16/2023, 3:43 PMcompileOnly
working with Kotlin/Native. This issue implies it should work if the consumer disables gradle caches. I've been finding it definitely doesn't work like with the JVM though. Most recently I'm finding the compileOnly
dependency is actually available at runtime (at least in tests even after I remove the test implementation). So yes, I think I'm going to have to avoid this route and publish separate variants explicitly.
What I'm trying to do is prevent the need for cascading variants with combinations of my base library, which has two variants, and supplemental extensions to the libraries. I'd prefer not to bundle all of them into the same library because some of the features in the extensions are optional and bring in other dependencies. But if this can be done with a slight modification to a project build.gradle.kts by creating another variant publication with a different dependency, this would work better. Do you know of a good example of doing this manually in a KMP project?
And what about cocoapods dependencies for iOS/macOS? Is it possible to use a different cocoapods dependency for a variant in the same way as Kotlin dependencies? My base library variants each require a different cocoapods dependency.ephemient
05/17/2023, 7:40 PMkotlin {
for (target in listOf(macosArm64("macosarm64basic"), macosX64("macosx64basic"), macosArm64("macosarm64extra"), macosX64("macosx64extra"))) {
configurations.matching { it.name.startsWith(target.name) }.configureEach {
outgoing {
// Register the same capability in all variants so that downstream consumers will reject using multiple different variants at the same time
capability("$group:${project.name}:$version")
// Add a unique capability to each variant so that they can be published distinctly
capability("$group:${project.name}-${target.name}:$version")
consumer
kotlin {
macosArm64()
sourceSets {
getByName("macosArm64Main") {
dependencies {
// Choose one or the other; Gradle will fail if both are used
implementation("my.group:name-macosarm64basic:version")
implementation("my.group:name-macosarm64extra:version")
it doesn't really seem to play well with other stuff that the Kotlin Gradle Plugin wants to do thoughephemient
05/17/2023, 7:44 PMephemient
05/17/2023, 7:45 PMJeff Lockhart
05/17/2023, 8:11 PMsrcDir
for the supplemental code. The supplemental code needs access to internal
APIs, which is why I have to symlink the base variant's source files, rather than just depending on the module.
If I could create both variants within the same module, where one uses the base srcDir
and the other uses both `srcDir`s, as well as changing the dependencies for each, this would work better. The symlinked `srcDir`s are only a problem in that all the files are indexed twice and occasionally experience false merge conflicts from find/replace changes.ephemient
05/17/2023, 8:13 PMinternal
code across modules with @file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
but a better option would be to use your own @RequiresOptIn
annotationJeff Lockhart
05/17/2023, 8:18 PMinternal
is public
).Jeff Lockhart
05/17/2023, 8:30 PMephemient
05/17/2023, 8:33 PMephemient
05/17/2023, 8:34 PMJeff Lockhart
05/17/2023, 8:34 PMJeff Lockhart
05/17/2023, 8:36 PMsrc
again. I might be able to rework these extension library modules with similar code to what you tried above, assuming I publish exclusive capabilities for the base library variants.Jeff Lockhart
05/17/2023, 8:36 PMephemient
05/17/2023, 8:36 PMephemient
05/17/2023, 8:37 PMephemient
05/17/2023, 8:38 PMwrapper-api
that your public code builds against, and wrapper-ce
and wrapper-ee
libraries that are only needed at runtime to implement wrapper-api
ephemient
05/17/2023, 8:40 PMJeff Lockhart
05/17/2023, 8:55 PMJeff Lockhart
05/18/2023, 9:42 PM