Fix JVM maven-publish caching by not capturing state in POM rewriting
In POM rewriting logic, ensure that non-serializable entities are
accessed from within project.provider { ... } and their evaluation
results are therefore properly serialized.
Issue #KT-43054 Fixed
This commit is contained in:
+27
-3
@@ -18,6 +18,27 @@ class ConfigurationCacheIT : AbstractConfigurationCacheIT() {
|
|||||||
testConfigurationCacheOf(":compileKotlin")
|
testConfigurationCacheOf(":compileKotlin")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testJvmWithMavenPublish() = with(Project("kotlinProject")) {
|
||||||
|
setupWorkingDir()
|
||||||
|
gradleBuildScript().appendText("""
|
||||||
|
apply plugin: "maven-publish"
|
||||||
|
group = "com.example"
|
||||||
|
version = "1.0"
|
||||||
|
publishing.repositories {
|
||||||
|
maven {
|
||||||
|
url = "${'$'}buildDir/repo"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
publishing.publications {
|
||||||
|
maven(MavenPublication) {
|
||||||
|
from(components["java"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent())
|
||||||
|
testConfigurationCacheOf(":publishMavenPublicationToMavenRepository", checkUpToDateOnRebuild = false)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testIncrementalKaptProject() = with(Project("kaptIncrementalCompilationProject")) {
|
fun testIncrementalKaptProject() = with(Project("kaptIncrementalCompilationProject")) {
|
||||||
setupIncrementalAptProject("AGGREGATING")
|
setupIncrementalAptProject("AGGREGATING")
|
||||||
@@ -57,6 +78,7 @@ abstract class AbstractConfigurationCacheIT : BaseGradleIT() {
|
|||||||
protected fun Project.testConfigurationCacheOf(
|
protected fun Project.testConfigurationCacheOf(
|
||||||
vararg taskNames: String,
|
vararg taskNames: String,
|
||||||
executedTaskNames: List<String>? = null,
|
executedTaskNames: List<String>? = null,
|
||||||
|
checkUpToDateOnRebuild: Boolean = true,
|
||||||
buildOptions: BuildOptions = defaultBuildOptions()
|
buildOptions: BuildOptions = defaultBuildOptions()
|
||||||
) {
|
) {
|
||||||
// First, run a build that serializes the tasks state for instant execution in further builds
|
// First, run a build that serializes the tasks state for instant execution in further builds
|
||||||
@@ -81,9 +103,11 @@ abstract class AbstractConfigurationCacheIT : BaseGradleIT() {
|
|||||||
assertContains("Reusing configuration cache.")
|
assertContains("Reusing configuration cache.")
|
||||||
}
|
}
|
||||||
|
|
||||||
build(*taskNames, options = buildOptions) {
|
if (checkUpToDateOnRebuild) {
|
||||||
assertSuccessful()
|
build(*taskNames, options = buildOptions) {
|
||||||
assertTasksUpToDate(executedTask)
|
assertSuccessful()
|
||||||
|
assertTasksUpToDate(executedTask)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+22
-9
@@ -22,6 +22,8 @@ import org.gradle.api.plugins.JavaPluginConvention
|
|||||||
import org.gradle.api.plugins.MavenPluginConvention
|
import org.gradle.api.plugins.MavenPluginConvention
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.publish.PublishingExtension
|
import org.gradle.api.publish.PublishingExtension
|
||||||
|
import org.gradle.api.publish.maven.MavenPom
|
||||||
|
import org.gradle.api.artifacts.maven.MavenPom as OldMavenPom
|
||||||
import org.gradle.api.publish.maven.MavenPublication
|
import org.gradle.api.publish.maven.MavenPublication
|
||||||
import org.gradle.api.tasks.*
|
import org.gradle.api.tasks.*
|
||||||
import org.gradle.api.tasks.compile.AbstractCompile
|
import org.gradle.api.tasks.compile.AbstractCompile
|
||||||
@@ -415,19 +417,32 @@ internal abstract class AbstractKotlinPlugin(
|
|||||||
project.components.addAll(target.components)
|
project.components.addAll(target.components)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun rewritePom(pom: MavenPom, rewriter: PomDependenciesRewriter, shouldRewritePom: Provider<Boolean>) {
|
||||||
|
pom.withXml { xml ->
|
||||||
|
if (shouldRewritePom.get())
|
||||||
|
rewriter.rewritePomMppDependenciesToActualTargetModules(xml)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rewritePom(pom: OldMavenPom, rewriter: PomDependenciesRewriter, shouldRewritePom: Provider<Boolean>) {
|
||||||
|
pom.withXml { xml ->
|
||||||
|
if (shouldRewritePom.get())
|
||||||
|
rewriter.rewritePomMppDependenciesToActualTargetModules(xml)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun rewriteMppDependenciesInPom(target: AbstractKotlinTarget) {
|
private fun rewriteMppDependenciesInPom(target: AbstractKotlinTarget) {
|
||||||
val project = target.project
|
val project = target.project
|
||||||
|
|
||||||
fun shouldRewritePoms(): Boolean =
|
val shouldRewritePoms = project.provider {
|
||||||
PropertiesProvider(project).keepMppDependenciesIntactInPoms != true
|
PropertiesProvider(project).keepMppDependenciesIntactInPoms != true
|
||||||
|
}
|
||||||
|
|
||||||
project.pluginManager.withPlugin("maven-publish") {
|
project.pluginManager.withPlugin("maven-publish") {
|
||||||
project.extensions.configure(PublishingExtension::class.java) { publishing ->
|
project.extensions.configure(PublishingExtension::class.java) { publishing ->
|
||||||
|
val pomRewriter = PomDependenciesRewriter(project, target.kotlinComponents.single())
|
||||||
publishing.publications.withType(MavenPublication::class.java).all { publication ->
|
publishing.publications.withType(MavenPublication::class.java).all { publication ->
|
||||||
publication.pom.withXml { xml ->
|
rewritePom(publication.pom, pomRewriter, shouldRewritePoms)
|
||||||
if (shouldRewritePoms())
|
|
||||||
project.rewritePomMppDependenciesToActualTargetModules(xml, target.kotlinComponents.single())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -435,10 +450,8 @@ internal abstract class AbstractKotlinPlugin(
|
|||||||
project.pluginManager.withPlugin("maven") {
|
project.pluginManager.withPlugin("maven") {
|
||||||
project.tasks.withType(Upload::class.java).all { uploadTask ->
|
project.tasks.withType(Upload::class.java).all { uploadTask ->
|
||||||
uploadTask.repositories.withType(MavenResolver::class.java).all { mavenResolver ->
|
uploadTask.repositories.withType(MavenResolver::class.java).all { mavenResolver ->
|
||||||
mavenResolver.pom.withXml { xml ->
|
val pomRewriter = PomDependenciesRewriter(project, target.kotlinComponents.single())
|
||||||
if (shouldRewritePoms())
|
rewritePom(mavenResolver.pom, pomRewriter, shouldRewritePoms)
|
||||||
project.rewritePomMppDependenciesToActualTargetModules(xml, target.kotlinComponents.single())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+40
-21
@@ -13,8 +13,10 @@ import org.gradle.api.attributes.AttributeContainer
|
|||||||
import org.gradle.api.internal.FeaturePreviews
|
import org.gradle.api.internal.FeaturePreviews
|
||||||
import org.gradle.api.internal.plugins.DslObject
|
import org.gradle.api.internal.plugins.DslObject
|
||||||
import org.gradle.api.plugins.JavaBasePlugin
|
import org.gradle.api.plugins.JavaBasePlugin
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.publish.PublicationContainer
|
import org.gradle.api.publish.PublicationContainer
|
||||||
import org.gradle.api.publish.PublishingExtension
|
import org.gradle.api.publish.PublishingExtension
|
||||||
|
import org.gradle.api.publish.maven.MavenPom
|
||||||
import org.gradle.api.publish.maven.MavenPublication
|
import org.gradle.api.publish.maven.MavenPublication
|
||||||
import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal
|
import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal
|
||||||
import org.gradle.api.tasks.SourceTask
|
import org.gradle.api.tasks.SourceTask
|
||||||
@@ -234,6 +236,18 @@ class KotlinMultiplatformPlugin(
|
|||||||
project.components.add(kotlinSoftwareComponent)
|
project.components.add(kotlinSoftwareComponent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun rewritePom(
|
||||||
|
pom: MavenPom,
|
||||||
|
pomRewriter: PomDependenciesRewriter,
|
||||||
|
shouldRewritePomDependencies: Provider<Boolean>,
|
||||||
|
includeOnlySpecifiedDependencies: Provider<Set<ModuleCoordinates>>?
|
||||||
|
) {
|
||||||
|
pom.withXml { xml ->
|
||||||
|
if (shouldRewritePomDependencies.get())
|
||||||
|
pomRewriter.rewritePomMppDependenciesToActualTargetModules(xml, includeOnlySpecifiedDependencies)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun AbstractKotlinTarget.createMavenPublications(publications: PublicationContainer) {
|
private fun AbstractKotlinTarget.createMavenPublications(publications: PublicationContainer) {
|
||||||
components
|
components
|
||||||
.map { gradleComponent -> gradleComponent to kotlinComponents.single { it.name == gradleComponent.name } }
|
.map { gradleComponent -> gradleComponent to kotlinComponents.single { it.name == gradleComponent.name } }
|
||||||
@@ -250,12 +264,16 @@ class KotlinMultiplatformPlugin(
|
|||||||
(this as MavenPublicationInternal).publishWithOriginalFileName()
|
(this as MavenPublicationInternal).publishWithOriginalFileName()
|
||||||
artifactId = kotlinComponent.defaultArtifactId
|
artifactId = kotlinComponent.defaultArtifactId
|
||||||
|
|
||||||
pom.withXml { xml ->
|
val pomRewriter = PomDependenciesRewriter(project, kotlinComponent)
|
||||||
if (PropertiesProvider(project).keepMppDependenciesIntactInPoms != true)
|
val shouldRewritePomDependencies =
|
||||||
project.rewritePomMppDependenciesToActualTargetModules(xml, kotlinComponent) { id ->
|
project.provider { PropertiesProvider(project).keepMppDependenciesIntactInPoms != true }
|
||||||
filterMetadataDependencies(this@createMavenPublications, id)
|
|
||||||
}
|
rewritePom(
|
||||||
}
|
pom,
|
||||||
|
pomRewriter,
|
||||||
|
shouldRewritePomDependencies,
|
||||||
|
dependenciesForPomRewriting(this@createMavenPublications)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
(kotlinComponent as? KotlinTargetComponentWithPublication)?.publicationDelegate = componentPublication
|
(kotlinComponent as? KotlinTargetComponentWithPublication)?.publicationDelegate = componentPublication
|
||||||
@@ -269,23 +287,24 @@ class KotlinMultiplatformPlugin(
|
|||||||
* can't read Gradle module metadata won't resolve a dependency on an MPP to the granular metadata variant and won't then choose the
|
* can't read Gradle module metadata won't resolve a dependency on an MPP to the granular metadata variant and won't then choose the
|
||||||
* right dependencies for each source set, we put only the dependencies of the legacy common variant into the POM, i.e. commonMain API.
|
* right dependencies for each source set, we put only the dependencies of the legacy common variant into the POM, i.e. commonMain API.
|
||||||
*/
|
*/
|
||||||
private fun filterMetadataDependencies(target: AbstractKotlinTarget, groupNameVersion: Triple<String?, String, String?>): Boolean {
|
private fun dependenciesForPomRewriting(target: AbstractKotlinTarget): Provider<Set<ModuleCoordinates>>? =
|
||||||
if (target !is KotlinMetadataTarget || !target.project.isKotlinGranularMetadataEnabled) {
|
if (target !is KotlinMetadataTarget || !target.project.isKotlinGranularMetadataEnabled)
|
||||||
return true
|
null
|
||||||
|
else {
|
||||||
|
val commonMain = target.project.kotlinExtension.sourceSets.findByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
||||||
|
if (commonMain == null)
|
||||||
|
null
|
||||||
|
else
|
||||||
|
target.project.provider {
|
||||||
|
val project = target.project
|
||||||
|
|
||||||
|
// Only the commonMain API dependencies can be published for consumers who can't read Gradle project metadata
|
||||||
|
val commonMainApi = project.sourceSetDependencyConfigurationByScope(commonMain, KotlinDependencyScope.API_SCOPE)
|
||||||
|
val commonMainDependencies = commonMainApi.allDependencies
|
||||||
|
commonMainDependencies.map { ModuleCoordinates(it.group, it.name, it.version) }.toSet()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val (group, name, _) = groupNameVersion
|
|
||||||
|
|
||||||
val project = target.project
|
|
||||||
val commonMain = project.kotlinExtension.sourceSets?.findByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
|
||||||
?: return true
|
|
||||||
|
|
||||||
// Only the commonMain API dependencies can be published for consumers who can't read Gradle project metadata
|
|
||||||
val commonMainApi = project.sourceSetDependencyConfigurationByScope(commonMain, KotlinDependencyScope.API_SCOPE)
|
|
||||||
|
|
||||||
return commonMainApi.allDependencies.any { it.group == group && it.name == name }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun configureSourceSets(project: Project) = with(project.multiplatformExtension) {
|
private fun configureSourceSets(project: Project) = with(project.multiplatformExtension) {
|
||||||
val production = sourceSets.create(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
val production = sourceSets.create(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
||||||
val test = sourceSets.create(KotlinSourceSet.COMMON_TEST_SOURCE_SET_NAME)
|
val test = sourceSets.create(KotlinSourceSet.COMMON_TEST_SOURCE_SET_NAME)
|
||||||
|
|||||||
+95
-84
@@ -14,82 +14,103 @@ import org.gradle.api.artifacts.ProjectDependency
|
|||||||
import org.gradle.api.attributes.Usage
|
import org.gradle.api.attributes.Usage
|
||||||
import org.gradle.api.internal.component.SoftwareComponentInternal
|
import org.gradle.api.internal.component.SoftwareComponentInternal
|
||||||
import org.gradle.api.internal.component.UsageContext
|
import org.gradle.api.internal.component.UsageContext
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationToRunnableFiles
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationToRunnableFiles
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent
|
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||||
|
|
||||||
internal fun Project.rewritePomMppDependenciesToActualTargetModules(
|
internal data class ModuleCoordinates(
|
||||||
pomXml: XmlProvider,
|
val group: String?,
|
||||||
component: KotlinTargetComponent,
|
val name: String,
|
||||||
filterDependencies: (groupNameVersion: Triple<String?, String, String?>) -> Boolean = { true }
|
val version: String?
|
||||||
|
)
|
||||||
|
|
||||||
|
internal class PomDependenciesRewriter(
|
||||||
|
project: Project,
|
||||||
|
|
||||||
|
@field:Transient
|
||||||
|
private val component: KotlinTargetComponent
|
||||||
) {
|
) {
|
||||||
if (component !is SoftwareComponentInternal)
|
|
||||||
return
|
|
||||||
|
|
||||||
val dependenciesNode = (pomXml.asNode().get("dependencies") as NodeList).filterIsInstance<Node>().singleOrNull() ?: return
|
|
||||||
|
|
||||||
val dependencyNodes = (dependenciesNode.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:
|
// Get the dependencies mapping according to the component's UsageContexts:
|
||||||
val resultDependenciesForEachUsageContext =
|
private val dependenciesMappingForEachUsageContext by project.provider {
|
||||||
component.usages.mapNotNull { usage ->
|
(component as SoftwareComponentInternal).usages.mapNotNull { usage ->
|
||||||
if (usage is KotlinUsageContext)
|
if (usage is KotlinUsageContext)
|
||||||
associateDependenciesWithActualModuleDependencies(usage, dependencies)
|
associateDependenciesWithActualModuleDependencies(usage)
|
||||||
// We are only interested in dependencies that are mapped to some other 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) }
|
.filter { (from, to) -> Triple(from.group, from.name, from.version) != Triple(to.group, to.name, to.version) }
|
||||||
else null
|
else null
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Rewrite the dependency nodes according to the mapping:
|
fun rewritePomMppDependenciesToActualTargetModules(
|
||||||
dependencyNodes.forEach { dependencyNode ->
|
pomXml: XmlProvider,
|
||||||
val moduleDependency = dependencyByNode[dependencyNode]
|
includeOnlySpecifiedDependencies: Provider<Set<ModuleCoordinates>>? = null
|
||||||
|
) {
|
||||||
|
if (component !is SoftwareComponentInternal)
|
||||||
|
return
|
||||||
|
|
||||||
if (moduleDependency != null) {
|
val dependenciesNode = (pomXml.asNode().get("dependencies") as NodeList).filterIsInstance<Node>().singleOrNull() ?: return
|
||||||
val groupNameVersion = Triple(moduleDependency.group, moduleDependency.name, moduleDependency.version)
|
|
||||||
if (!filterDependencies(groupNameVersion)) {
|
val dependencyNodes = (dependenciesNode.get("dependency") as? NodeList).orEmpty().filterIsInstance<Node>()
|
||||||
dependenciesNode.remove(dependencyNode)
|
|
||||||
return@forEach
|
val dependencyByNode = mutableMapOf<Node, ModuleCoordinates>()
|
||||||
}
|
|
||||||
|
// 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")
|
||||||
|
?: error("unexpected dependency in POM with no artifact ID: $dependenciesNode")
|
||||||
|
val version = dependencyNode.getSingleChildValueOrNull("version")
|
||||||
|
(ModuleCoordinates(groupId, artifactId, version)).also { dependencyByNode[dependencyNode] = it }
|
||||||
|
}.toSet()
|
||||||
|
|
||||||
|
val resultDependenciesForEachUsageContext = dependencies.associate { key ->
|
||||||
|
val map = dependenciesMappingForEachUsageContext.find { key in it }
|
||||||
|
val value = map?.get(key) ?: key
|
||||||
|
key to value
|
||||||
}
|
}
|
||||||
|
|
||||||
val mapDependencyTo = resultDependenciesForEachUsageContext.find { moduleDependency in it }?.get(moduleDependency)
|
val includeOnlySpecifiedDependenciesSet = includeOnlySpecifiedDependencies?.get()
|
||||||
|
|
||||||
if (mapDependencyTo != null) {
|
// Rewrite the dependency nodes according to the mapping:
|
||||||
|
dependencyNodes.forEach { dependencyNode ->
|
||||||
|
val moduleDependency = dependencyByNode[dependencyNode]
|
||||||
|
|
||||||
fun Node.setChildNodeByName(name: String, value: String?) {
|
if (moduleDependency != null) {
|
||||||
val childNode: Node? = (get(name) as NodeList?)?.firstOrNull() as Node?
|
if (includeOnlySpecifiedDependenciesSet != null && moduleDependency !in includeOnlySpecifiedDependenciesSet) {
|
||||||
if (value != null) {
|
dependenciesNode.remove(dependencyNode)
|
||||||
(childNode ?: appendNode(name)).setValue(value)
|
return@forEach
|
||||||
} else {
|
|
||||||
childNode?.let { remove(it) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyNode.setChildNodeByName("groupId", mapDependencyTo.group)
|
val mapDependencyTo = resultDependenciesForEachUsageContext.get(moduleDependency)
|
||||||
dependencyNode.setChildNodeByName("artifactId", mapDependencyTo.name)
|
|
||||||
dependencyNode.setChildNodeByName("version", mapDependencyTo.version)
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun associateDependenciesWithActualModuleDependencies(
|
private fun associateDependenciesWithActualModuleDependencies(
|
||||||
usageContext: KotlinUsageContext,
|
usageContext: KotlinUsageContext
|
||||||
moduleDependencies: Set<ModuleDependency>
|
): Map<ModuleCoordinates, ModuleCoordinates> {
|
||||||
): Map<ModuleDependency, ModuleDependency> {
|
|
||||||
val compilation = usageContext.compilation
|
val compilation = usageContext.compilation
|
||||||
val project = compilation.target.project
|
val project = compilation.target.project
|
||||||
|
|
||||||
@@ -119,17 +140,19 @@ private fun associateDependenciesWithActualModuleDependencies(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val resolvedModulesByRootModuleCoordinates = targetDependenciesConfiguration
|
return targetDependenciesConfiguration
|
||||||
.allDependencies.withType(ModuleDependency::class.java)
|
.allDependencies.withType(ModuleDependency::class.java)
|
||||||
.associate { dependency ->
|
.associate { dependency ->
|
||||||
|
val coordinates = ModuleCoordinates(dependency.group, dependency.name, dependency.version)
|
||||||
|
val noMapping = coordinates to coordinates
|
||||||
when (dependency) {
|
when (dependency) {
|
||||||
is ProjectDependency -> {
|
is ProjectDependency -> {
|
||||||
val dependencyProject = dependency.dependencyProject
|
val dependencyProject = dependency.dependencyProject
|
||||||
val dependencyProjectKotlinExtension = dependencyProject.multiplatformExtensionOrNull
|
val dependencyProjectKotlinExtension = dependencyProject.multiplatformExtensionOrNull
|
||||||
?: return@associate dependency to dependency
|
?: return@associate noMapping
|
||||||
|
|
||||||
val resolved = resolvedDependencies[Triple(dependency.group, dependency.name, dependency.version)]
|
val resolved = resolvedDependencies[Triple(dependency.group, dependency.name, dependency.version)]
|
||||||
?: return@associate dependency to dependency
|
?: return@associate noMapping
|
||||||
|
|
||||||
val resolvedToConfiguration = resolved.configuration
|
val resolvedToConfiguration = resolved.configuration
|
||||||
val dependencyTargetComponent: KotlinTargetComponent = run {
|
val dependencyTargetComponent: KotlinTargetComponent = run {
|
||||||
@@ -140,7 +163,7 @@ private fun associateDependenciesWithActualModuleDependencies(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Failed to find a matching component:
|
// Failed to find a matching component:
|
||||||
return@associate dependency to dependency
|
return@associate noMapping
|
||||||
}
|
}
|
||||||
|
|
||||||
val targetModulePublication = (dependencyTargetComponent as? KotlinTargetComponentWithPublication)?.publicationDelegate
|
val targetModulePublication = (dependencyTargetComponent as? KotlinTargetComponentWithPublication)?.publicationDelegate
|
||||||
@@ -149,49 +172,37 @@ private fun associateDependenciesWithActualModuleDependencies(
|
|||||||
// During Gradle POM generation, a project dependency is already written as the root module's coordinates. In the
|
// 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:
|
// dependencies mapping, map the root module to the target's module:
|
||||||
|
|
||||||
val rootModule = project.dependencies.module(
|
val rootModule = ModuleCoordinates(
|
||||||
listOf(
|
rootModulePublication?.groupId ?: dependency.group,
|
||||||
rootModulePublication?.groupId ?: dependency.group,
|
rootModulePublication?.artifactId ?: dependencyProject.name,
|
||||||
rootModulePublication?.artifactId ?: dependencyProject.name,
|
rootModulePublication?.version ?: dependency.version
|
||||||
rootModulePublication?.version ?: dependency.version
|
)
|
||||||
).joinToString(":")
|
|
||||||
) as ModuleDependency
|
|
||||||
|
|
||||||
rootModule to project.dependencies.module(
|
rootModule to ModuleCoordinates(
|
||||||
listOf(
|
targetModulePublication?.groupId ?: dependency.group,
|
||||||
targetModulePublication?.groupId ?: dependency.group,
|
targetModulePublication?.artifactId ?: dependencyTargetComponent.defaultArtifactId,
|
||||||
targetModulePublication?.artifactId ?: dependencyTargetComponent.defaultArtifactId,
|
targetModulePublication?.version ?: dependency.version
|
||||||
targetModulePublication?.version ?: dependency.version
|
)
|
||||||
).joinToString(":")
|
|
||||||
) as ModuleDependency
|
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val resolvedDependency = resolvedDependencies[Triple(dependency.group, dependency.name, dependency.version)]
|
val resolvedDependency = resolvedDependencies[Triple(dependency.group, dependency.name, dependency.version)]
|
||||||
?: return@associate dependency to dependency
|
?: return@associate noMapping
|
||||||
|
|
||||||
if (resolvedDependency.moduleArtifacts.isEmpty() && resolvedDependency.children.size == 1) {
|
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
|
// 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()
|
val targetModule = resolvedDependency.children.single()
|
||||||
dependency to project.dependencies.module(
|
coordinates to ModuleCoordinates(
|
||||||
listOf(
|
targetModule.moduleGroup,
|
||||||
targetModule.moduleGroup,
|
targetModule.moduleName,
|
||||||
targetModule.moduleName,
|
targetModule.moduleVersion
|
||||||
targetModule.moduleVersion
|
)
|
||||||
).joinToString(":")
|
|
||||||
) as ModuleDependency
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
dependency to dependency
|
noMapping
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinTargetComponent.findUsageContext(configurationName: String): UsageContext? {
|
private fun KotlinTargetComponent.findUsageContext(configurationName: String): UsageContext? {
|
||||||
|
|||||||
Reference in New Issue
Block a user