[Gradle] ExternalKotlinTargetComponent: Implement 'usages' as 'KotlinUsageContext'

... to support multiplatform publication components as
re-writing pom dependencies and project structure metadata

KT-60159
This commit is contained in:
Sebastian Sellmair
2023-08-03 12:10:23 +02:00
committed by Space Team
parent 93f8e21e9e
commit 3d593f0ee9
13 changed files with 217 additions and 109 deletions
@@ -8,24 +8,17 @@ import org.gradle.api.Action
import org.gradle.api.DomainObjectSet import org.gradle.api.DomainObjectSet
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.artifacts.ConfigurablePublishArtifact import org.gradle.api.artifacts.ConfigurablePublishArtifact
import org.gradle.api.attributes.* import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.component.ComponentWithCoordinates
import org.gradle.api.component.ComponentWithVariants
import org.gradle.api.component.SoftwareComponent
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.publish.maven.MavenPublication import org.gradle.api.publish.maven.MavenPublication
import org.jetbrains.kotlin.gradle.DeprecatedTargetPresetApi
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.PRESETS_API_IS_DEPRECATED_MESSAGE import org.jetbrains.kotlin.gradle.PRESETS_API_IS_DEPRECATED_MESSAGE
import org.jetbrains.kotlin.gradle.DeprecatedTargetPresetApi
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsageContext.MavenScope.* import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsageContext.MavenScope.COMPILE
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsageContext.MavenScope.RUNTIME
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.tooling.core.MutableExtras import org.jetbrains.kotlin.tooling.core.MutableExtras
import org.jetbrains.kotlin.tooling.core.mutableExtrasOf import org.jetbrains.kotlin.tooling.core.mutableExtrasOf
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
@@ -34,7 +27,7 @@ import org.jetbrains.kotlin.utils.addIfNotNull
internal const val PRIMARY_SINGLE_COMPONENT_NAME = "kotlin" internal const val PRIMARY_SINGLE_COMPONENT_NAME = "kotlin"
abstract class AbstractKotlinTarget( abstract class AbstractKotlinTarget(
final override val project: Project final override val project: Project,
) : InternalKotlinTarget { ) : InternalKotlinTarget {
final override val extras: MutableExtras = mutableExtrasOf() final override val extras: MutableExtras = mutableExtrasOf()
@@ -96,8 +89,13 @@ abstract class AbstractKotlinTarget(
setOf(result) setOf(result)
} }
override val components: Set<SoftwareComponent> by lazy {
project.buildAdhocComponentsFromKotlinVariants(kotlinComponents) /**
* Returns, potentially not configured (e.g. without some usages), Gradle SoftwareComponent's for this target
* For final version of components use [awaitComponents]
*/
override val components: Set<KotlinTargetSoftwareComponent> by lazy {
kotlinComponents.map { kotlinComponent -> KotlinTargetSoftwareComponent(this, kotlinComponent) }.toSet()
} }
protected open fun createKotlinVariant( protected open fun createKotlinVariant(
@@ -190,69 +188,6 @@ abstract class AbstractKotlinTarget(
internal set 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) = internal fun KotlinTarget.disambiguateName(simpleName: String) =
lowerCamelCaseName(targetName, simpleName) lowerCamelCaseName(targetName, simpleName)
internal fun javaApiUsageForMavenScoping() = "java-api-jars"
internal fun Project.buildAdhocComponentsFromKotlinVariants(kotlinVariants: Set<KotlinTargetComponent>): Set<SoftwareComponent> {
val softwareComponentFactoryClass = SoftwareComponentFactory::class.java
// TODO replace internal API access with injection (not possible until we have this class on the compile classpath)
val softwareComponentFactory = (project as ProjectInternal).services.get(softwareComponentFactoryClass)
return kotlinVariants.map { kotlinVariant ->
val adhocVariant = softwareComponentFactory.adhoc(kotlinVariant.name)
project.launchInStage(KotlinPluginLifecycle.Stage.AfterFinaliseCompilations) {
(kotlinVariant as SoftwareComponentInternal).usages.filterIsInstance<KotlinUsageContext>().forEach { kotlinUsageContext ->
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))
configuration.artifacts.addAll(kotlinUsageContext.artifacts)
val attributes = kotlinUsageContext.attributes
attributes.keySet().forEach {
// capture type parameter T
fun <T> copyAttribute(key: Attribute<T>, from: AttributeContainer, to: AttributeContainer) {
to.attribute(key, from.getAttribute(key)!!)
}
copyAttribute(it, attributes, configuration.attributes)
}
}
adhocVariant.addVariantsFromConfiguration(configuration) { configurationVariantDetails ->
val mavenScope = kotlinUsageContext.mavenScope
if (mavenScope != null) {
val mavenScopeString = when (mavenScope) {
COMPILE -> "compile"
RUNTIME -> "runtime"
}
configurationVariantDetails.mapToMavenScope(mavenScopeString)
}
}
}
}
adhocVariant as SoftwareComponent
object : ComponentWithVariants, ComponentWithCoordinates, SoftwareComponentInternal {
override fun getCoordinates() =
(kotlinVariant as? ComponentWithCoordinates)?.coordinates ?: error("kotlinVariant is not ComponentWithCoordinates")
override fun getVariants(): Set<SoftwareComponent> =
(kotlinVariant as? KotlinVariantWithMetadataVariant)?.variants.orEmpty()
override fun getName(): String = adhocVariant.name
override fun getUsages(): MutableSet<out UsageContext> = (adhocVariant as SoftwareComponentInternal).usages
}
}.toSet()
}
@@ -6,6 +6,8 @@
package org.jetbrains.kotlin.gradle.plugin.mpp package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.publish.maven.MavenPublication
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent
import org.jetbrains.kotlin.tooling.core.HasMutableExtras import org.jetbrains.kotlin.tooling.core.HasMutableExtras
@@ -13,6 +15,9 @@ import org.jetbrains.kotlin.tooling.core.HasMutableExtras
internal interface InternalKotlinTarget : KotlinTarget, HasMutableExtras { internal interface InternalKotlinTarget : KotlinTarget, HasMutableExtras {
var isSourcesPublishable: Boolean var isSourcesPublishable: Boolean
val kotlinComponents: Set<KotlinTargetComponent> val kotlinComponents: Set<KotlinTargetComponent>
@InternalKotlinGradlePluginApi
override val components: Set<KotlinTargetSoftwareComponent>
fun onPublicationCreated(publication: MavenPublication) fun onPublicationCreated(publication: MavenPublication)
} }
@@ -0,0 +1,21 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.internal.component.SoftwareComponentInternal
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent
/**
* Enforced 'internal' common supertype for all [KotlinTargetComponent] implementations.
*/
@InternalKotlinGradlePluginApi
abstract class InternalKotlinTargetComponent : KotlinTargetComponent, SoftwareComponentInternal {
abstract override fun getUsages(): Set<KotlinUsageContext>
}
internal val KotlinTargetComponent.internal: InternalKotlinTargetComponent
get() = this as InternalKotlinTargetComponent
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.component.ComponentWithCoordinates
import org.gradle.api.component.ComponentWithVariants
import org.gradle.api.internal.component.SoftwareComponentInternal
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinTargetSoftwareComponent
/**
* Common supertype for
* - [KotlinTargetSoftwareComponentImpl]: internal targets
* - [ExternalKotlinTargetSoftwareComponent]: external targets
*/
@InternalKotlinGradlePluginApi
abstract class KotlinTargetSoftwareComponent : ComponentWithVariants, ComponentWithCoordinates, SoftwareComponentInternal
@@ -0,0 +1,86 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project
import org.gradle.api.component.AdhocComponentWithVariants
import org.gradle.api.component.ComponentWithCoordinates
import org.gradle.api.component.SoftwareComponent
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.jetbrains.kotlin.gradle.plugin.KotlinPluginLifecycle
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent
import org.jetbrains.kotlin.gradle.plugin.launchInStage
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.copyAttributes
import org.jetbrains.kotlin.tooling.core.UnsafeApi
internal fun KotlinTargetSoftwareComponent(
target: AbstractKotlinTarget,
kotlinComponent: KotlinTargetComponent,
): KotlinTargetSoftwareComponent {
val softwareComponentFactory = (target.project as ProjectInternal).services.get(SoftwareComponentFactory::class.java)
val adhocVariant = softwareComponentFactory.adhoc(kotlinComponent.name)
/* Launch configuration */
target.project.launchInStage(KotlinPluginLifecycle.Stage.AfterFinaliseCompilations) {
kotlinComponent.internal.usages.forEach { kotlinUsageContext ->
/* Explicitly typing 'Project' to avoid smart cast from 'target.project as ProjectInternal' */
val project: Project = target.project
val publishedConfigurationName = publishedConfigurationName(kotlinUsageContext.name)
val configuration = project.configurations.findByName(publishedConfigurationName)
?: project.configurations.create(publishedConfigurationName).also { publishedConfiguration ->
publishedConfiguration.isCanBeConsumed = false
publishedConfiguration.isCanBeResolved = false
publishedConfiguration.extendsFrom(project.configurations.getByName(kotlinUsageContext.dependencyConfigurationName))
publishedConfiguration.artifacts.addAll(kotlinUsageContext.artifacts)
copyAttributes(from = kotlinUsageContext.attributes, to = publishedConfiguration.attributes)
}
adhocVariant.addVariantsFromConfiguration(configuration) { configurationVariantDetails ->
val mavenScope = kotlinUsageContext.mavenScope
if (mavenScope != null) {
val mavenScopeString = when (mavenScope) {
KotlinUsageContext.MavenScope.COMPILE -> "compile"
KotlinUsageContext.MavenScope.RUNTIME -> "runtime"
}
configurationVariantDetails.mapToMavenScope(mavenScopeString)
}
}
}
}
@OptIn(UnsafeApi::class)
return KotlinTargetSoftwareComponentImpl(adhocVariant, kotlinComponent)
}
/* Smaller Utils functions */
private val publishedConfigurationNameSuffix = "-published"
internal fun originalVariantNameFromPublished(publishedConfigurationName: String): String? =
publishedConfigurationName.takeIf { it.endsWith(publishedConfigurationNameSuffix) }?.removeSuffix(publishedConfigurationNameSuffix)
internal fun publishedConfigurationName(originalVariantName: String) = originalVariantName + publishedConfigurationNameSuffix
/* KotlinTargetSoftwareComponent Implementation */
internal class KotlinTargetSoftwareComponentImpl @UnsafeApi constructor(
private val adhocComponent: AdhocComponentWithVariants,
private val kotlinComponent: KotlinTargetComponent,
) : KotlinTargetSoftwareComponent() {
override fun getCoordinates() =
(kotlinComponent as? ComponentWithCoordinates)?.coordinates ?: error("kotlinComponent is not ComponentWithCoordinates")
override fun getVariants(): Set<SoftwareComponent> =
(kotlinComponent as? KotlinVariantWithMetadataVariant)?.variants.orEmpty()
override fun getName(): String = adhocComponent.name
override fun getUsages(): MutableSet<out UsageContext> = (adhocComponent as SoftwareComponentInternal).usages
}
@@ -10,16 +10,17 @@ import org.gradle.api.artifacts.PublishArtifact
import org.gradle.api.component.ComponentWithCoordinates import org.gradle.api.component.ComponentWithCoordinates
import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.publish.maven.MavenPublication
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinTargetComponentWithPublication import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsageContext.MavenScope.COMPILE
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsageContext.MavenScope.RUNTIME
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinTargetComponent.TargetProvider import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinTargetComponent.TargetProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.getCoordinatesFromPublicationDelegateAndProject
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
internal class ExternalKotlinTargetComponent( internal class ExternalKotlinTargetComponent(
val targetProvider: TargetProvider val targetProvider: TargetProvider,
) : KotlinTargetComponentWithPublication, ComponentWithCoordinates { ) : InternalKotlinTargetComponent(), KotlinTargetComponentWithPublication, ComponentWithCoordinates {
/* /*
Target creation requires this component. We will provide the target once it is required Target creation requires this component. We will provide the target once it is required
@@ -37,7 +38,7 @@ internal class ExternalKotlinTargetComponent(
/* Required for getting correct coordinates */ /* Required for getting correct coordinates */
override var publicationDelegate: MavenPublication? = null override var publicationDelegate: MavenPublication? = null
override val target: KotlinTarget by lazy { targetProvider() } override val target: DecoratedExternalKotlinTarget by lazy { targetProvider() }
override val publishable: Boolean override val publishable: Boolean
get() = target.publishable get() = target.publishable
@@ -60,4 +61,23 @@ internal class ExternalKotlinTargetComponent(
override fun getCoordinates(): ModuleVersionIdentifier = override fun getCoordinates(): ModuleVersionIdentifier =
getCoordinatesFromPublicationDelegateAndProject(publicationDelegate, target.project, null) getCoordinatesFromPublicationDelegateAndProject(publicationDelegate, target.project, null)
private val _usages: Set<DefaultKotlinUsageContext> by lazy {
val compilation = target.compilations.findByName(KotlinCompilation.MAIN_COMPILATION_NAME)
?: error("Missing conventional '${KotlinCompilation.MAIN_COMPILATION_NAME}' compilation in '$target'")
setOf(
DefaultKotlinUsageContext(compilation, COMPILE, target.apiElementsPublishedConfiguration.name),
DefaultKotlinUsageContext(compilation, RUNTIME, target.runtimeElementsPublishedConfiguration.name),
DefaultKotlinUsageContext(
compilation = compilation,
mavenScope = null,
dependencyConfigurationName = target.sourcesElementsPublishedConfiguration.name,
includeIntoProjectStructureMetadata = false,
publishOnlyIf = { target.isSourcesPublishable }
)
)
}
override fun getUsages(): Set<KotlinUsageContext> = _usages.filter { it.publishOnlyIf.predicate() }.toSet()
} }
@@ -1,13 +1,11 @@
/* /*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
package org.jetbrains.kotlin.gradle.plugin.mpp.external package org.jetbrains.kotlin.gradle.plugin.mpp.external
import org.gradle.api.artifacts.ModuleVersionIdentifier import org.gradle.api.artifacts.ModuleVersionIdentifier
import org.gradle.api.component.ComponentWithCoordinates
import org.gradle.api.component.ComponentWithVariants
import org.gradle.api.component.SoftwareComponent import org.gradle.api.component.SoftwareComponent
import org.gradle.api.component.SoftwareComponentFactory import org.gradle.api.component.SoftwareComponentFactory
import org.gradle.api.internal.component.SoftwareComponentInternal import org.gradle.api.internal.component.SoftwareComponentInternal
@@ -15,8 +13,11 @@ import org.gradle.api.internal.component.UsageContext
import org.gradle.api.internal.project.ProjectInternal import org.gradle.api.internal.project.ProjectInternal
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.launch
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinTargetSoftwareComponent
import org.jetbrains.kotlin.tooling.core.UnsafeApi import org.jetbrains.kotlin.tooling.core.UnsafeApi
internal fun ExternalKotlinTargetSoftwareComponent( internal fun ExternalKotlinTargetSoftwareComponent(
target: ExternalKotlinTargetImpl, target: ExternalKotlinTargetImpl,
): ExternalKotlinTargetSoftwareComponent { ): ExternalKotlinTargetSoftwareComponent {
@@ -39,7 +40,7 @@ internal fun ExternalKotlinTargetSoftwareComponent(
return ExternalKotlinTargetSoftwareComponent( return ExternalKotlinTargetSoftwareComponent(
target.project.multiplatformExtension, target.project.multiplatformExtension,
adhocSoftwareComponent as SoftwareComponentInternal, adhocSoftwareComponent as SoftwareComponentInternal,
target.kotlinTargetComponent target.kotlinTargetComponent,
) )
} }
@@ -47,7 +48,8 @@ internal class ExternalKotlinTargetSoftwareComponent @UnsafeApi constructor(
private val multiplatformExtension: KotlinMultiplatformExtension, private val multiplatformExtension: KotlinMultiplatformExtension,
private val adhocSoftwareComponent: SoftwareComponentInternal, private val adhocSoftwareComponent: SoftwareComponentInternal,
private val kotlinTargetComponent: ExternalKotlinTargetComponent, private val kotlinTargetComponent: ExternalKotlinTargetComponent,
) : ComponentWithCoordinates, ComponentWithVariants, SoftwareComponentInternal { ) : KotlinTargetSoftwareComponent() {
override fun getName(): String = adhocSoftwareComponent.name override fun getName(): String = adhocSoftwareComponent.name
override fun getUsages(): Set<UsageContext> = adhocSoftwareComponent.usages override fun getUsages(): Set<UsageContext> = adhocSoftwareComponent.usages
override fun getVariants(): Set<SoftwareComponent> = multiplatformExtension.metadata().components override fun getVariants(): Set<SoftwareComponent> = multiplatformExtension.metadata().components
@@ -59,7 +59,7 @@ private interface KotlinTargetComponentWithCoordinatesAndPublication :
open class KotlinVariant( open class KotlinVariant(
val producingCompilation: KotlinCompilation<*>, val producingCompilation: KotlinCompilation<*>,
private val usages: Set<DefaultKotlinUsageContext> private val usages: Set<DefaultKotlinUsageContext>
) : KotlinTargetComponentWithPublication, SoftwareComponentInternal { ) : InternalKotlinTargetComponent(), KotlinTargetComponentWithPublication {
var componentName: String? = null var componentName: String? = null
var artifactTargetName: String = target.targetName var artifactTargetName: String = target.targetName
@@ -112,7 +112,7 @@ class JointAndroidKotlinTargetComponent(
override val target: KotlinAndroidTarget, override val target: KotlinAndroidTarget,
private val nestedVariants: Set<KotlinVariant>, private val nestedVariants: Set<KotlinVariant>,
val flavorNames: List<String> val flavorNames: List<String>
) : KotlinTargetComponentWithCoordinatesAndPublication, SoftwareComponentInternal { ) : InternalKotlinTargetComponent(), KotlinTargetComponentWithCoordinatesAndPublication {
override fun getUsages(): Set<KotlinUsageContext> = nestedVariants.filter { it.publishable }.flatMap { it.usages }.toSet() override fun getUsages(): Set<KotlinUsageContext> = nestedVariants.filter { it.publishable }.flatMap { it.usages }.toSet()
@@ -12,7 +12,6 @@ import org.gradle.api.attributes.Category
import org.gradle.api.attributes.Category.CATEGORY_ATTRIBUTE import org.gradle.api.attributes.Category.CATEGORY_ATTRIBUTE
import org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE import org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.api.internal.component.SoftwareComponentInternal
import org.gradle.api.plugins.BasePlugin import org.gradle.api.plugins.BasePlugin
import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.bundling.Jar import org.gradle.api.tasks.bundling.Jar
@@ -189,7 +188,7 @@ class KotlinMetadataTargetConfigurator :
private fun createMetadataCompilationsForCommonSourceSets( private fun createMetadataCompilationsForCommonSourceSets(
target: KotlinMetadataTarget, target: KotlinMetadataTarget,
allMetadataJar: TaskProvider<out Jar> allMetadataJar: TaskProvider<out Jar>,
) = target.project.launchInStage(KotlinPluginLifecycle.Stage.AfterFinaliseDsl) { ) = target.project.launchInStage(KotlinPluginLifecycle.Stage.AfterFinaliseDsl) {
withRestrictedStages(KotlinPluginLifecycle.Stage.upTo(KotlinPluginLifecycle.Stage.FinaliseCompilations)) { withRestrictedStages(KotlinPluginLifecycle.Stage.upTo(KotlinPluginLifecycle.Stage.FinaliseCompilations)) {
// Do this after all targets are configured by the user build script // Do this after all targets are configured by the user build script
@@ -255,7 +254,7 @@ class KotlinMetadataTargetConfigurator :
} }
private fun exportDependenciesForPublishing( private fun exportDependenciesForPublishing(
compilation: KotlinCompilation<*> compilation: KotlinCompilation<*>,
) { ) {
val sourceSet = compilation.defaultSourceSet val sourceSet = compilation.defaultSourceSet
val isSharedNativeCompilation = compilation is KotlinSharedNativeCompilation val isSharedNativeCompilation = compilation is KotlinSharedNativeCompilation
@@ -295,7 +294,7 @@ class KotlinMetadataTargetConfigurator :
target: KotlinMetadataTarget, target: KotlinMetadataTarget,
sourceSet: KotlinSourceSet, sourceSet: KotlinSourceSet,
allMetadataJar: TaskProvider<out Jar>, allMetadataJar: TaskProvider<out Jar>,
isHostSpecific: Boolean isHostSpecific: Boolean,
): KotlinCompilation<*> { ): KotlinCompilation<*> {
val project = target.project val project = target.project
@@ -392,7 +391,7 @@ class KotlinMetadataTargetConfigurator :
} }
internal class NativeSharedCompilationProcessor( internal class NativeSharedCompilationProcessor(
private val compilation: KotlinSharedNativeCompilation private val compilation: KotlinSharedNativeCompilation,
) : KotlinCompilationProcessor<KotlinNativeCompile>(KotlinCompilationInfo(compilation)) { ) : KotlinCompilationProcessor<KotlinNativeCompile>(KotlinCompilationInfo(compilation)) {
override val kotlinTask: TaskProvider<out KotlinNativeCompile> = override val kotlinTask: TaskProvider<out KotlinNativeCompile> =
@@ -472,18 +471,14 @@ internal suspend fun getCommonSourceSetsForMetadataCompilation(project: Project)
internal suspend fun getPublishedPlatformCompilations(project: Project): Map<KotlinUsageContext, KotlinCompilation<*>> { internal suspend fun getPublishedPlatformCompilations(project: Project): Map<KotlinUsageContext, KotlinCompilation<*>> {
val result = mutableMapOf<KotlinUsageContext, KotlinCompilation<*>>() val result = mutableMapOf<KotlinUsageContext, KotlinCompilation<*>>()
project.multiplatformExtension.awaitTargets().withType(AbstractKotlinTarget::class.java).forEach { target -> project.multiplatformExtension.awaitTargets().withType(InternalKotlinTarget::class.java).forEach { target ->
if (target.platformType == KotlinPlatformType.common) if (target.platformType == KotlinPlatformType.common)
return@forEach return@forEach
target.kotlinComponents target.kotlinComponents
.filterIsInstance<SoftwareComponentInternal>() .flatMap { component -> component.internal.usages }
.forEach { component -> .filter { it.includeIntoProjectStructureMetadata }
component.usages .forEach { usage -> result[usage] = usage.compilation }
.filterIsInstance<KotlinUsageContext>()
.filter { it.includeIntoProjectStructureMetadata }
.forEach { usage -> result[usage] = usage.compilation }
}
} }
return result return result
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("FunctionName")
package org.jetbrains.kotlin.gradle.unitTests
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent
import org.jetbrains.kotlin.gradle.plugin.mpp.InternalKotlinTargetComponent
import org.jetbrains.kotlin.gradle.util.assertAllImplementationsAlsoImplement
import kotlin.test.Test
class InternalKotlinTargetComponentTest {
@Test
fun `test - all implementations of KotlinTargetComponent - implement InternalKotlinTargetComponent`() {
assertAllImplementationsAlsoImplement(KotlinTargetComponent::class, InternalKotlinTargetComponent::class)
}
}
@@ -124,7 +124,7 @@ class MppPublicationTest {
for ((targetName, sourceElements) in sourcesElements) { for ((targetName, sourceElements) in sourcesElements) {
assertTrue( assertTrue(
message = "Sources Elements of target $targetName doesn't have 'userAttribute'" message = "$sourceElements of target $targetName doesn't have 'userAttribute'"
) { sourceElements.attributes.toMapOfStrings().containsKey("userAttribute") } ) { sourceElements.attributes.toMapOfStrings().containsKey("userAttribute") }
} }
} }
@@ -143,6 +143,7 @@ class MppPublicationTest {
@Test @Test
fun `sourcesJar task should be available during configuration time`() { fun `sourcesJar task should be available during configuration time`() {
kotlin.linuxX64("linux") kotlin.linuxX64("linux")
project.evaluate()
val sourcesJars = listOf( val sourcesJars = listOf(
"sourcesJar", // sources of common source sets i.e. root module "sourcesJar", // sources of common source sets i.e. root module
@@ -187,6 +188,7 @@ class MppPublicationTest {
fun `test that sourcesJar tasks still exist even if sources should not be published`() { fun `test that sourcesJar tasks still exist even if sources should not be published`() {
kotlin.linuxX64("linux") kotlin.linuxX64("linux")
kotlin.withSourcesJar(publish = false) kotlin.withSourcesJar(publish = false)
project.evaluate()
val sourcesJars = listOf( val sourcesJars = listOf(
"sourcesJar", // sources of common source sets i.e. root module "sourcesJar", // sources of common source sets i.e. root module
@@ -190,7 +190,7 @@ class ProjectCompilerOptionsTests {
} }
} }
assertEquals(true, project.kotlinJvmTask("compileFakeKotlinFake").compilerOptions.javaParameters.get()) assertEquals(true, project.kotlinJvmTask("compileKotlinFake").compilerOptions.javaParameters.get())
assertEquals(true, project.kotlinJvmTask("compileTestKotlinFake").compilerOptions.javaParameters.get()) assertEquals(true, project.kotlinJvmTask("compileTestKotlinFake").compilerOptions.javaParameters.get())
} }
@@ -199,7 +199,7 @@ class ProjectCompilerOptionsTests {
val project = buildProjectWithMPP() val project = buildProjectWithMPP()
project.runLifecycleAwareTest { project.runLifecycleAwareTest {
tasks.withType<KotlinJvmCompileTask>().configureEach { tasks.withType<KotlinJvmCompileTask>().configureEach {
if (it.name == "compileFakeKotlinFake") { if (it.name == "compileKotlinFake") {
it.compilerOptions.javaParameters.set(false) it.compilerOptions.javaParameters.set(false)
} }
} }
@@ -215,7 +215,7 @@ class ProjectCompilerOptionsTests {
} }
} }
assertEquals(false, project.kotlinJvmTask("compileFakeKotlinFake").compilerOptions.javaParameters.get()) assertEquals(false, project.kotlinJvmTask("compileKotlinFake").compilerOptions.javaParameters.get())
assertEquals(true, project.kotlinJvmTask("compileTestKotlinFake").compilerOptions.javaParameters.get()) assertEquals(true, project.kotlinJvmTask("compileTestKotlinFake").compilerOptions.javaParameters.get())
} }
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.util
import org.gradle.api.NamedDomainObjectContainer import org.gradle.api.NamedDomainObjectContainer
import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.HasCompilerOptions import org.jetbrains.kotlin.gradle.plugin.HasCompilerOptions
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.external.* import org.jetbrains.kotlin.gradle.plugin.mpp.external.*
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinCompilationDescriptor.CompilationFactory import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinCompilationDescriptor.CompilationFactory
@@ -18,6 +19,7 @@ class FakeCompilation(delegate: Delegate) : DecoratedExternalKotlinCompilation(d
override val compilerOptions: HasCompilerOptions<KotlinJvmCompilerOptions> override val compilerOptions: HasCompilerOptions<KotlinJvmCompilerOptions>
get() = super.compilerOptions as HasCompilerOptions<KotlinJvmCompilerOptions> get() = super.compilerOptions as HasCompilerOptions<KotlinJvmCompilerOptions>
} }
class FakeTarget(delegate: Delegate) : DecoratedExternalKotlinTarget(delegate) { class FakeTarget(delegate: Delegate) : DecoratedExternalKotlinTarget(delegate) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@@ -40,7 +42,7 @@ fun ExternalKotlinTargetDescriptorBuilder<FakeTarget>.defaults() {
fun ExternalKotlinCompilationDescriptorBuilder<FakeCompilation>.defaults( fun ExternalKotlinCompilationDescriptorBuilder<FakeCompilation>.defaults(
kotlin: KotlinMultiplatformExtension, kotlin: KotlinMultiplatformExtension,
name: String = "fake" name: String = KotlinCompilation.MAIN_COMPILATION_NAME,
) { ) {
compilationName = name compilationName = name
compilationFactory = CompilationFactory(::FakeCompilation) compilationFactory = CompilationFactory(::FakeCompilation)