From ec3fa2610eda98e81becf294dfd038fd99d3a454 Mon Sep 17 00:00:00 2001 From: Sergey Igushkin Date: Tue, 16 Feb 2021 12:07:09 +0300 Subject: [PATCH] Support basic publishing with `maven-publish` in the PM20 plugin --- .../mpp/DefaultKotlinDependencyHandler.kt | 6 +- .../plugin/mpp/GradleProjectModuleBuilder.kt | 9 +- .../mpp/KotlinProjectStructureMetadata.kt | 1 + .../kotlin/gradle/plugin/mpp/ModuleIds.kt | 35 ++++--- .../gradle/plugin/mpp/pm20/GradlePlugin.kt | 50 +++++++++- .../plugin/mpp/pm20/KotlinGradleModule.kt | 1 + .../plugin/mpp/pm20/KotlinJvmVariant.kt | 2 +- .../mpp/pm20/abstractVariantFactories.kt | 92 ++++++++++++++++++- .../plugin/mpp/pm20/abstractVariants.kt | 56 ++++++++++- .../mpp/pm20/fragmentsMetadataCompilation.kt | 12 ++- .../gradle/plugin/mpp/pm20/modelClasses.kt | 2 +- .../plugin/mpp/pm20/util/capabilities.kt | 11 ++- 12 files changed, 241 insertions(+), 36 deletions(-) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/DefaultKotlinDependencyHandler.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/DefaultKotlinDependencyHandler.kt index 1c6fbe37ab4..252990b2230 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/DefaultKotlinDependencyHandler.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/DefaultKotlinDependencyHandler.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinGradleModule -import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.LazyCapability +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.CalculatedCapability import org.jetbrains.kotlin.gradle.targets.js.npm.NpmDependency import org.jetbrains.kotlin.gradle.targets.js.npm.directoryNpmDependency import org.jetbrains.kotlin.gradle.targets.js.npm.moduleName @@ -76,7 +76,9 @@ class DefaultKotlinDependencyHandler( val dependency = when (dependencyNotation) { is KotlinGradleModule -> project.dependencies.create(dependencyNotation.project).apply { (this as ModuleDependency).capabilities { - it.requireCapability(LazyCapability.fromModule(dependencyNotation)) + if (dependencyNotation.moduleClassifier != null) { + it.requireCapability(CalculatedCapability.fromModule(dependencyNotation)) + } } } else -> dependencyNotation diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GradleProjectModuleBuilder.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GradleProjectModuleBuilder.kt index 7e575c0ebf2..010dade2c5f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GradleProjectModuleBuilder.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/GradleProjectModuleBuilder.kt @@ -267,8 +267,13 @@ class GradleModuleVariantResolver(val project: Project) : ModuleVariantResolver // TODO maybe improve this behavior? Currently it contradicts dependency resolution in that it may return a chosen variant for an // unrequested dependency. This workaround is needed for synthetic modules which were not produced from module metadata, so maybe // those modules should be marked somehow - dependencyModule.variants.singleOrNull() - ?.let { return VariantResolution.fromMatchingVariants(requestingVariant, dependencyModule, listOf(it)) } + if (dependencyModule is ExternalSyntheticKotlinModule) { + return VariantResolution.fromMatchingVariants( + requestingVariant, + dependencyModule, + listOf(dependencyModule.variants.single()) + ) + } val module = requestingVariant.containingModule diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt index 37bc403816b..480ad4ef1f8 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinProjectStructureMetadata.kt @@ -198,6 +198,7 @@ internal fun buildProjectStructureMetadata(module: KotlinGradleModule): KotlinPr module.fragments.associate { it.name to it.directRefinesDependencies.map { it.name }.toSet() } // FIXME: support native implementation-as-api-dependencies + // FIXME: support dependencies on auxiliary modules val fragmentDependencies = module.fragments.associate { fragment -> fragment.name to fragment.declaredModuleDependencies.map { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/ModuleIds.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/ModuleIds.kt index f473003d9eb..6e7ac210e9d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/ModuleIds.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/ModuleIds.kt @@ -15,13 +15,12 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull import org.jetbrains.kotlin.gradle.dsl.topLevelExtension -import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinPm20ProjectExtension -import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.currentBuildId +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.* +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.CalculatedCapability import org.jetbrains.kotlin.gradle.utils.getValue import org.jetbrains.kotlin.project.model.KotlinModuleIdentifier import org.jetbrains.kotlin.project.model.LocalModuleIdentifier import org.jetbrains.kotlin.project.model.MavenModuleIdentifier -import java.lang.IllegalArgumentException internal object ModuleIds { fun fromDependency(dependency: Dependency) = when (dependency) { @@ -77,7 +76,8 @@ internal object ModuleIds { is LocalModuleIdentifier -> { check(moduleIdentifier.buildId == thisProject.currentBuildId().name) val dependencyProject = thisProject.project(moduleIdentifier.projectId) - val getRootPublication: () -> MavenPublication? = when (val topLevelExtension = dependencyProject.topLevelExtension) { + val topLevelExtension = dependencyProject.topLevelExtension + val getRootPublication: () -> MavenPublication? = when (topLevelExtension) { is KotlinMultiplatformExtension -> { { topLevelExtension.rootSoftwareComponent.publicationDelegate } } @@ -86,7 +86,19 @@ internal object ModuleIds { } else -> error("unexpected top-level extension $topLevelExtension") } - val coordinatesProvider = MultiplatformRootPublicationCoordinatesProvider(dependencyProject, getRootPublication) + val capabilities = when (topLevelExtension) { + is KotlinMultiplatformExtension -> emptyList() + is KotlinPm20ProjectExtension -> listOfNotNull(CalculatedCapability.capabilityStringFromModule( + topLevelExtension.modules.single { it.moduleIdentifier == moduleIdentifier } + )) + else -> error("unexpected top-level extension $topLevelExtension") + } + val coordinatesProvider = MavenPublicationCoordinatesProvider( + dependencyProject, + getRootPublication, + defaultModuleSuffix = null, + capabilities = capabilities + ) return ChangingModuleDependencyIdentifier({ coordinatesProvider.group }, { coordinatesProvider.name }) } is MavenModuleIdentifier -> { @@ -104,9 +116,11 @@ interface PublishedModuleCoordinatesProvider { val capabilities: Iterable } -class MultiplatformRootPublicationCoordinatesProvider( +open class MavenPublicationCoordinatesProvider( project: Project, - val getPublication: () -> MavenPublication? + val getPublication: () -> MavenPublication?, + defaultModuleSuffix: String?, + override val capabilities: Iterable = emptyList() ) : PublishedModuleCoordinatesProvider { override val group: String by project.provider { @@ -114,13 +128,10 @@ class MultiplatformRootPublicationCoordinatesProvider( } override val name: String by project.provider { - getPublication()?.artifactId ?: project.group.toString() + getPublication()?.artifactId ?: project.name.plus(defaultModuleSuffix?.let { "-$it" }.orEmpty()) } override val version: String by project.provider { - getPublication()?.artifactId ?: project.version.toString() + getPublication()?.version ?: project.version.toString() } - - override val capabilities: Iterable - get() = emptyList() } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradlePlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradlePlugin.kt index 49411eb2538..89da77ff979 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradlePlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/GradlePlugin.kt @@ -6,7 +6,9 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 import org.gradle.api.* +import org.gradle.api.component.SoftwareComponentFactory import org.gradle.api.plugins.JavaBasePlugin +import org.gradle.api.publish.PublishingExtension import org.gradle.api.publish.maven.MavenPublication import org.gradle.util.GradleVersion import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension @@ -14,8 +16,11 @@ import org.jetbrains.kotlin.gradle.dsl.pm20Extension import org.jetbrains.kotlin.gradle.internal.customizeKotlinDependencies import org.jetbrains.kotlin.gradle.utils.checkGradleCompatibility import org.jetbrains.kotlin.project.model.KotlinModuleIdentifier +import javax.inject.Inject -abstract class KotlinPm20GradlePlugin : Plugin { +abstract class KotlinPm20GradlePlugin @Inject constructor( + @Inject private val softwareComponentFactory: SoftwareComponentFactory +) : Plugin { override fun apply(project: Project) { checkGradleCompatibility("the Kotlin Multiplatform plugin", GradleVersion.version("6.1")) @@ -25,6 +30,8 @@ abstract class KotlinPm20GradlePlugin : Plugin { createDefaultModules(project) customizeKotlinDependencies(project) registerDefaultVariantFactories(project) + setupFragmentsMetadata(project) + setupPublication(project) } private fun registerDefaultVariantFactories(project: Project) { @@ -42,17 +49,54 @@ abstract class KotlinPm20GradlePlugin : Plugin { modules.create(KotlinGradleModule.TEST_MODULE_NAME) main { makePublic() } } - setupFragmentsMetadata(project) } private fun setupFragmentsMetadata(project: Project) { project.pm20Extension.modules.all { module -> configureMetadataResolutionAndBuild(module) - module.ifMadePublic { configureMetadataExposure(module) } + configureMetadataExposure(module) + } + } + + private fun setupPublication(project: Project) { + project.pm20Extension.modules.all { module -> + setupPublicationForModule(module) + } + } + + private fun setupPublicationForModule(module: KotlinGradleModule) { + val project = module.project + + val metadataElements = project.configurations.getByName(metadataElementsConfigurationName(module)) + + val componentName = rootPublicationComponentName(module) + val rootSoftwareComponent = softwareComponentFactory.adhoc(componentName).also { + project.components.add(it) + it.addVariantsFromConfiguration(metadataElements) { } + } + + module.ifMadePublic { + val metadataDependencyConfiguration = resolvableMetadataConfiguration(module) + project.pluginManager.withPlugin("maven-publish") { + project.extensions.getByType(PublishingExtension::class.java).publications.create( + componentName, + MavenPublication::class.java + ) { publication -> + publication.from(rootSoftwareComponent) + publication.versionMapping { versionMapping -> + versionMapping.allVariants { + it.fromResolutionOf(metadataDependencyConfiguration) + } + } + } + } } } } +fun rootPublicationComponentName(module: KotlinGradleModule) = + module.disambiguateName("root") + open class KotlinPm20ProjectExtension(project: Project) : KotlinTopLevelExtension(project) { val modules: NamedDomainObjectContainer by lazy { project.objects.domainObjectContainer( diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinGradleModule.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinGradleModule.kt index ae9eca4ba6e..e65266e1064 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinGradleModule.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinGradleModule.kt @@ -42,6 +42,7 @@ open class KotlinGradleModule( private var setPublicHandlers: MutableList<() -> Unit> = mutableListOf() fun ifMadePublic(action: () -> Unit) { + // FIXME reentrancy? if (isPublic) action() else setPublicHandlers.add(action) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinJvmVariant.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinJvmVariant.kt index 07da82a5c1a..1428546c286 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinJvmVariant.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinJvmVariant.kt @@ -20,7 +20,7 @@ import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import org.jetbrains.kotlin.project.model.refinesClosure open class KotlinJvmVariant(containingModule: KotlinGradleModule, fragmentName: String) : - KotlinGradleVariantWithRuntimeDependencies(containingModule, fragmentName) { + KotlinGradlePublishedVariantWithRuntime(containingModule, fragmentName) { override val platformType: KotlinPlatformType get() = KotlinPlatformType.jvm diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/abstractVariantFactories.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/abstractVariantFactories.kt index 3dfdc08dc4c..6a38ee85c1a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/abstractVariantFactories.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/abstractVariantFactories.kt @@ -6,12 +6,20 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 import org.gradle.api.artifacts.Configuration +import org.gradle.api.artifacts.ModuleDependency import org.gradle.api.attributes.Usage +import org.gradle.api.component.AdhocComponentWithVariants +import org.gradle.api.component.SoftwareComponentFactory +import org.gradle.api.internal.project.ProjectInternal +import org.gradle.api.publish.PublishingExtension +import org.gradle.api.publish.maven.MavenPublication import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages -import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.LazyCapability +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.CalculatedCapability +import org.jetbrains.kotlin.gradle.plugin.mpp.publishedConfigurationName import org.jetbrains.kotlin.gradle.plugin.mpp.sourcesJarTask import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation +import org.jetbrains.kotlin.gradle.utils.dashSeparatedName import org.jetbrains.kotlin.project.model.refinesClosure abstract class AbstractKotlinGradleVariantFactory( @@ -79,7 +87,7 @@ abstract class AbstractKotlinGradleVariantFactory( } } -abstract class AbstractKotlinGradleVariantWithRuntimeDependenciesFactory(module: KotlinGradleModule) : +abstract class AbstractKotlinGradleVariantWithRuntimeFactory(module: KotlinGradleModule) : AbstractKotlinGradleVariantFactory(module) { open fun configureRuntimeResolvableConfiguration(fragment: T, configuration: Configuration) { @@ -98,7 +106,7 @@ abstract class AbstractKotlinGradleVariantWithRuntimeDependenciesFactory(module: KotlinGradleModule) : + AbstractKotlinGradleVariantWithRuntimeFactory(module) { + + override fun create(name: String): T { + val result = super.create(name) + configureVariantPublishing(result) + return result + } + + open fun configureVariantPublishing(variant: T) { + val rootSoftwareComponent = + project.components + .withType(AdhocComponentWithVariants::class.java) + .getByName(rootPublicationComponentName(module)) + + val platformModuleDependencyProvider = project.provider { + val coordinates = variant.publishedMavenModuleCoordinates + (project.dependencies.create("${coordinates.group}:${coordinates.name}:${coordinates.version}") as ModuleDependency).apply { + if (module.moduleClassifier != null) { + capabilities { it.requireCapability(CalculatedCapability.fromModule(module)) } + } + } + } + + // FIXME inject vs internal API + val platformComponentName = platformComponentName(variant) + val platformComponent = (project as ProjectInternal).services + .get(SoftwareComponentFactory::class.java) + .adhoc(platformComponentName) + project.components.add(platformComponent) + platformComponent.addVariantsFromConfiguration(project.configurations.getByName(variant.apiElementsConfigurationName)) { + it.mapToMavenScope("compile") + } + platformComponent.addVariantsFromConfiguration(project.configurations.getByName(variant.runtimeElementsConfigurationName)) { + it.mapToMavenScope("compile") + } + + module.ifMadePublic { + project.pluginManager.withPlugin("maven-publish") { + project.extensions.getByType(PublishingExtension::class.java).apply { + publications.create(platformComponentName, MavenPublication::class.java).apply { + from(platformComponent) + variant.assignMavenPublication(this) + artifactId = dashSeparatedName(project.name, variant.defaultPublishedModuleSuffix) + } + } + } + } + + val publishedApiConfiguration = + project.configurations.create(publishedConfigurationName(variant.apiElementsConfigurationName)).apply { + isCanBeConsumed = false + isCanBeResolved = false + configureApiElementsConfiguration(variant, this) + setModuleCapability(this, module) + dependencies.addLater(platformModuleDependencyProvider) + } + val publishedRuntimeConfiguration = + project.configurations.create(publishedConfigurationName(variant.runtimeElementsConfigurationName)).apply { + isCanBeConsumed = false + isCanBeResolved = false + configureRuntimeElementsConfiguration(variant, this) + setModuleCapability(this, module) + dependencies.addLater(platformModuleDependencyProvider) + } + listOf(publishedApiConfiguration, publishedRuntimeConfiguration).forEach { + rootSoftwareComponent.addVariantsFromConfiguration(it) { } + } + } + + open fun platformComponentName(variant: T) = variant.disambiguateName("") +} + + internal fun setModuleCapability(configuration: Configuration, module: KotlinGradleModule) { - configuration.outgoing.capability(LazyCapability.fromModule(module)) + if (module.moduleClassifier != null) { + configuration.outgoing.capability(CalculatedCapability.fromModule(module)) + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/abstractVariants.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/abstractVariants.kt index 1a351462c8d..9139725a09f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/abstractVariants.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/abstractVariants.kt @@ -7,13 +7,18 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 import org.gradle.api.file.ConfigurableFileCollection import org.gradle.api.file.FileCollection +import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.tasks.TaskProvider import org.gradle.api.tasks.bundling.AbstractArchiveTask import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationOutput import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinCompilationOutput +import org.jetbrains.kotlin.gradle.plugin.mpp.MavenPublicationCoordinatesProvider +import org.jetbrains.kotlin.gradle.plugin.mpp.PublishedModuleCoordinatesProvider +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.CalculatedCapability import org.jetbrains.kotlin.gradle.plugin.mpp.publishedConfigurationName import org.jetbrains.kotlin.gradle.tasks.withType +import org.jetbrains.kotlin.gradle.utils.dashSeparatedName import org.jetbrains.kotlin.project.model.KotlinAttributeKey import org.jetbrains.kotlin.project.model.KotlinModuleVariant import org.jetbrains.kotlin.project.model.KotlinPlatformTypeAttribute @@ -49,19 +54,47 @@ abstract class KotlinGradleVariant( val apiElementsConfigurationName: String get() = disambiguateName("apiElements") - open val gradleVariantNames: Set - get() = listOf(apiElementsConfigurationName, publishedConfigurationName(apiElementsConfigurationName)).toSet() + abstract val gradleVariantNames: Set override fun toString(): String = "variant $fragmentName in $containingModule" } +interface SingleMavenPublicationHolder { + fun assignMavenPublication(publication: MavenPublication) + val defaultPublishedModuleSuffix: String? + val publishedMavenModuleCoordinates: PublishedModuleCoordinatesProvider +} + +class DefaultSingleMavenPublicationHolder( + private var module: KotlinGradleModule, + override val defaultPublishedModuleSuffix: String? +) : SingleMavenPublicationHolder { + private val project get() = module.project + + private var assignedMavenPublication: MavenPublication? = null + + override fun assignMavenPublication(publication: MavenPublication) { + if (assignedMavenPublication != null) + error("already assigned publication $publication") + assignedMavenPublication = publication + } + + override val publishedMavenModuleCoordinates: PublishedModuleCoordinatesProvider = + MavenPublicationCoordinatesProvider( + project, + { assignedMavenPublication }, + defaultPublishedModuleSuffix, + capabilities = listOfNotNull(CalculatedCapability.capabilityStringFromModule(module)) + ) +} + private fun kotlinPlatformTypeAttributeFromPlatform(platformType: KotlinPlatformType) = platformType.name // TODO: rewrite with the artifacts API internal val KotlinGradleVariant.defaultSourceArtifactTaskName: String get() = disambiguateName("sourcesJar") -abstract class KotlinGradleVariantWithRuntimeDependencies( +abstract class KotlinGradleVariantWithRuntime( containingModule: KotlinGradleModule, fragmentName: String ) : KotlinGradleVariant(containingModule, fragmentName) { @@ -78,8 +111,21 @@ abstract class KotlinGradleVariantWithRuntimeDependencies( // TODO generalize exposing outputs: what if a variant has more than one such configurations or none? val runtimeElementsConfigurationName: String get() = disambiguateName("runtimeElements") +} + +private fun defaultModuleSuffix(module: KotlinGradleModule, variantName: String): String = + dashSeparatedName(variantName, module.moduleClassifier) + +abstract class KotlinGradlePublishedVariantWithRuntime(containingModule: KotlinGradleModule, fragmentName: String) : + KotlinGradleVariantWithRuntime(containingModule, fragmentName), + SingleMavenPublicationHolder by DefaultSingleMavenPublicationHolder( + containingModule, + defaultModuleSuffix(containingModule, fragmentName) + ) { override val gradleVariantNames: Set - get() = super.gradleVariantNames + - listOf(runtimeElementsConfigurationName, publishedConfigurationName(runtimeElementsConfigurationName)) + get() = + listOf(apiElementsConfigurationName, runtimeElementsConfigurationName).flatMapTo(mutableSetOf()) { + listOf(it, publishedConfigurationName(it)) + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/fragmentsMetadataCompilation.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/fragmentsMetadataCompilation.kt index 0822496c45c..6e26012cb29 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/fragmentsMetadataCompilation.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/fragmentsMetadataCompilation.kt @@ -42,11 +42,14 @@ internal fun configureMetadataResolutionAndBuild(module: KotlinGradleModule) { internal fun configureMetadataExposure(module: KotlinGradleModule) { val project = module.project - project.configurations.create(module.disambiguateName("metadataElements")).apply { - isCanBeConsumed = true + project.configurations.create(metadataElementsConfigurationName(module)).apply { + module.ifMadePublic { + isCanBeConsumed = true + } isCanBeResolved = false project.artifacts.add(name, project.tasks.named(metadataJarName(module))) attributes.attribute(Usage.USAGE_ATTRIBUTE, project.usageByName(KotlinUsages.KOTLIN_METADATA)) + attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.common) module.fragments.all { fragment -> // FIXME: native api-implementation project.addExtendsFromRelation(name, fragment.apiConfigurationName) @@ -55,6 +58,9 @@ internal fun configureMetadataExposure(module: KotlinGradleModule) { } } +fun metadataElementsConfigurationName(module: KotlinGradleModule) = + module.disambiguateName("metadataElements") + private fun generateAndExportProjectStructureMetadata( module: KotlinGradleModule ) { @@ -123,7 +129,7 @@ private fun configureMetadataJarTask( } } -private fun metadataJarName(module: KotlinGradleModule) = +internal fun metadataJarName(module: KotlinGradleModule) = lowerCamelCaseName(module.moduleClassifier, "metadataJar") private fun createMetadataCompilation( diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/modelClasses.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/modelClasses.kt index e47c909ef25..0896df4deb9 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/modelClasses.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/modelClasses.kt @@ -18,7 +18,7 @@ import org.jetbrains.kotlin.project.model.utils.variantsContainingFragment import java.util.concurrent.Callable open class KotlinJvmVariantFactory(module: KotlinGradleModule) : - AbstractKotlinGradleVariantWithRuntimeDependenciesFactory(module) { + AbstractKotlinGradleRuntimePublishedVariantFactory(module) { override fun instantiateFragment(name: String) = KotlinJvmVariant(module, name) // FIXME expose the JAR with the artifacts API diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/util/capabilities.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/util/capabilities.kt index 8d7a0814b28..00fcfcc6109 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/util/capabilities.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/util/capabilities.kt @@ -9,7 +9,7 @@ import org.gradle.api.capabilities.Capability import org.gradle.api.provider.Provider import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinGradleModule -internal class LazyCapability( +internal class CalculatedCapability( val groupProvider: Provider, val nameValue: String, val versionProvider: Provider, @@ -22,14 +22,19 @@ internal class LazyCapability( override fun getVersion(): String? = versionProvider.get() companion object { - fun fromModule(module: KotlinGradleModule): LazyCapability { + fun fromModule(module: KotlinGradleModule): CalculatedCapability { val project = module.project - return LazyCapability( + return CalculatedCapability( project.provider { project.group.toString() }, project.name, project.provider { project.version.toString() }, module.moduleClassifier ) } + + fun capabilityStringFromModule(module: KotlinGradleModule): String? = + if (module.moduleClassifier != null) fromModule(module).notation() else null } + + fun notation(): String = "$group:$name:$version" } \ No newline at end of file