From a94597d85a101a983a2acf42aa28d30a1b559a51 Mon Sep 17 00:00:00 2001 From: Sergey Igushkin Date: Thu, 1 Apr 2021 15:21:07 +0300 Subject: [PATCH] Experimental sources publication in the PM2.0 prototype --- .../plugin/mpp/pm20/KotlinGradleFragment.kt | 4 + .../plugin/mpp/pm20/KotlinGradleVariant.kt | 2 +- .../mpp/DefaultKotlinDependencyHandler.kt | 4 +- .../plugin/mpp/KotlinMultiplatformPlugin.kt | 9 +- .../kotlin/gradle/plugin/mpp/KotlinUsages.kt | 1 + .../kotlin/gradle/plugin/mpp/ModuleIds.kt | 4 +- ...Provider.kt => FragmentSourcesProvider.kt} | 32 ++++--- .../gradle/plugin/mpp/pm20/GradlePlugin.kt | 2 + .../pm20/KotlinCompilationTaskConfigurator.kt | 10 +-- .../mpp/pm20/abstractVariantFactories.kt | 43 +++++----- .../plugin/mpp/pm20/abstractVariants.kt | 8 +- .../mpp/pm20/fragmentsMetadataCompilation.kt | 17 ++++ .../plugin/mpp/pm20/util/capabilities.kt | 11 ++- .../plugin/mpp/pm20/variantPublishing.kt | 83 ++++++++++++++++--- 14 files changed, 166 insertions(+), 64 deletions(-) rename libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/{VariantSourcesProvider.kt => FragmentSourcesProvider.kt} (51%) diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinGradleFragment.kt b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinGradleFragment.kt index a28eeb7ce39..5d7a72c6601 100644 --- a/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinGradleFragment.kt +++ b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinGradleFragment.kt @@ -14,6 +14,7 @@ import org.gradle.util.ConfigureUtil import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder import org.jetbrains.kotlin.project.model.KotlinModuleFragment +import org.jetbrains.kotlin.project.model.refinesClosure interface KotlinGradleFragment : KotlinModuleFragment, HasKotlinDependencies, Named { override val kotlinSourceRoots: SourceDirectorySet @@ -49,3 +50,6 @@ interface KotlinGradleFragment : KotlinModuleFragment, HasKotlinDependencies, Na // TODO: resolvable metadata configurations? listOf(transitiveApiConfigurationName, transitiveImplementationConfigurationName) } + +val KotlinGradleFragment.refinesClosure: Set + get() = (this as KotlinModuleFragment).refinesClosure.mapTo(mutableSetOf()) { it as KotlinGradleFragment } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinGradleVariant.kt b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinGradleVariant.kt index a972eb0afb8..d22ba16c5e3 100644 --- a/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinGradleVariant.kt +++ b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinGradleVariant.kt @@ -26,7 +26,7 @@ interface KotlinGradleVariant : KotlinGradleFragment, KotlinModuleVariant { val compilationOutputs: KotlinCompilationOutput // TODO rewrite using our own artifacts API - val sourceArchiveTask: TaskProvider + val sourceArchiveTaskName: String // TODO generalize exposing outputs: what if a variant has more than one such configurations or none? val apiElementsConfigurationName: String 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 252990b2230..51117e1f883 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.CalculatedCapability +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.ComputedCapability 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 @@ -77,7 +77,7 @@ class DefaultKotlinDependencyHandler( is KotlinGradleModule -> project.dependencies.create(dependencyNotation.project).apply { (this as ModuleDependency).capabilities { if (dependencyNotation.moduleClassifier != null) { - it.requireCapability(CalculatedCapability.fromModule(dependencyNotation)) + it.requireCapability(ComputedCapability.fromModule(dependencyNotation)) } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt index f4cdc898037..79d71020174 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt @@ -297,9 +297,14 @@ internal fun sourcesJarTask( sourceSets: Lazy>, componentName: String?, artifactNameAppendix: String -): TaskProvider { - val taskName = lowerCamelCaseName(componentName, "sourcesJar") +): TaskProvider = sourcesJarTaskNamed(lowerCamelCaseName(componentName, "sourcesJar"), project, sourceSets, artifactNameAppendix) +internal fun sourcesJarTaskNamed( + taskName: String, + project: Project, + sourceSets: Lazy>, + artifactNameAppendix: String +): TaskProvider { project.locateTask(taskName)?.let { return it } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt index fe8f1762aef..75e00ec7659 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinUsages.kt @@ -19,6 +19,7 @@ object KotlinUsages { const val KOTLIN_API = "kotlin-api" const val KOTLIN_RUNTIME = "kotlin-runtime" const val KOTLIN_METADATA = "kotlin-metadata" + const val KOTLIN_SOURCES = "kotlin-sources" val values = setOf(KOTLIN_API, KOTLIN_RUNTIME) 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 57dd0b194c7..08a8715f4dd 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 @@ -16,7 +16,7 @@ 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.* -import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.CalculatedCapability +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.ComputedCapability import org.jetbrains.kotlin.gradle.utils.getValue import org.jetbrains.kotlin.project.model.KotlinModuleIdentifier import org.jetbrains.kotlin.project.model.LocalModuleIdentifier @@ -88,7 +88,7 @@ internal object ModuleIds { } val capabilities = when (topLevelExtension) { is KotlinMultiplatformExtension -> emptyList() - is KotlinPm20ProjectExtension -> listOfNotNull(CalculatedCapability.capabilityStringFromModule( + is KotlinPm20ProjectExtension -> listOfNotNull(ComputedCapability.capabilityStringFromModule( topLevelExtension.modules.single { it.moduleIdentifier == moduleIdentifier } )) else -> error("unexpected top-level extension $topLevelExtension") diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/VariantSourcesProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/FragmentSourcesProvider.kt similarity index 51% rename from libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/VariantSourcesProvider.kt rename to libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/FragmentSourcesProvider.kt index 3c69b133387..aefe9a5915a 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/VariantSourcesProvider.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/FragmentSourcesProvider.kt @@ -8,22 +8,32 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 import org.gradle.api.Project import org.gradle.api.file.FileCollection import org.gradle.language.base.plugins.LifecycleBasePlugin -import org.jetbrains.kotlin.project.model.refinesClosure import org.jetbrains.kotlin.project.model.utils.variantsContainingFragment -open class VariantSourcesProvider { - open fun getSourcesFromRefinesClosure(variant: KotlinGradleVariant): FileCollection { - val project = variant.containingModule.project - return project.files(project.provider { - variant.refinesClosure.map { it.kotlinSourceRoots } - }) - } +open class FragmentSourcesProvider { + protected open fun getSourcesFromFragmentsAsMap( + fragments: Iterable + ): Map = + fragments.associateWith { it.project.files(it.project.provider { it.kotlinSourceRoots }) } - open fun getCommonSourcesFromRefinesClosure(variant: KotlinGradleVariant): FileCollection { - val containingModule = variant.containingModule + open fun getFragmentOwnSources(fragment: KotlinGradleFragment): FileCollection = + getSourcesFromFragmentsAsMap(listOf(fragment)).values.single() + + open fun getAllFragmentSourcesAsMap(module: KotlinGradleModule): Map = + getSourcesFromFragmentsAsMap(module.fragments) + + open fun getSourcesFromRefinesClosureAsMap(fragment: KotlinGradleFragment): Map = + getSourcesFromFragmentsAsMap(fragment.refinesClosure) + + open fun getSourcesFromRefinesClosure(fragment: KotlinGradleFragment): FileCollection = + fragment.project.files(fragment.project.provider { getSourcesFromRefinesClosureAsMap(fragment).values }) + + open fun getCommonSourcesFromRefinesClosure(fragment: KotlinGradleFragment): FileCollection { + val containingModule = fragment.containingModule val project = containingModule.project + getSourcesFromRefinesClosureAsMap(fragment) return project.files(project.provider { - variant.refinesClosure.filter { + fragment.refinesClosure.filter { // Every fragment refined by some other fragment should be considered common, even if it is included in just one variant containingModule.variantsContainingFragment(it).toSet() != setOf(it) }.map { it.kotlinSourceRoots } 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 63461a760eb..063f9f04f6d 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 @@ -86,11 +86,13 @@ abstract class KotlinPm20GradlePlugin @Inject constructor( val project = module.project val metadataElements = project.configurations.getByName(metadataElementsConfigurationName(module)) + val sourceElements = project.configurations.getByName(sourceElementsConfigurationName(module)) val componentName = rootPublicationComponentName(module) val rootSoftwareComponent = softwareComponentFactory.adhoc(componentName).also { project.components.add(it) it.addVariantsFromConfiguration(metadataElements) { } + it.addVariantsFromConfiguration(sourceElements) { } } module.ifMadePublic { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinCompilationTaskConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinCompilationTaskConfigurator.kt index 881dbcafacf..b49d6678bee 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinCompilationTaskConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinCompilationTaskConfigurator.kt @@ -32,9 +32,9 @@ open class KotlinCompilationTaskConfigurator( fragment: KotlinGradleFragment, compilationData: KotlinCompilationData<*> ): TaskProvider { - Kotlin2JvmSourceSetProcessor(KotlinTasksProvider(), compilationData, kotlinPluginVersion).run() - val allSources = variantSourcesProvider.getSourcesFromRefinesClosure(variant) - val commonSources = variantSourcesProvider.getCommonSourcesFromRefinesClosure(variant) + Kotlin2JvmSourceSetProcessor(KotlinTasksProvider(), compilationData).run() + val allSources = getSourcesForFragmentCompilation(fragment) + val commonSources = getCommonSourcesForFragmentCompilation(fragment) // FIXME support custom source file extensions in the two calls below addSourcesToKotlinCompileTask(project, compilationData.compileKotlinTaskName, emptyList()) { allSources } @@ -49,8 +49,8 @@ open class KotlinCompilationTaskConfigurator( ): TaskProvider { val compileTask = KotlinNativeTargetConfigurator.createKlibCompilationTask(compilationData) - val allSources = variantSourcesProvider.getSourcesFromRefinesClosure(variant) - val commonSources = variantSourcesProvider.getSourcesFromRefinesClosure(variant) + val allSources = getSourcesForFragmentCompilation(fragment) + val commonSources = getCommonSourcesForFragmentCompilation(fragment) compileTask.configure { it.source(allSources) 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 94e2271c01b..68ec8fcaadf 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 @@ -5,28 +5,15 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 -import jdk.internal.org.objectweb.asm.tree.VarInsnNode -import org.gradle.api.Project import org.gradle.api.artifacts.Configuration -import org.gradle.api.artifacts.ModuleDependency -import org.gradle.api.attributes.Attribute -import org.gradle.api.attributes.AttributeContainer +import org.gradle.api.attributes.Bundling +import org.gradle.api.attributes.Category 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.gradle.api.publish.maven.internal.publication.DefaultMavenPublication import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages -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.plugin.mpp.pm20.util.ComputedCapability +import org.jetbrains.kotlin.gradle.plugin.mpp.sourcesJarTaskNamed import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation -import org.jetbrains.kotlin.gradle.utils.dashSeparatedName -import org.jetbrains.kotlin.project.model.refinesClosure -import javax.inject.Inject abstract class AbstractKotlinGradleVariantFactory( module: KotlinGradleModule @@ -51,17 +38,21 @@ abstract class AbstractKotlinGradleVariantFactory( open fun configureApiElementsConfiguration(fragment: T, configuration: Configuration) { setPlatformAttributesInConfiguration(fragment, configuration) - configuration.attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(project, fragment.platformType)) + configuration.attributes.apply { + attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(project, fragment.platformType)) + attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category::class.java, Category.LIBRARY)) + attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling::class.java, Bundling.EXTERNAL)) + } } abstract fun configureKotlinCompilation(fragment: T) open fun createSourcesArchiveTask(fragment: T) { - sourcesJarTask( + sourcesJarTaskNamed( + fragment.sourceArchiveTaskName, project, - lazy { fragment.refinesClosure.associate { it.disambiguateName("") to project.files(it.kotlinSourceRoots) } }, - fragment.name, - fragment.name.toLowerCase() + lazy { FragmentSourcesProvider().getSourcesFromRefinesClosureAsMap(fragment).mapKeys { it.key.fragmentName } }, + fragment.name ) } @@ -104,7 +95,11 @@ abstract class AbstractKotlinGradleVariantWithRuntimeFactory - get() = project.tasks.withType().named(defaultSourceArtifactTaskName) + override val sourceArchiveTaskName: String + get() = defaultSourceArtifactTaskName // TODO generalize exposing outputs: what if a variant has more than one such configurations or none? override val apiElementsConfigurationName: String @@ -81,7 +81,7 @@ class DefaultSingleMavenPublishedModuleHolder( project, { assignedMavenPublication }, defaultPublishedModuleSuffix, - capabilities = listOfNotNull(CalculatedCapability.capabilityStringFromModule(module)) + capabilities = listOfNotNull(ComputedCapability.capabilityStringFromModule(module)) ) } 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 55bccbfccaa..edcb09278a3 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 @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.gradle.dsl.pm20Extension import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.KotlinCommonSourceSetProcessor import org.jetbrains.kotlin.gradle.plugin.mpp.* +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.ComputedCapability import org.jetbrains.kotlin.gradle.targets.metadata.NativeSharedCompilationProcessor import org.jetbrains.kotlin.gradle.targets.metadata.createGenerateProjectStructureMetadataTask import org.jetbrains.kotlin.gradle.targets.metadata.filesWithUnpackedArchives @@ -22,6 +23,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider import org.jetbrains.kotlin.gradle.tasks.registerTask import org.jetbrains.kotlin.gradle.tasks.withType import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation +import org.jetbrains.kotlin.gradle.utils.dashSeparatedName import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION import org.jetbrains.kotlin.project.model.KotlinModuleFragment @@ -58,11 +60,26 @@ internal fun configureMetadataExposure(module: KotlinGradleModule) { } setModuleCapability(this, module) } + + val sourcesArtifactAppendix = dashSeparatedName(module.moduleClassifier, "all", "sources") + val sourcesArtifact = sourcesJarTaskNamed( + module.disambiguateName("allSourcesJar"), + project, + lazy { FragmentSourcesProvider().getAllFragmentSourcesAsMap(module).mapKeys { it.key.fragmentName } }, + sourcesArtifactAppendix + ) + DocumentationVariantConfigurator().createSourcesElementsConfiguration( + project, sourceElementsConfigurationName(module), + sourcesArtifact.get(), "sources", ComputedCapability.fromModuleOrNull(module) + ) } fun metadataElementsConfigurationName(module: KotlinGradleModule) = module.disambiguateName("metadataElements") +fun sourceElementsConfigurationName(module: KotlinGradleModule) = + module.disambiguateName("sourceElements") + private fun generateAndExportProjectStructureMetadata( module: KotlinGradleModule ) { 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 00fcfcc6109..f82731c6363 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 CalculatedCapability( +internal class ComputedCapability( val groupProvider: Provider, val nameValue: String, val versionProvider: Provider, @@ -22,9 +22,9 @@ internal class CalculatedCapability( override fun getVersion(): String? = versionProvider.get() companion object { - fun fromModule(module: KotlinGradleModule): CalculatedCapability { + fun fromModule(module: KotlinGradleModule): ComputedCapability { val project = module.project - return CalculatedCapability( + return ComputedCapability( project.provider { project.group.toString() }, project.name, project.provider { project.version.toString() }, @@ -32,6 +32,11 @@ internal class CalculatedCapability( ) } + fun fromModuleOrNull(module: KotlinGradleModule): ComputedCapability? = + if (module.moduleClassifier != null) + fromModule(module) + else null + fun capabilityStringFromModule(module: KotlinGradleModule): String? = if (module.moduleClassifier != null) fromModule(module).notation() else null } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/variantPublishing.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/variantPublishing.kt index 86fdebae7e8..c6765e0f8b6 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/variantPublishing.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/variantPublishing.kt @@ -6,16 +6,21 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 import org.gradle.api.Project +import org.gradle.api.artifacts.Configuration import org.gradle.api.artifacts.ModuleDependency -import org.gradle.api.attributes.Attribute -import org.gradle.api.attributes.AttributeContainer +import org.gradle.api.attributes.* +import org.gradle.api.capabilities.Capability import org.gradle.api.component.AdhocComponentWithVariants import org.gradle.api.component.SoftwareComponentFactory import org.gradle.api.publish.PublishingExtension import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.publish.maven.internal.publication.DefaultMavenPublication -import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.CalculatedCapability +import org.gradle.api.tasks.bundling.AbstractArchiveTask +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages +import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.ComputedCapability import org.jetbrains.kotlin.gradle.plugin.mpp.publishedConfigurationName +import org.jetbrains.kotlin.gradle.plugin.usageByName +import org.jetbrains.kotlin.gradle.tasks.withType import org.jetbrains.kotlin.gradle.utils.dashSeparatedName import javax.inject.Inject @@ -37,7 +42,7 @@ open class VariantPublishingConfigurator @Inject constructor( private val softwareComponentFactory: SoftwareComponentFactory ) { companion object { - fun get(project: Project) = project.objects.newInstance(VariantPublishingConfigurator::class.java, project) + fun get(project: Project): VariantPublishingConfigurator = project.objects.newInstance(VariantPublishingConfigurator::class.java, project) } open fun platformComponentName(variant: KotlinGradleVariant) = variant.disambiguateName("") @@ -59,11 +64,29 @@ open class VariantPublishingConfigurator @Inject constructor( val componentName = platformComponentName(variant) val configurationsMap = inferMavenScopes(variant, publishConfigurations) - // FIXME: add the sources artifact of the variant to the publication!!! - // do that following the Gradle's guidelines on publishing sources variant along library variants, if possible + registerPlatformModulePublication( + componentName, + publishedModuleHolder, + configurationsMap, + variant.containingModule::ifMadePublic + ) - registerPlatformModulePublication(componentName, publishedModuleHolder, configurationsMap, variant.containingModule::ifMadePublic) - registerPlatformVariantsInRootModule(publishedModuleHolder, variant.containingModule, publishConfigurations) + configureSourceElementsPublishing(variant) + + registerPlatformVariantsInRootModule( + publishedModuleHolder, + variant.containingModule, + publishConfigurations + ) + } + + protected open fun configureSourceElementsPublishing(variant: KotlinGradleVariant) { + val configurationName = variant.disambiguateName("sourceElements") + val componentName = platformComponentName(variant) + val docsVariants = DocumentationVariantConfigurator().createSourcesElementsConfiguration(configurationName, variant) + project.components.withType(AdhocComponentWithVariants::class.java).named(componentName).configure { component -> + component.addVariantsFromConfiguration(docsVariants) { } + } } /** @@ -79,7 +102,7 @@ open class VariantPublishingConfigurator @Inject constructor( ) { val platformComponent = softwareComponentFactory.adhoc(componentName) project.components.add(platformComponent) - publishConfigurationsWithMavenScopes.forEach { configurationName, mavenScopeOrNull -> + publishConfigurationsWithMavenScopes.forEach { (configurationName, mavenScopeOrNull) -> platformComponent.addVariantsFromConfiguration(project.configurations.getByName(configurationName)) { variantDetails -> mavenScopeOrNull?.let { variantDetails.mapToMavenScope(it) } } @@ -108,7 +131,7 @@ open class VariantPublishingConfigurator @Inject constructor( val coordinates = publishedModuleHolder.publishedMavenModuleCoordinates (project.dependencies.create("${coordinates.group}:${coordinates.name}:${coordinates.version}") as ModuleDependency).apply { if (kotlinModule.moduleClassifier != null) { - capabilities { it.requireCapability(CalculatedCapability.fromModule(kotlinModule)) } + capabilities { it.requireCapability(ComputedCapability.fromModule(kotlinModule)) } } } } @@ -138,4 +161,44 @@ open class VariantPublishingConfigurator @Inject constructor( } } } +} + +open class DocumentationVariantConfigurator { + open fun createSourcesElementsConfiguration( + project: Project, + configurationName: String, + sourcesArtifactProvider: AbstractArchiveTask, + artifactClassifier: String, + capability: Capability? + ): Configuration { + return project.configurations.create(configurationName).apply { + isCanBeResolved = false + isCanBeConsumed = true +// attributes.attribute(Usage.USAGE_ATTRIBUTE, project.usageByName(KotlinUsages.KOTLIN_SOURCES)) + attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category::class.java, Category.DOCUMENTATION)) + attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, project.objects.named(Bundling::class.java, Bundling.EXTERNAL)) + attributes.attribute(DocsType.DOCS_TYPE_ATTRIBUTE, project.objects.named(DocsType::class.java, DocsType.SOURCES)) + outgoing.artifact(sourcesArtifactProvider) { + it.classifier = artifactClassifier + } + if (capability != null) { + outgoing.capability(capability) + } + } + } + + open fun createSourcesElementsConfiguration( + configurationName: String, + variant: KotlinGradleVariant + ): Configuration { + val sourcesArtifactTask = variant.project.tasks.withType().named(variant.sourceArchiveTaskName) + val artifactClassifier = dashSeparatedName(variant.containingModule.moduleClassifier, "sources") + return createSourcesElementsConfiguration( + variant.project, + configurationName, + sourcesArtifactTask.get(), + artifactClassifier, + ComputedCapability.fromModuleOrNull(variant.containingModule) + ) + } } \ No newline at end of file