Simplify matching of Kotlin variant name and Gradle configuration name
Earlier, the matching was non-trivial and required the consumer to look through all of the producer's targets to find the Kotlin variant given the name of the configuration that Gradle chose during variant-aware dependency resolution. This is not feasible in composite builds as we can't look into a project model of an included build. To fix this, simplify the matching of the Gradle configuration name and the Kotlin variant name by just using a suffix for the published configurations. Namely, instead of names like `jvm-api`, use the original configuration name `jvmApiElements` for Kotlin variant names. To avoid ambiguity with Gradle configurations (which we might want to customize for publishing, like by altering the attributes or the published artifacts compared to the configuration exposed for inter-project dependencies), create publishing configurations
This commit is contained in:
+5
-5
@@ -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"),
|
||||
|
||||
+3
-3
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-11
@@ -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<KotlinCompilationType : KotlinCompil
|
||||
jarArtifact.type = archiveType
|
||||
|
||||
val apiElementsConfiguration = project.configurations.getByName(target.apiElementsConfigurationName)
|
||||
addJar(apiElementsConfiguration, jarArtifact)
|
||||
// If the target adds its own artifact to this configuration until this happens, don't add another one:
|
||||
addJarIfNoArtifactsPresent(apiElementsConfiguration, jarArtifact)
|
||||
|
||||
if (mainCompilation is KotlinCompilationToRunnableFiles<*>) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
@@ -20,6 +20,14 @@ internal const val COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME = "commonMainMetadata
|
||||
open class KotlinMetadataTarget @Inject constructor(project: Project) :
|
||||
KotlinOnlyTarget<AbstractKotlinCompilation<*>>(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<KotlinTargetComponent> by lazy {
|
||||
if (!project.isKotlinGranularMetadataEnabled)
|
||||
super.kotlinComponents
|
||||
|
||||
+1
-5
@@ -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)
|
||||
|
||||
+4
-12
@@ -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<String, Configuration>()
|
||||
|
||||
val visiblePlatformVariantNames: Set<String?> =
|
||||
@@ -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
|
||||
|
||||
+9
-3
@@ -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<KotlinUsageContext>().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)
|
||||
|
||||
|
||||
+31
-23
@@ -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<out Zip> {
|
||||
val result = super.createArchiveTasks(target)
|
||||
if (!target.project.isKotlinGranularMetadataEnabled)
|
||||
return super.createArchiveTasks(target)
|
||||
|
||||
if (target.project.isKotlinGranularMetadataEnabled) {
|
||||
target.project.locateTask<Jar>(target.artifactsTaskName)!!.configure {
|
||||
if (!target.project.isCompatibilityMetadataVariantEnabled) {
|
||||
it.archiveClassifier.set("commonMain")
|
||||
}
|
||||
it.onlyIf { target.project.isCompatibilityMetadataVariantEnabled }
|
||||
val result = target.project.registerTask<Jar>(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<Jar>(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<Jar>(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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user