Assume I have 3 gradle projects with the following paths and file contents:
:sub1
is a KMM project:
plugins {
kotlin("multiplatform")
}
val customAttribute = Attribute.of("custom", String::class.java)
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi::class)
kotlin {
targetHierarchy.default()
jvm {
attributes {
attribute(customAttribute, "normal")
}
}
jvm("custom") {
attributes {
attribute(customAttribute, "customValue")
}
}
sourceSets {
val commonMain by getting
}
}
:sub2
is a KMM project that depends on :sub1
:
plugins {
kotlin("multiplatform")
}
val customAttribute = Attribute.of("custom", String::class.java)
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi::class)
kotlin {
targetHierarchy.default()
jvm {
attributes {
attribute(customAttribute, "normal")
}
}
jvm("custom") {
attributes {
attribute(customAttribute, "customValue")
}
}
sourceSets {
val commonMain by getting {
dependencies {
api(project(":sub1"))
}
}
}
}
:parent
which is a JVM project that depends on :sub2
:
plugins {
id("kotlin")
id("org.jetbrains.kotlin.jvm")
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
val customAttribute = Attribute.of("custom", String::class.java)
dependencies {
api(project(":sub2")) {
attributes {
attribute(customAttribute, "customValue")
}
}
}
Building :project
causes the following error:
> Could not resolve project :sub1.
Required by:
project :project > project :sub2
> The consumer was configured to find a library for use during compile-time, compatible with Java 17, preferably in the form of class files, preferably optimized for standard JVMs, and its dependencies declared externally, as well as attribute 'org.jetbrains.kotlin.platform.type' with value 'jvm'. However we cannot choose between the following variants of project :sub1
- jvmApiElements
- jvmRuntimeElements
- customApiElements
- customRuntimeElements
How do I make it so that the "customValue" of customAttribute declared in :project
propagates down to the project :sub1
from :sub2
, instead of only going down to :sub2
, so that the "custom" JVM target is chosen?
I have tried to set a Gradle project property during the configuration step, but I can't seem to find a way to guarantee project configuration order, so I can't reliably use properties either.
According to error message in project :sub2
Gradle can't choose between jvm
and jvm("custom")
for :sub1
.
Targets should be marked on both the library and consumer sides with a custom attribute, which Gradle uses during dependency resolution.
So in project :sub2
you either need to specify variant attribute for :sub1
project or move dependency from common source. For example:
kotlin {
...
sourceSets {
val jvmMain by getting {
dependencies {
api(project(":sub1")) {
attributes {
attribute(customAttribute, "normal")
}
}
}
}
val customMain by getting {
dependencies {
api(project(":sub1")) {
attributes {
attribute(customAttribute, "customValue")
}
}
}
}
}
}
Take a look at Kotlin Multiplatform documentations for several targets