Always rewrite dependencies in POMs when publishing an MPP (KT-28482)
As non-Gradle consumers and Gradle consumers with metadata disabled cannot read Gradle metadata, in POMs (the only source of dependencies for the consumers mentioned above), we should publish the dependencies on modules with metadata as the target artifact IDs rather than the root MPP module ID (e.g. 'foo-jvm' rather than 'foo'). To do that, we rewrite the POMs of the publications even when Gradle metadata is enabled. Note: in the POMs, a project dependency is already written in the form of the artifact ID of the root Kotlin software component, so it complicates the dependencies rewriting a little. To rewrite third-party dependencies, we detect dependencies that resolved to no artifact and have a single child in the Gradle dependencies graph of the resolved configuration – this is what a dependency looks like which was redirected to another module via 'available-at'. Issue #KT-28482 Fixed
This commit is contained in:
+69
-10
@@ -10,7 +10,10 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.NativeOutputKind
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.UnusedSourceSetsChecker
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.METADATA_CONFIGURATION_NAME_SUFFIX
|
||||
import org.jetbrains.kotlin.gradle.plugin.sources.SourceSetConsistencyChecks
|
||||
import org.jetbrains.kotlin.gradle.util.*
|
||||
import org.jetbrains.kotlin.gradle.util.checkBytecodeContains
|
||||
import org.jetbrains.kotlin.gradle.util.isWindows
|
||||
import org.jetbrains.kotlin.gradle.util.modify
|
||||
import org.jetbrains.kotlin.gradle.util.testResolveAllConfigurations
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
import org.jetbrains.kotlin.konan.target.HostManager
|
||||
import org.junit.Assert
|
||||
@@ -603,7 +606,7 @@ class NewMultiplatformIT : BaseGradleIT() {
|
||||
fun testPublishWithoutGradleMetadata() {
|
||||
val libProject = Project("sample-lib", gradleVersion, "new-mpp-lib-and-app")
|
||||
|
||||
with (libProject) {
|
||||
with(libProject) {
|
||||
setupWorkingDir()
|
||||
projectDir.resolve("settings.gradle").modify { it.replace("enableFeaturePreview", "// enableFeaturePreview") }
|
||||
|
||||
@@ -1160,8 +1163,34 @@ class NewMultiplatformIT : BaseGradleIT() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPublishMultimoduleProjectWithNoMetadata() {
|
||||
val libProject = Project("sample-lib", gradleVersion, "new-mpp-lib-and-app")
|
||||
fun testPublishMultimoduleProjectWithNoMetadata() = doTestPublishMultimoduleProject(withMetadata = false)
|
||||
|
||||
@Test
|
||||
fun testPublishMultimoduleProjectWithMetadata() = doTestPublishMultimoduleProject(withMetadata = true)
|
||||
|
||||
private fun doTestPublishMultimoduleProject(withMetadata: Boolean) {
|
||||
val libProject = Project("sample-lib", gradleVersion, "new-mpp-lib-and-app").apply {
|
||||
if (withMetadata) {
|
||||
setupWorkingDir()
|
||||
// Make another publication that will be consumed as a module with metadata, see a similar conditional block below:
|
||||
projectDir.resolve("settings.gradle").writeText("rootProject.name = 'external'; enableFeaturePreview 'GRADLE_METADATA'")
|
||||
gradleBuildScript().appendText(
|
||||
"\n" + """
|
||||
group = "com.external.dependency"
|
||||
version = "1.2.3"
|
||||
publishing {
|
||||
repositories {
|
||||
maven { url "file://${'$'}{rootProject.projectDir.absolutePath.replace('\\', '/')}/repo" }
|
||||
}
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
build("publish") {
|
||||
assertSuccessful()
|
||||
gradleBuildScript().appendText("\ngroup = 'com.example'; version = '1.0'")
|
||||
}
|
||||
}
|
||||
}
|
||||
val appProject = Project("sample-app", gradleVersion, "new-mpp-lib-and-app")
|
||||
|
||||
with(libProject) {
|
||||
@@ -1169,7 +1198,7 @@ class NewMultiplatformIT : BaseGradleIT() {
|
||||
appProject.setupWorkingDir()
|
||||
appProject.projectDir.copyRecursively(projectDir.resolve("sample-app"))
|
||||
|
||||
projectDir.resolve("settings.gradle").writeText("include 'sample-app'") // also disables feature preview 'GRADLE_METADATA'
|
||||
gradleSettingsScript().writeText("include 'sample-app'") // disables feature preview 'GRADLE_METADATA', resets rootProject name
|
||||
gradleBuildScript("sample-app").modify {
|
||||
it.replace("'com.example:sample-lib:1.0'", "project(':')") + "\n" + """
|
||||
apply plugin: 'maven-publish'
|
||||
@@ -1182,6 +1211,20 @@ class NewMultiplatformIT : BaseGradleIT() {
|
||||
}
|
||||
""".trimIndent()
|
||||
}
|
||||
if (withMetadata) {
|
||||
gradleSettingsScript().appendText("\nenableFeaturePreview(\"GRADLE_METADATA\")")
|
||||
// Add a dependency that is resolved with metadata:
|
||||
gradleBuildScript("sample-app").appendText(
|
||||
"\n" + """
|
||||
repositories {
|
||||
maven { url "file://${'$'}{rootProject.projectDir.absolutePath.replace('\\', '/')}/repo" }
|
||||
}
|
||||
dependencies {
|
||||
commonMainApi 'com.external.dependency:external:1.2.3'
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
gradleBuildScript().appendText("\n" + """
|
||||
publishing {
|
||||
@@ -1195,7 +1238,7 @@ class NewMultiplatformIT : BaseGradleIT() {
|
||||
}
|
||||
""".trimIndent())
|
||||
|
||||
build("publish") {
|
||||
build("clean", "publish") {
|
||||
assertSuccessful()
|
||||
assertFileContains(
|
||||
"repo/com/exampleapp/sample-app-nodejs/1.0/sample-app-nodejs-1.0.pom",
|
||||
@@ -1209,6 +1252,22 @@ class NewMultiplatformIT : BaseGradleIT() {
|
||||
"<artifactId>bar</artifactId>",
|
||||
"<version>42</version>"
|
||||
)
|
||||
if (withMetadata) {
|
||||
// Check that the external dependency that was resolved with metadata is written to the POM as the artifactId it
|
||||
// resolved to:
|
||||
assertFileContains(
|
||||
"repo/com/exampleapp/sample-app-jvm8/1.0/sample-app-jvm8-1.0.pom",
|
||||
"<groupId>com.external.dependency</groupId>",
|
||||
"<artifactId>external-jvm6</artifactId>",
|
||||
"<version>1.2.3</version>"
|
||||
)
|
||||
|
||||
// Check that, despite the rewritten POM, the module metadata contains the original dependency:
|
||||
val moduleMetadata = projectDir.resolve("repo/com/exampleapp/sample-app-jvm8/1.0/sample-app-jvm8-1.0.module").readText()
|
||||
.replace("\\s+".toRegex(), "").replace("\n", "")
|
||||
assertTrue { "\"group\":\"com.example\",\"module\":\"sample-lib\"" in moduleMetadata }
|
||||
assertTrue { "\"group\":\"com.external.dependency\",\"module\":\"external\"" in moduleMetadata }
|
||||
}
|
||||
assertFileExists("repo/foo/bar/42/bar-42.jar")
|
||||
}
|
||||
}
|
||||
@@ -1285,10 +1344,10 @@ class NewMultiplatformIT : BaseGradleIT() {
|
||||
assertFileContains("build/classes/kotlin/nodeJs/main/sample-lib.js", "Override")
|
||||
|
||||
val (compilerPluginArgsBySourceSet, compilerPluginClasspathBySourceSet) =
|
||||
listOf(compilerPluginArgsRegex, compilerPluginClasspathRegex)
|
||||
.map { marker ->
|
||||
marker.findAll(output).associate { it.groupValues[1] to it.groupValues[2] }
|
||||
}
|
||||
listOf(compilerPluginArgsRegex, compilerPluginClasspathRegex)
|
||||
.map { marker ->
|
||||
marker.findAll(output).associate { it.groupValues[1] to it.groupValues[2] }
|
||||
}
|
||||
|
||||
// TODO once Kotlin/Native properly supports compiler plugins, expand this to all source sets:
|
||||
listOf("commonMain", "commonTest", "jvm6Main", "jvm6Test", "nodeJsMain", "nodeJsTest").forEach {
|
||||
|
||||
+10
-3
@@ -12,9 +12,8 @@ import org.gradle.util.ConfigureUtil
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetPreset
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetsContainerWithPresets
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinCommonCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinMultiplatformPlugin
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinOnlyTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
|
||||
|
||||
open class KotlinMultiplatformExtension : KotlinProjectExtension(), KotlinTargetContainerWithPresetFunctions {
|
||||
override lateinit var presets: NamedDomainObjectCollection<KotlinTargetPreset<*>>
|
||||
@@ -44,6 +43,14 @@ open class KotlinMultiplatformExtension : KotlinProjectExtension(), KotlinTarget
|
||||
fun targetFromPreset(preset: KotlinTargetPreset<*>) = targetFromPreset(preset, preset.name) { }
|
||||
fun targetFromPreset(preset: KotlinTargetPreset<*>, name: String) = targetFromPreset(preset, name) { }
|
||||
fun targetFromPreset(preset: KotlinTargetPreset<*>, configure: Closure<*>) = targetFromPreset(preset, preset.name, configure)
|
||||
|
||||
internal val rootSoftwareComponent: KotlinSoftwareComponent by lazy {
|
||||
if (isGradleVersionAtLeast(4, 7)) {
|
||||
KotlinSoftwareComponentWithCoordinatesAndPublication("kotlin", targets)
|
||||
} else {
|
||||
KotlinSoftwareComponent("kotlin", targets)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun KotlinTarget.isProducedFromPreset(kotlinTargetPreset: KotlinTargetPreset<*>): Boolean =
|
||||
|
||||
+66
-1
@@ -6,8 +6,12 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import groovy.lang.Closure
|
||||
import groovy.util.Node
|
||||
import groovy.util.NodeList
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.XmlProvider
|
||||
import org.gradle.api.artifacts.ModuleDependency
|
||||
import org.gradle.api.attributes.Attribute
|
||||
import org.gradle.api.attributes.AttributeContainer
|
||||
import org.gradle.api.internal.FeaturePreviews
|
||||
@@ -156,7 +160,7 @@ class KotlinMultiplatformPlugin(
|
||||
}
|
||||
|
||||
val targets = project.multiplatformExtension!!.targets
|
||||
val kotlinSoftwareComponent = KotlinSoftwareComponent("kotlin", targets)
|
||||
val kotlinSoftwareComponent = project.multiplatformExtension!!.rootSoftwareComponent
|
||||
|
||||
project.extensions.configure(PublishingExtension::class.java) { publishing ->
|
||||
|
||||
@@ -203,6 +207,8 @@ class KotlinMultiplatformPlugin(
|
||||
}
|
||||
(this as MavenPublicationInternal).publishWithOriginalFileName()
|
||||
artifactId = variant.defaultArtifactId
|
||||
|
||||
pom.withXml { xml -> project.rewritePomMppDependenciesToActualTargetModules(xml, variant) }
|
||||
}
|
||||
|
||||
(variant as? KotlinTargetComponentWithPublication)?.publicationDelegate = variantPublication
|
||||
@@ -308,3 +314,62 @@ internal fun compilationsBySourceSet(project: Project): Map<KotlinSourceSet, Set
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.rewritePomMppDependenciesToActualTargetModules(
|
||||
pomXml: XmlProvider,
|
||||
component: KotlinTargetComponent
|
||||
) {
|
||||
if (component !is SoftwareComponentInternal)
|
||||
return
|
||||
|
||||
val dependenciesNodeList = pomXml.asNode().get("dependencies") as NodeList
|
||||
val dependencyNodes = dependenciesNodeList.filterIsInstance<Node>().flatMap {
|
||||
(it.get("dependency") as? NodeList).orEmpty()
|
||||
}.filterIsInstance<Node>()
|
||||
|
||||
val dependencyByNode = mutableMapOf<Node, ModuleDependency>()
|
||||
|
||||
// Collect all the dependencies from the nodes:
|
||||
val dependencies = dependencyNodes.map { dependencyNode ->
|
||||
fun Node.getSingleChildValueOrNull(childName: String): String? =
|
||||
((get(childName) as NodeList?)?.singleOrNull() as Node?)?.text()
|
||||
|
||||
val groupId = dependencyNode.getSingleChildValueOrNull("groupId")
|
||||
val artifactId = dependencyNode.getSingleChildValueOrNull("artifactId")
|
||||
val version = dependencyNode.getSingleChildValueOrNull("version")
|
||||
(project.dependencies.module("$groupId:$artifactId:$version") as ModuleDependency)
|
||||
.also { dependencyByNode[dependencyNode] = it }
|
||||
}.toSet()
|
||||
|
||||
// Get the dependencies mapping according to the component's UsageContexts:
|
||||
val resultDependenciesForEachUsageContext =
|
||||
component.usages.mapNotNull { usage ->
|
||||
if (usage is KotlinUsageContext)
|
||||
rewriteDependenciesToActualModuleDependencies(usage, dependencies)
|
||||
// We are only interested in dependencies that are mapped to some other dependencies:
|
||||
.filter { (from, to) -> Triple(from.group, from.name, from.version) != Triple(to.group, to.name, to.version) }
|
||||
else null
|
||||
}
|
||||
|
||||
// Rewrite the dependency nodes according to the mapping:
|
||||
dependencyNodes.forEach { dependencyNode ->
|
||||
val moduleDependency = dependencyByNode[dependencyNode]
|
||||
val mapDependencyTo = resultDependenciesForEachUsageContext.find { moduleDependency in it }?.get(moduleDependency)
|
||||
|
||||
if (mapDependencyTo != null) {
|
||||
|
||||
fun Node.setChildNodeByName(name: String, value: String?) {
|
||||
val childNode: Node? = (get(name) as NodeList?)?.firstOrNull() as Node?
|
||||
if (value != null) {
|
||||
(childNode ?: appendNode(name)).setValue(value)
|
||||
} else {
|
||||
childNode?.let { remove(it) }
|
||||
}
|
||||
}
|
||||
|
||||
dependencyNode.setChildNodeByName("groupId", mapDependencyTo.group)
|
||||
dependencyNode.setChildNodeByName("artifactId", mapDependencyTo.name)
|
||||
dependencyNode.setChildNodeByName("version", mapDependencyTo.version)
|
||||
}
|
||||
}
|
||||
}
|
||||
+89
-45
@@ -10,15 +10,17 @@ import org.gradle.api.artifacts.*
|
||||
import org.gradle.api.attributes.AttributeContainer
|
||||
import org.gradle.api.attributes.Usage
|
||||
import org.gradle.api.capabilities.Capability
|
||||
import org.gradle.api.component.ComponentWithCoordinates
|
||||
import org.gradle.api.component.ComponentWithVariants
|
||||
import org.gradle.api.internal.component.SoftwareComponentInternal
|
||||
import org.gradle.api.internal.component.UsageContext
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.utils.ifEmpty
|
||||
|
||||
class KotlinSoftwareComponent(
|
||||
open class KotlinSoftwareComponent(
|
||||
private val name: String,
|
||||
private val kotlinTargets: Iterable<KotlinTarget>
|
||||
protected val kotlinTargets: Iterable<KotlinTarget>
|
||||
) : SoftwareComponentInternal, ComponentWithVariants {
|
||||
|
||||
override fun getUsages(): Set<UsageContext> = emptySet()
|
||||
@@ -27,6 +29,18 @@ class KotlinSoftwareComponent(
|
||||
kotlinTargets.flatMap { it.components }.toSet()
|
||||
|
||||
override fun getName(): String = name
|
||||
|
||||
// This property is declared in the parent type to allow the usages to reference it without forcing the subtypes to load,
|
||||
// which is needed for compatibility with older Gradle versions
|
||||
var publicationDelegate: MavenPublication? = null
|
||||
}
|
||||
|
||||
class KotlinSoftwareComponentWithCoordinatesAndPublication(name: String, kotlinTargets: Iterable<KotlinTarget>) :
|
||||
KotlinSoftwareComponent(name, kotlinTargets), ComponentWithCoordinates {
|
||||
|
||||
override fun getCoordinates(): ModuleVersionIdentifier = getCoordinatesFromPublicationDelegateAndProject(
|
||||
publicationDelegate, kotlinTargets.first().project, null
|
||||
)
|
||||
}
|
||||
|
||||
// At the moment all KN artifacts have JAVA_API usage.
|
||||
@@ -45,7 +59,6 @@ class DefaultKotlinUsageContext(
|
||||
override val compilation: KotlinCompilation<*>,
|
||||
private val usage: Usage,
|
||||
override val dependencyConfigurationName: String,
|
||||
private val publishWithGradleMetadata: Boolean,
|
||||
override val sourcesArtifact: PublishArtifact? = null,
|
||||
private val overrideConfigurationArtifacts: Set<PublishArtifact>? = null
|
||||
) : KotlinUsageContext {
|
||||
@@ -65,10 +78,7 @@ class DefaultKotlinUsageContext(
|
||||
get() = project.configurations.getByName(dependencyConfigurationName)
|
||||
|
||||
override fun getDependencies(): MutableSet<out ModuleDependency> =
|
||||
if (publishWithGradleMetadata)
|
||||
configuration.incoming.dependencies.withType(ModuleDependency::class.java)
|
||||
else
|
||||
rewriteMppDependenciesToTargetModuleDependencies(this, configuration).toMutableSet()
|
||||
configuration.incoming.dependencies.withType(ModuleDependency::class.java)
|
||||
|
||||
override fun getDependencyConstraints(): MutableSet<out DependencyConstraint> =
|
||||
configuration.incoming.dependencyConstraints
|
||||
@@ -86,14 +96,14 @@ class DefaultKotlinUsageContext(
|
||||
override fun getGlobalExcludes(): Set<ExcludeRule> = emptySet()
|
||||
}
|
||||
|
||||
private fun rewriteMppDependenciesToTargetModuleDependencies(
|
||||
internal fun rewriteDependenciesToActualModuleDependencies(
|
||||
usageContext: KotlinUsageContext,
|
||||
fromConfiguration: Configuration
|
||||
): Set<ModuleDependency> = with(usageContext.compilation.target.project) {
|
||||
moduleDependencies: Set<ModuleDependency>
|
||||
): Map<ModuleDependency, ModuleDependency> {
|
||||
val compilation = usageContext.compilation
|
||||
val moduleDependencies = fromConfiguration.incoming.dependencies.withType(ModuleDependency::class.java).ifEmpty { return emptySet() }
|
||||
val project = compilation.target.project
|
||||
|
||||
val targetCompileDependenciesConfiguration = project.configurations.getByName(
|
||||
val targetDependenciesConfiguration = project.configurations.getByName(
|
||||
when (compilation) {
|
||||
is KotlinJvmAndroidCompilation -> {
|
||||
// TODO handle Android configuration names in a general way once we drop AGP < 3.0.0
|
||||
@@ -112,52 +122,86 @@ private fun rewriteMppDependenciesToTargetModuleDependencies(
|
||||
}
|
||||
)
|
||||
|
||||
val resolvedCompileDependencies by lazy {
|
||||
val resolvedDependencies by lazy {
|
||||
// don't resolve if no project dependencies on MPP projects are found
|
||||
targetCompileDependenciesConfiguration.resolvedConfiguration.lenientConfiguration.allModuleDependencies.associateBy {
|
||||
targetDependenciesConfiguration.resolvedConfiguration.lenientConfiguration.allModuleDependencies.associateBy {
|
||||
Triple(it.moduleGroup, it.moduleName, it.moduleVersion)
|
||||
}
|
||||
}
|
||||
|
||||
moduleDependencies.map { dependency ->
|
||||
when (dependency) {
|
||||
!is ProjectDependency -> dependency
|
||||
else -> {
|
||||
val dependencyProject = dependency.dependencyProject
|
||||
val dependencyProjectKotlinExtension = dependencyProject.multiplatformExtension
|
||||
?: return@map dependency
|
||||
val resolvedModulesByRootModuleCoordinates = targetDependenciesConfiguration
|
||||
.allDependencies.withType(ModuleDependency::class.java)
|
||||
.associate { dependency ->
|
||||
when (dependency) {
|
||||
is ProjectDependency -> {
|
||||
val dependencyProject = dependency.dependencyProject
|
||||
val dependencyProjectKotlinExtension = dependencyProject.multiplatformExtension
|
||||
?: return@associate dependency to dependency
|
||||
|
||||
if (dependencyProjectKotlinExtension.isGradleMetadataAvailable)
|
||||
return@map dependency
|
||||
val resolved = resolvedDependencies[Triple(dependency.group, dependency.name, dependency.version)]
|
||||
?: return@associate dependency to dependency
|
||||
|
||||
val resolved = resolvedCompileDependencies[Triple(dependency.group, dependency.name, dependency.version)]
|
||||
?: return@map dependency
|
||||
|
||||
val resolvedToConfiguration = resolved.configuration
|
||||
|
||||
val dependencyTargetComponent: KotlinTargetComponent = run {
|
||||
dependencyProjectKotlinExtension.targets.forEach { target ->
|
||||
target.components.forEach { component ->
|
||||
if (component.findUsageContext(resolvedToConfiguration) != null)
|
||||
return@run component
|
||||
val resolvedToConfiguration = resolved.configuration
|
||||
val dependencyTargetComponent: KotlinTargetComponent = run {
|
||||
dependencyProjectKotlinExtension.targets.forEach { target ->
|
||||
target.components.forEach { component ->
|
||||
if (component.findUsageContext(resolvedToConfiguration) != null)
|
||||
return@run component
|
||||
}
|
||||
}
|
||||
// Failed to find a matching component:
|
||||
return@associate dependency to dependency
|
||||
}
|
||||
// Failed to find a matching component:
|
||||
return@map dependency
|
||||
|
||||
val targetModulePublication = (dependencyTargetComponent as? KotlinTargetComponentWithPublication)?.publicationDelegate
|
||||
val rootModulePublication = dependencyProjectKotlinExtension.rootSoftwareComponent.publicationDelegate
|
||||
|
||||
// During Gradle POM generation, a project dependency is already written as the root module's coordinates. In the
|
||||
// dependencies mapping, map the root module to the target's module:
|
||||
|
||||
val rootModule = project.dependencies.module(
|
||||
listOf(
|
||||
rootModulePublication?.groupId ?: dependency.group,
|
||||
rootModulePublication?.artifactId ?: dependencyProject.name,
|
||||
rootModulePublication?.version ?: dependency.version
|
||||
).joinToString(":")
|
||||
) as ModuleDependency
|
||||
|
||||
rootModule to project.dependencies.module(
|
||||
listOf(
|
||||
targetModulePublication?.groupId ?: dependency.group,
|
||||
targetModulePublication?.artifactId ?: dependencyTargetComponent.defaultArtifactId,
|
||||
targetModulePublication?.version ?: dependency.version
|
||||
).joinToString(":")
|
||||
) as ModuleDependency
|
||||
}
|
||||
else -> {
|
||||
val resolvedDependency = resolvedDependencies[Triple(dependency.group, dependency.name, dependency.version)]
|
||||
?: return@associate dependency to dependency
|
||||
|
||||
val publicationDelegate = (dependencyTargetComponent as? KotlinTargetComponentWithPublication)?.publicationDelegate
|
||||
if (resolvedDependency.moduleArtifacts.isEmpty() && resolvedDependency.children.size == 1) {
|
||||
// This is a dependency on a module that resolved to another module; map the original dependency to the target module
|
||||
val targetModule = resolvedDependency.children.single()
|
||||
dependency to project.dependencies.module(
|
||||
listOf(
|
||||
targetModule.moduleGroup,
|
||||
targetModule.moduleName,
|
||||
targetModule.moduleVersion
|
||||
).joinToString(":")
|
||||
) as ModuleDependency
|
||||
|
||||
dependencies.module(
|
||||
listOf(
|
||||
publicationDelegate?.groupId ?: dependency.group,
|
||||
publicationDelegate?.artifactId ?: dependencyTargetComponent.defaultArtifactId,
|
||||
publicationDelegate?.version ?: dependency.version
|
||||
).joinToString(":")
|
||||
) as ModuleDependency
|
||||
} else {
|
||||
dependency to dependency
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}.toSet()
|
||||
}.mapKeys { (key, _) -> Triple(key.group, key.name, key.version) }
|
||||
|
||||
return moduleDependencies.associate { dependency ->
|
||||
val key = Triple(dependency.group, dependency.name, dependency.version)
|
||||
val value = resolvedModulesByRootModuleCoordinates[key] ?: dependency
|
||||
dependency to value
|
||||
}
|
||||
}
|
||||
|
||||
internal fun KotlinTargetComponent.findUsageContext(configurationName: String): UsageContext? {
|
||||
|
||||
-8
@@ -95,9 +95,6 @@ abstract class AbstractKotlinTarget(
|
||||
componentName: String,
|
||||
artifactNameAppendix: String
|
||||
): Set<DefaultKotlinUsageContext> {
|
||||
val publishWithKotlinMetadata = (project.kotlinExtension as? KotlinMultiplatformExtension)?.isGradleMetadataAvailable
|
||||
?: true // In non-MPP project, these usage contexts do not get published anyway
|
||||
|
||||
val sourcesJarArtifact = sourcesJarArtifact(producingCompilation, componentName, artifactNameAppendix)
|
||||
|
||||
// Here, `JAVA_API` and `JAVA_RUNTIME_JARS` are used intentionally as Gradle needs this for
|
||||
@@ -111,7 +108,6 @@ abstract class AbstractKotlinTarget(
|
||||
producingCompilation,
|
||||
project.usageByName(usageName),
|
||||
dependenciesConfigurationName,
|
||||
publishWithKotlinMetadata,
|
||||
sourcesJarArtifact
|
||||
)
|
||||
}
|
||||
@@ -295,9 +291,6 @@ open class KotlinAndroidTarget(
|
||||
classifierPrefix = artifactClassifier
|
||||
)
|
||||
|
||||
val publishWithKotlinMetadata = (project.kotlinExtension as? KotlinMultiplatformExtension)?.isGradleMetadataAvailable
|
||||
?: true // In non-MPP project, these usage contexts do not get published anyway
|
||||
|
||||
val variantName = getVariantName(variant)
|
||||
val outputTask = getLibraryOutputTask(variant) ?: return emptySet()
|
||||
val artifact = run {
|
||||
@@ -325,7 +318,6 @@ open class KotlinAndroidTarget(
|
||||
compilation,
|
||||
project.usageByName(usageName),
|
||||
dependencyConfigurationName,
|
||||
publishWithKotlinMetadata,
|
||||
sourcesJarArtifact,
|
||||
overrideConfigurationArtifacts = setOf(artifact)
|
||||
)
|
||||
|
||||
+16
-10
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.ExcludeRule
|
||||
import org.gradle.api.artifacts.ModuleDependency
|
||||
import org.gradle.api.artifacts.ModuleIdentifier
|
||||
@@ -26,30 +27,35 @@ internal interface KotlinTargetComponentWithPublication : KotlinTargetComponent
|
||||
var publicationDelegate: MavenPublication?
|
||||
}
|
||||
|
||||
private interface KotlinTargetComponentWithCoordinatesAndPublication :
|
||||
KotlinTargetComponentWithPublication,
|
||||
ComponentWithCoordinates /* Gradle 4.7+ API, don't use with older versions */
|
||||
{
|
||||
override fun getCoordinates() = object : ModuleVersionIdentifier {
|
||||
private val project get() = target.project
|
||||
|
||||
internal fun getCoordinatesFromPublicationDelegateAndProject(
|
||||
publication: MavenPublication?,
|
||||
project: Project,
|
||||
target: KotlinTarget?
|
||||
): ModuleVersionIdentifier =
|
||||
object : ModuleVersionIdentifier {
|
||||
private val moduleName: String
|
||||
get() =
|
||||
publicationDelegate?.artifactId ?: "${project.name}-${target.name.toLowerCase()}"
|
||||
publication?.artifactId ?: lowerSpinalCaseName(project.name, target?.name)
|
||||
|
||||
private val moduleGroup: String
|
||||
get() =
|
||||
publicationDelegate?.groupId ?: project.group.toString()
|
||||
publication?.groupId ?: project.group.toString()
|
||||
|
||||
override fun getGroup() = moduleGroup
|
||||
override fun getName() = moduleName
|
||||
override fun getVersion() = publicationDelegate?.version ?: project.version.toString()
|
||||
override fun getVersion() = publication?.version ?: project.version.toString()
|
||||
|
||||
override fun getModule(): ModuleIdentifier = object : ModuleIdentifier {
|
||||
override fun getGroup(): String = moduleGroup
|
||||
override fun getName(): String = moduleName
|
||||
}
|
||||
}
|
||||
|
||||
private interface KotlinTargetComponentWithCoordinatesAndPublication :
|
||||
KotlinTargetComponentWithPublication,
|
||||
ComponentWithCoordinates /* Gradle 4.7+ API, don't use with older versions */
|
||||
{
|
||||
override fun getCoordinates() = getCoordinatesFromPublicationDelegateAndProject(publicationDelegate, target.project, target)
|
||||
}
|
||||
|
||||
open class KotlinVariant(
|
||||
|
||||
Reference in New Issue
Block a user