diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/HierarchicalMppIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/HierarchicalMppIT.kt index 4d52b3f8a65..182e42a5d24 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/HierarchicalMppIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/HierarchicalMppIT.kt @@ -452,11 +452,11 @@ class HierarchicalMppIT : BaseGradleIT() { val jsSourceSets = setOf("commonMain", "jvmAndJsMain", "linuxAndJsMain") return KotlinProjectStructureMetadata( sourceSetNamesByVariantName = mapOf( - "js-api" to jsSourceSets, - "js-runtime" to jsSourceSets, - "jvm-api" to jvmSourceSets, - "jvm-runtime" to jvmSourceSets, - "linuxX64-api" to setOf("commonMain", "linuxAndJsMain") + "jsApiElements" to jsSourceSets, + "jsRuntimeElements" to jsSourceSets, + "jvmApiElements" to jvmSourceSets, + "jvmRuntimeElements" to jvmSourceSets, + "linuxX64ApiElements" to setOf("commonMain", "linuxAndJsMain") ), sourceSetsDependsOnRelation = mapOf( "jvmAndJsMain" to setOf("commonMain"), 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 14010fca230..0a83177d40f 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 @@ -978,9 +978,9 @@ class NewMultiplatformIT : BaseGradleIT() { // but check that the module metadata contains all variants: val gradleModuleMetadata = projectDir.resolve("repo/com/example/sample-lib/1.0/sample-lib-1.0.module").readText() - assertTrue(""""name": "linux64-api"""" in gradleModuleMetadata) - assertTrue(""""name": "mingw64-api"""" in gradleModuleMetadata) - assertTrue(""""name": "macos64-api"""" in gradleModuleMetadata) + assertTrue(""""name": "linux64ApiElements-published"""" in gradleModuleMetadata) + assertTrue(""""name": "mingw64ApiElements-published"""" in gradleModuleMetadata) + assertTrue(""""name": "macos64ApiElements-published"""" in gradleModuleMetadata) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt index fa35af78736..3a0b61664d7 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.gradle.plugin import org.gradle.api.DefaultTask import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.Project -import org.gradle.api.Task import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.Dependency import org.gradle.api.artifacts.PublishArtifact @@ -34,7 +33,6 @@ import org.jetbrains.kotlin.gradle.targets.js.KotlinJsCompilerAttribute import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask -import org.jetbrains.kotlin.gradle.tasks.locateTask import org.jetbrains.kotlin.gradle.tasks.registerTask import org.jetbrains.kotlin.gradle.tasks.withType import org.jetbrains.kotlin.gradle.utils.COMPILE @@ -406,25 +404,27 @@ abstract class KotlinOnlyTargetConfigurator) { val runtimeConfiguration = project.configurations.getByName(mainCompilation.deprecatedRuntimeConfigurationName) val runtimeElementsConfiguration = project.configurations.getByName(target.runtimeElementsConfigurationName) - addJar(runtimeConfiguration, jarArtifact) - addJar(runtimeElementsConfiguration, jarArtifact) - // TODO Check Gradle's special split into variants for classes & resources -- do we need that too? + addJarIfNoArtifactsPresent(runtimeConfiguration, jarArtifact) + addJarIfNoArtifactsPresent(runtimeElementsConfiguration, jarArtifact) } } } } - private fun addJar(configuration: Configuration, jarArtifact: PublishArtifact) { - val publications = configuration.outgoing + private fun addJarIfNoArtifactsPresent(configuration: Configuration, jarArtifact: PublishArtifact) { + if (configuration.artifacts.isEmpty()) { + val publications = configuration.outgoing - // Configure an implicit variant - publications.artifacts.add(jarArtifact) - publications.attributes.attribute(ArtifactAttributes.ARTIFACT_FORMAT, archiveType) + // Configure an implicit variant + publications.artifacts.add(jarArtifact) + publications.attributes.attribute(ArtifactAttributes.ARTIFACT_FORMAT, archiveType) + } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataTarget.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataTarget.kt index 8ed308de305..445b12bd541 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataTarget.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMetadataTarget.kt @@ -20,6 +20,14 @@ internal const val COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME = "commonMainMetadata open class KotlinMetadataTarget @Inject constructor(project: Project) : KotlinOnlyTarget>(project, KotlinPlatformType.common) { + override val artifactsTaskName: String + // The IDE import looks at this task name to determine the artifact and register the path to the artifact; + // in HMPP, since the project resolves to the all-metadata JAR, the IDE import needs to work with that JAR, too + get() = if (project.isKotlinGranularMetadataEnabled) KotlinMetadataTargetConfigurator.ALL_METADATA_JAR_NAME else super.artifactsTaskName + + internal val legacyArtifactsTaskName: String + get() = super.artifactsTaskName + override val kotlinComponents: Set by lazy { if (!project.isKotlinGranularMetadataEnabled) super.kotlinComponents 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 48c3b039a41..fe40398b5af 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 @@ -72,11 +72,7 @@ class DefaultKotlinUsageContext( override fun getUsage(): Usage = usage - override fun getName(): String = kotlinTarget.targetName + when (dependencyConfigurationName) { - kotlinTarget.apiElementsConfigurationName -> "-api" - kotlinTarget.runtimeElementsConfigurationName -> "-runtime" - else -> "-$dependencyConfigurationName" - } + override fun getName(): String = dependencyConfigurationName private val configuration: Configuration get() = project.configurations.getByName(dependencyConfigurationName) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt index 05f11d3b71c..9ec71cfd519 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/SourceSetVisibilityProvider.kt @@ -13,7 +13,6 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationToRunnableFiles import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope -import org.jetbrains.kotlin.gradle.targets.metadata.getPublishedPlatformCompilations import java.io.File internal data class SourceSetVisibilityResult( @@ -59,16 +58,6 @@ internal class SourceSetVisibilityProvider( val mppModuleIdentifier = ModuleIds.fromComponent(project, resolvedRootMppDependency ?: resolvedMetadataDependency) - /** - * When Gradle resolves a project dependency, as opposed to an external dependency, the variant name it returns in the resolution - * results is the name of the configuration that is chosen during variant-aware resolution, not the actual name of the variant that - * is written to the Gradle module metadata and the Kotlin project structure metadata. To fix this, get the published Kotlin - * variants of the dependency project and find among them the one that owns the configuration by the given name. - */ - val projectPublishedCompilations = resolvedToOtherProject?.let(::getPublishedPlatformCompilations)?.keys - fun platformVariantName(resolvedToVariantName: String): String = - projectPublishedCompilations?.first { it.dependencyConfigurationName == resolvedToVariantName }?.name ?: resolvedToVariantName - val firstConfigurationByVariant = mutableMapOf() val visiblePlatformVariantNames: Set = @@ -81,7 +70,7 @@ internal class SourceSetVisibilityProvider( } .mapTo(mutableSetOf()) { configuration -> val resolvedVariant = resolvedVariantsProvider.getResolvedVariantName(mppModuleIdentifier, configuration) - ?.let { platformVariantName(it) } + ?.let { kotlinVariantNameFromPublishedVariantName(it) } ?: return@mapTo null firstConfigurationByVariant.putIfAbsent(resolvedVariant, configuration) @@ -135,6 +124,9 @@ internal class SourceSetVisibilityProvider( } } +private fun kotlinVariantNameFromPublishedVariantName(resolvedToVariantName: String): String = + originalVariantNameFromPublished(resolvedToVariantName) ?: resolvedToVariantName + private fun Project.resolvableConfigurationFromCompilationByScope( compilation: KotlinCompilation<*>, scope: KotlinDependencyScope 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 43d5e1ef66c..47d0ea3d890 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 @@ -21,7 +21,6 @@ import org.gradle.api.component.SoftwareComponentFactory import org.gradle.api.internal.component.SoftwareComponentInternal import org.gradle.api.internal.component.UsageContext import org.gradle.api.internal.project.ProjectInternal -import org.gradle.api.provider.Provider import org.gradle.api.publish.maven.MavenPublication import org.gradle.util.ConfigureUtil import org.gradle.util.WrapUtil @@ -95,8 +94,9 @@ abstract class AbstractKotlinTarget( project.whenEvaluated { (kotlinVariant as SoftwareComponentInternal).usages.filterIsInstance().forEach { kotlinUsageContext -> - val configuration = project.configurations.findByName(kotlinUsageContext.name) - ?: project.configurations.create(kotlinUsageContext.name).also { configuration -> + val publishedConfigurationName = publishedConfigurationName(kotlinUsageContext.name) + val configuration = project.configurations.findByName(publishedConfigurationName) + ?: project.configurations.create(publishedConfigurationName).also { configuration -> configuration.isCanBeConsumed = false configuration.isCanBeResolved = false configuration.extendsFrom(project.configurations.getByName(kotlinUsageContext.dependencyConfigurationName)) @@ -219,6 +219,12 @@ abstract class AbstractKotlinTarget( internal set } +private val publishedConfigurationNameSuffix = "-published" + +internal fun publishedConfigurationName(originalVariantName: String) = originalVariantName + publishedConfigurationNameSuffix +internal fun originalVariantNameFromPublished(publishedConfigurationName: String): String? = + publishedConfigurationName.takeIf { it.endsWith(publishedConfigurationNameSuffix) }?.removeSuffix(publishedConfigurationNameSuffix) + internal fun KotlinTarget.disambiguateName(simpleName: String) = lowerCamelCaseName(targetName, simpleName) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt index 7dd98daadc3..f9764604578 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/metadata/KotlinMetadataTargetConfigurator.kt @@ -83,8 +83,13 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) : setupDependencyTransformationForCommonSourceSets(target) - target.project.configurations.getByName(target.apiElementsConfigurationName).attributes - .attribute(USAGE_ATTRIBUTE, target.project.usageByName(KotlinUsages.KOTLIN_METADATA)) + target.project.configurations.getByName(target.apiElementsConfigurationName).run { + attributes.attribute(USAGE_ATTRIBUTE, target.project.usageByName(KotlinUsages.KOTLIN_METADATA)) + /** Note: to add this artifact here is enough to avoid duplicate artifacts in this configuration: the default artifact + * won't be added (later) if there's already an artifact in the configuration, see + * [KotlinOnlyTargetConfigurator.configureArchivesAndComponent] */ + target.project.artifacts.add(target.apiElementsConfigurationName, allMetadataJar) + } if (target.project.isCompatibilityMetadataVariantEnabled) { createCommonMainElementsConfiguration(target) @@ -126,30 +131,33 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) : } override fun createArchiveTasks(target: KotlinMetadataTarget): TaskProvider { - val result = super.createArchiveTasks(target) + if (!target.project.isKotlinGranularMetadataEnabled) + return super.createArchiveTasks(target) - if (target.project.isKotlinGranularMetadataEnabled) { - target.project.locateTask(target.artifactsTaskName)!!.configure { - if (!target.project.isCompatibilityMetadataVariantEnabled) { - it.archiveClassifier.set("commonMain") - } - it.onlyIf { target.project.isCompatibilityMetadataVariantEnabled } + val result = target.project.registerTask(target.artifactsTaskName) { + it.group = BasePlugin.BUILD_GROUP + /** The content is added to this JAR in [KotlinMetadataTargetConfigurator.configureTarget]. */ + } + + result.configure { allMetadataJar -> + allMetadataJar.description = "Assembles a jar archive containing the metadata for all Kotlin source sets." + allMetadataJar.group = BasePlugin.BUILD_GROUP + + allMetadataJar.archiveAppendix.set(target.name.toLowerCase()) + + if (target.project.isCompatibilityMetadataVariantEnabled) { + allMetadataJar.archiveClassifier.set("all") } + } - /** This JAR is created in addition to the main one, published with a classifier, but is by default used - * for project dependencies (as the Kotlin Granular metadata is enabled across all projects in a build, this is OK). - * See also [KotlinMetadataTarget.kotlinComponents] - */ - target.project.registerTask(ALL_METADATA_JAR_NAME) { allMetadataJar -> - allMetadataJar.description = "Assembles a jar archive containing the metadata for all Kotlin source sets." - allMetadataJar.group = BasePlugin.BUILD_GROUP - - allMetadataJar.archiveAppendix.set(target.name.toLowerCase()) - - if (target.project.isCompatibilityMetadataVariantEnabled) { - allMetadataJar.archiveClassifier.set("all") - } + val legacyJar = target.project.registerTask(target.legacyArtifactsTaskName) + legacyJar.configure { + it.description = "Assembles an archive containing the Kotin metadata of the commonMain source set." + if (!target.project.isCompatibilityMetadataVariantEnabled) { + it.archiveClassifier.set("commonMain") } + it.onlyIf { target.project.isCompatibilityMetadataVariantEnabled } + it.from(target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME).output.allOutputs) } return result @@ -499,7 +507,7 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) : ) extendsFrom(commonMainApiConfiguration) - project.artifacts.add(name, project.tasks.getByName(target.artifactsTaskName)) + project.artifacts.add(name, project.tasks.getByName(target.legacyArtifactsTaskName)) } }