From f9c45c30a24f4095b87323b00fb37022f8f94fd9 Mon Sep 17 00:00:00 2001 From: Sergey Igushkin Date: Thu, 10 Jan 2019 22:17:50 +0300 Subject: [PATCH] Always rewrite dependencies in POMs when publishing an MPP (KT-28482) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .../kotlin/gradle/NewMultiplatformIT.kt | 79 +++++++++-- .../dsl/KotlinMultiplatformExtension.kt | 13 +- .../plugin/mpp/KotlinMultiplatformPlugin.kt | 67 ++++++++- .../plugin/mpp/KotlinSoftwareComponent.kt | 134 ++++++++++++------ .../kotlin/gradle/plugin/mpp/kotlinTargets.kt | 8 -- .../gradle/plugin/mpp/kotlinVariants.kt | 26 ++-- 6 files changed, 250 insertions(+), 77 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt index e3361fa0718..f7bb7eef15a 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt @@ -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() { "bar", "42" ) + 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", + "com.external.dependency", + "external-jvm6", + "1.2.3" + ) + + // 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 { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt index fcebc819482..68889457bb3 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/dsl/KotlinMultiplatformExtension.kt @@ -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> @@ -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 = diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt index 32092b35be8..8d39b9606f2 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt @@ -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().flatMap { + (it.get("dependency") as? NodeList).orEmpty() + }.filterIsInstance() + + val dependencyByNode = mutableMapOf() + + // 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) + } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt index 95df74a4048..7fc86818b5b 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt @@ -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 + protected val kotlinTargets: Iterable ) : SoftwareComponentInternal, ComponentWithVariants { override fun getUsages(): Set = 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) : + 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? = null ) : KotlinUsageContext { @@ -65,10 +78,7 @@ class DefaultKotlinUsageContext( get() = project.configurations.getByName(dependencyConfigurationName) override fun getDependencies(): MutableSet = - 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 = configuration.incoming.dependencyConstraints @@ -86,14 +96,14 @@ class DefaultKotlinUsageContext( override fun getGlobalExcludes(): Set = emptySet() } -private fun rewriteMppDependenciesToTargetModuleDependencies( +internal fun rewriteDependenciesToActualModuleDependencies( usageContext: KotlinUsageContext, - fromConfiguration: Configuration -): Set = with(usageContext.compilation.target.project) { + moduleDependencies: Set +): Map { 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? { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt index a22d179c3a9..32d43821f90 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt @@ -95,9 +95,6 @@ abstract class AbstractKotlinTarget( componentName: String, artifactNameAppendix: String ): Set { - 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) ) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt index 8cd91f9e830..8387de3caae 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinVariants.kt @@ -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(