Gradle KMM自定义属性无法传递至下级项目依赖的解决方法咨询
问题描述
现有三个Gradle项目::sub1(KMM项目)、:sub2(依赖:sub1的KMM项目)、:parent(依赖:sub2的JVM项目)。构建:parent时出现依赖解析错误,原因是:parent指定的customAttribute仅传递到:sub2,未传递至:sub1,导致Gradle无法确定选择:sub1的哪个JVM变体。
项目代码
:sub1(KMM项目)
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(依赖:sub1的KMM项目)
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(依赖:sub2的JVM项目)
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") } } }
构建错误
> 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
解决方案
要让:parent指定的customAttribute传递到:sub1,需要让中间层:sub2在解析:sub1依赖时,传递自身的customAttribute值。以下是两种可靠实现方式:
方式1:在:sub2中配置属性传递(推荐)
修改:sub2的build.gradle.kts,添加依赖解析策略,让:sub2的变体自动将自身的customAttribute传递给:sub1:
val customAttribute = Attribute.of("custom", String::class.java) // 为所有可解析的配置设置依赖解析策略,传递custom属性 configurations.filter { it.isCanBeResolved }.forEach { config -> // 仅处理带有custom属性的配置 config.attributes.maybeGet(customAttribute)?.let { currentValue -> config.resolutionStrategy.eachDependency { details -> // 匹配依赖的:sub1项目 if (details.requested.group.isBlank() && details.requested.name == "sub1") { // 为:sub1依赖设置当前配置的custom属性值 details.useTarget(mapOf( customAttribute.name to currentValue, "org.jetbrains.kotlin.platform.type" to "jvm" )) } } } }
原理:遍历:sub2中所有可解析的配置(如customCompileClasspath),若配置带有custom属性,则强制解析:sub1时使用相同属性值,实现属性逐层传递。
方式2:在:parent中全局配置属性
修改:parent的build.gradle.kts,直接为:sub1和:sub2设置全局属性规则:
dependencies { api(project(":sub2")) { attributes { attribute(customAttribute, "customValue") } } } val customAttribute = Attribute.of("custom", String::class.java) configurations.all { resolutionStrategy.eachDependency { details -> // 为:sub2和:sub1都设置custom属性 if (details.requested.name in listOf("sub2", "sub1")) { details.attributes { attribute(customAttribute, "customValue") } } } }
原理:在:parent的全局解析策略中,直接指定:sub1和:sub2的customAttribute值,跳过中间传递环节,适合属性值固定的场景。
内容的提问来源于stack exchange,提问作者Mirage
相关产品推荐
相关产品推荐

