Experimental sources publication in the PM2.0 prototype

This commit is contained in:
Sergey Igushkin
2021-04-01 15:21:07 +03:00
parent 44fcd7e891
commit a94597d85a
14 changed files with 166 additions and 64 deletions
@@ -14,6 +14,7 @@ import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
import org.jetbrains.kotlin.project.model.KotlinModuleFragment import org.jetbrains.kotlin.project.model.KotlinModuleFragment
import org.jetbrains.kotlin.project.model.refinesClosure
interface KotlinGradleFragment : KotlinModuleFragment, HasKotlinDependencies, Named { interface KotlinGradleFragment : KotlinModuleFragment, HasKotlinDependencies, Named {
override val kotlinSourceRoots: SourceDirectorySet override val kotlinSourceRoots: SourceDirectorySet
@@ -49,3 +50,6 @@ interface KotlinGradleFragment : KotlinModuleFragment, HasKotlinDependencies, Na
// TODO: resolvable metadata configurations? // TODO: resolvable metadata configurations?
listOf(transitiveApiConfigurationName, transitiveImplementationConfigurationName) listOf(transitiveApiConfigurationName, transitiveImplementationConfigurationName)
} }
val KotlinGradleFragment.refinesClosure: Set<KotlinGradleFragment>
get() = (this as KotlinModuleFragment).refinesClosure.mapTo(mutableSetOf()) { it as KotlinGradleFragment }
@@ -26,7 +26,7 @@ interface KotlinGradleVariant : KotlinGradleFragment, KotlinModuleVariant {
val compilationOutputs: KotlinCompilationOutput val compilationOutputs: KotlinCompilationOutput
// TODO rewrite using our own artifacts API // TODO rewrite using our own artifacts API
val sourceArchiveTask: TaskProvider<AbstractArchiveTask> val sourceArchiveTaskName: String
// TODO generalize exposing outputs: what if a variant has more than one such configurations or none? // TODO generalize exposing outputs: what if a variant has more than one such configurations or none?
val apiElementsConfigurationName: String val apiElementsConfigurationName: String
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinGradleModule 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.NpmDependency
import org.jetbrains.kotlin.gradle.targets.js.npm.directoryNpmDependency import org.jetbrains.kotlin.gradle.targets.js.npm.directoryNpmDependency
import org.jetbrains.kotlin.gradle.targets.js.npm.moduleName import org.jetbrains.kotlin.gradle.targets.js.npm.moduleName
@@ -77,7 +77,7 @@ class DefaultKotlinDependencyHandler(
is KotlinGradleModule -> project.dependencies.create(dependencyNotation.project).apply { is KotlinGradleModule -> project.dependencies.create(dependencyNotation.project).apply {
(this as ModuleDependency).capabilities { (this as ModuleDependency).capabilities {
if (dependencyNotation.moduleClassifier != null) { if (dependencyNotation.moduleClassifier != null) {
it.requireCapability(CalculatedCapability.fromModule(dependencyNotation)) it.requireCapability(ComputedCapability.fromModule(dependencyNotation))
} }
} }
} }
@@ -297,9 +297,14 @@ internal fun sourcesJarTask(
sourceSets: Lazy<Map<String, FileCollection>>, sourceSets: Lazy<Map<String, FileCollection>>,
componentName: String?, componentName: String?,
artifactNameAppendix: String artifactNameAppendix: String
): TaskProvider<Jar> { ): TaskProvider<Jar> = sourcesJarTaskNamed(lowerCamelCaseName(componentName, "sourcesJar"), project, sourceSets, artifactNameAppendix)
val taskName = lowerCamelCaseName(componentName, "sourcesJar")
internal fun sourcesJarTaskNamed(
taskName: String,
project: Project,
sourceSets: Lazy<Map<String, FileCollection>>,
artifactNameAppendix: String
): TaskProvider<Jar> {
project.locateTask<Jar>(taskName)?.let { project.locateTask<Jar>(taskName)?.let {
return it return it
} }
@@ -19,6 +19,7 @@ object KotlinUsages {
const val KOTLIN_API = "kotlin-api" const val KOTLIN_API = "kotlin-api"
const val KOTLIN_RUNTIME = "kotlin-runtime" const val KOTLIN_RUNTIME = "kotlin-runtime"
const val KOTLIN_METADATA = "kotlin-metadata" const val KOTLIN_METADATA = "kotlin-metadata"
const val KOTLIN_SOURCES = "kotlin-sources"
val values = setOf(KOTLIN_API, KOTLIN_RUNTIME) val values = setOf(KOTLIN_API, KOTLIN_RUNTIME)
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.dsl.topLevelExtension import org.jetbrains.kotlin.gradle.dsl.topLevelExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.* 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.gradle.utils.getValue
import org.jetbrains.kotlin.project.model.KotlinModuleIdentifier import org.jetbrains.kotlin.project.model.KotlinModuleIdentifier
import org.jetbrains.kotlin.project.model.LocalModuleIdentifier import org.jetbrains.kotlin.project.model.LocalModuleIdentifier
@@ -88,7 +88,7 @@ internal object ModuleIds {
} }
val capabilities = when (topLevelExtension) { val capabilities = when (topLevelExtension) {
is KotlinMultiplatformExtension -> emptyList() is KotlinMultiplatformExtension -> emptyList()
is KotlinPm20ProjectExtension -> listOfNotNull(CalculatedCapability.capabilityStringFromModule( is KotlinPm20ProjectExtension -> listOfNotNull(ComputedCapability.capabilityStringFromModule(
topLevelExtension.modules.single { it.moduleIdentifier == moduleIdentifier } topLevelExtension.modules.single { it.moduleIdentifier == moduleIdentifier }
)) ))
else -> error("unexpected top-level extension $topLevelExtension") else -> error("unexpected top-level extension $topLevelExtension")
@@ -8,22 +8,32 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.language.base.plugins.LifecycleBasePlugin import org.gradle.language.base.plugins.LifecycleBasePlugin
import org.jetbrains.kotlin.project.model.refinesClosure
import org.jetbrains.kotlin.project.model.utils.variantsContainingFragment import org.jetbrains.kotlin.project.model.utils.variantsContainingFragment
open class VariantSourcesProvider { open class FragmentSourcesProvider {
open fun getSourcesFromRefinesClosure(variant: KotlinGradleVariant): FileCollection { protected open fun getSourcesFromFragmentsAsMap(
val project = variant.containingModule.project fragments: Iterable<KotlinGradleFragment>
return project.files(project.provider { ): Map<KotlinGradleFragment, FileCollection> =
variant.refinesClosure.map { it.kotlinSourceRoots } fragments.associateWith { it.project.files(it.project.provider { it.kotlinSourceRoots }) }
})
}
open fun getCommonSourcesFromRefinesClosure(variant: KotlinGradleVariant): FileCollection { open fun getFragmentOwnSources(fragment: KotlinGradleFragment): FileCollection =
val containingModule = variant.containingModule getSourcesFromFragmentsAsMap(listOf(fragment)).values.single()
open fun getAllFragmentSourcesAsMap(module: KotlinGradleModule): Map<KotlinGradleFragment, FileCollection> =
getSourcesFromFragmentsAsMap(module.fragments)
open fun getSourcesFromRefinesClosureAsMap(fragment: KotlinGradleFragment): Map<KotlinGradleFragment, FileCollection> =
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 val project = containingModule.project
getSourcesFromRefinesClosureAsMap(fragment)
return project.files(project.provider { 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 // 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) containingModule.variantsContainingFragment(it).toSet() != setOf(it)
}.map { it.kotlinSourceRoots } }.map { it.kotlinSourceRoots }
@@ -86,11 +86,13 @@ abstract class KotlinPm20GradlePlugin @Inject constructor(
val project = module.project val project = module.project
val metadataElements = project.configurations.getByName(metadataElementsConfigurationName(module)) val metadataElements = project.configurations.getByName(metadataElementsConfigurationName(module))
val sourceElements = project.configurations.getByName(sourceElementsConfigurationName(module))
val componentName = rootPublicationComponentName(module) val componentName = rootPublicationComponentName(module)
val rootSoftwareComponent = softwareComponentFactory.adhoc(componentName).also { val rootSoftwareComponent = softwareComponentFactory.adhoc(componentName).also {
project.components.add(it) project.components.add(it)
it.addVariantsFromConfiguration(metadataElements) { } it.addVariantsFromConfiguration(metadataElements) { }
it.addVariantsFromConfiguration(sourceElements) { }
} }
module.ifMadePublic { module.ifMadePublic {
@@ -32,9 +32,9 @@ open class KotlinCompilationTaskConfigurator(
fragment: KotlinGradleFragment, fragment: KotlinGradleFragment,
compilationData: KotlinCompilationData<*> compilationData: KotlinCompilationData<*>
): TaskProvider<out KotlinCompile> { ): TaskProvider<out KotlinCompile> {
Kotlin2JvmSourceSetProcessor(KotlinTasksProvider(), compilationData, kotlinPluginVersion).run() Kotlin2JvmSourceSetProcessor(KotlinTasksProvider(), compilationData).run()
val allSources = variantSourcesProvider.getSourcesFromRefinesClosure(variant) val allSources = getSourcesForFragmentCompilation(fragment)
val commonSources = variantSourcesProvider.getCommonSourcesFromRefinesClosure(variant) val commonSources = getCommonSourcesForFragmentCompilation(fragment)
// FIXME support custom source file extensions in the two calls below // FIXME support custom source file extensions in the two calls below
addSourcesToKotlinCompileTask(project, compilationData.compileKotlinTaskName, emptyList()) { allSources } addSourcesToKotlinCompileTask(project, compilationData.compileKotlinTaskName, emptyList()) { allSources }
@@ -49,8 +49,8 @@ open class KotlinCompilationTaskConfigurator(
): TaskProvider<KotlinNativeCompile> { ): TaskProvider<KotlinNativeCompile> {
val compileTask = KotlinNativeTargetConfigurator.createKlibCompilationTask(compilationData) val compileTask = KotlinNativeTargetConfigurator.createKlibCompilationTask(compilationData)
val allSources = variantSourcesProvider.getSourcesFromRefinesClosure(variant) val allSources = getSourcesForFragmentCompilation(fragment)
val commonSources = variantSourcesProvider.getSourcesFromRefinesClosure(variant) val commonSources = getCommonSourcesForFragmentCompilation(fragment)
compileTask.configure { compileTask.configure {
it.source(allSources) it.source(allSources)
@@ -5,28 +5,15 @@
package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 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.Configuration
import org.gradle.api.artifacts.ModuleDependency import org.gradle.api.attributes.Bundling
import org.gradle.api.attributes.Attribute import org.gradle.api.attributes.Category
import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.attributes.Usage 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.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages 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.pm20.util.ComputedCapability
import org.jetbrains.kotlin.gradle.plugin.mpp.publishedConfigurationName import org.jetbrains.kotlin.gradle.plugin.mpp.sourcesJarTaskNamed
import org.jetbrains.kotlin.gradle.plugin.mpp.sourcesJarTask
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation 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<T : KotlinGradleVariant>( abstract class AbstractKotlinGradleVariantFactory<T : KotlinGradleVariant>(
module: KotlinGradleModule module: KotlinGradleModule
@@ -51,17 +38,21 @@ abstract class AbstractKotlinGradleVariantFactory<T : KotlinGradleVariant>(
open fun configureApiElementsConfiguration(fragment: T, configuration: Configuration) { open fun configureApiElementsConfiguration(fragment: T, configuration: Configuration) {
setPlatformAttributesInConfiguration(fragment, 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) abstract fun configureKotlinCompilation(fragment: T)
open fun createSourcesArchiveTask(fragment: T) { open fun createSourcesArchiveTask(fragment: T) {
sourcesJarTask( sourcesJarTaskNamed(
fragment.sourceArchiveTaskName,
project, project,
lazy { fragment.refinesClosure.associate { it.disambiguateName("") to project.files(it.kotlinSourceRoots) } }, lazy { FragmentSourcesProvider().getSourcesFromRefinesClosureAsMap(fragment).mapKeys { it.key.fragmentName } },
fragment.name, fragment.name
fragment.name.toLowerCase()
) )
} }
@@ -104,7 +95,11 @@ abstract class AbstractKotlinGradleVariantWithRuntimeFactory<T : KotlinGradleVar
open fun configureRuntimeElementsConfiguration(fragment: T, configuration: Configuration) { open fun configureRuntimeElementsConfiguration(fragment: T, configuration: Configuration) {
setPlatformAttributesInConfiguration(fragment, configuration) setPlatformAttributesInConfiguration(fragment, configuration)
configuration.attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerRuntimeUsage(project, fragment.platformType)) configuration.attributes.apply {
attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerRuntimeUsage(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))
}
} }
override fun createDependencyConfigurations(fragment: T) { override fun createDependencyConfigurations(fragment: T) {
@@ -153,6 +148,6 @@ abstract class AbstractKotlinGradleRuntimePublishedVariantFactory<T : KotlinGrad
internal fun setModuleCapability(configuration: Configuration, module: KotlinGradleModule) { internal fun setModuleCapability(configuration: Configuration, module: KotlinGradleModule) {
if (module.moduleClassifier != null) { if (module.moduleClassifier != null) {
configuration.outgoing.capability(CalculatedCapability.fromModule(module)) configuration.outgoing.capability(ComputedCapability.fromModule(module))
} }
} }
@@ -15,7 +15,7 @@ import org.gradle.api.tasks.bundling.AbstractArchiveTask
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinCompilationOutput import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinCompilationOutput
import org.jetbrains.kotlin.gradle.plugin.mpp.MavenPublicationCoordinatesProvider import org.jetbrains.kotlin.gradle.plugin.mpp.MavenPublicationCoordinatesProvider
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.plugin.mpp.publishedConfigurationName import org.jetbrains.kotlin.gradle.plugin.mpp.publishedConfigurationName
import org.jetbrains.kotlin.gradle.tasks.withType import org.jetbrains.kotlin.gradle.tasks.withType
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
@@ -49,8 +49,8 @@ abstract class KotlinGradleVariantInternal(
) )
// TODO rewrite using our own artifacts API // TODO rewrite using our own artifacts API
override val sourceArchiveTask: TaskProvider<AbstractArchiveTask> override val sourceArchiveTaskName: String
get() = project.tasks.withType<AbstractArchiveTask>().named(defaultSourceArtifactTaskName) get() = defaultSourceArtifactTaskName
// TODO generalize exposing outputs: what if a variant has more than one such configurations or none? // TODO generalize exposing outputs: what if a variant has more than one such configurations or none?
override val apiElementsConfigurationName: String override val apiElementsConfigurationName: String
@@ -81,7 +81,7 @@ class DefaultSingleMavenPublishedModuleHolder(
project, project,
{ assignedMavenPublication }, { assignedMavenPublication },
defaultPublishedModuleSuffix, defaultPublishedModuleSuffix,
capabilities = listOfNotNull(CalculatedCapability.capabilityStringFromModule(module)) capabilities = listOfNotNull(ComputedCapability.capabilityStringFromModule(module))
) )
} }
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.gradle.dsl.pm20Extension
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.KotlinCommonSourceSetProcessor import org.jetbrains.kotlin.gradle.plugin.KotlinCommonSourceSetProcessor
import org.jetbrains.kotlin.gradle.plugin.mpp.* 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.NativeSharedCompilationProcessor
import org.jetbrains.kotlin.gradle.targets.metadata.createGenerateProjectStructureMetadataTask import org.jetbrains.kotlin.gradle.targets.metadata.createGenerateProjectStructureMetadataTask
import org.jetbrains.kotlin.gradle.targets.metadata.filesWithUnpackedArchives 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.registerTask
import org.jetbrains.kotlin.gradle.tasks.withType import org.jetbrains.kotlin.gradle.tasks.withType
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation 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.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION
import org.jetbrains.kotlin.project.model.KotlinModuleFragment import org.jetbrains.kotlin.project.model.KotlinModuleFragment
@@ -58,11 +60,26 @@ internal fun configureMetadataExposure(module: KotlinGradleModule) {
} }
setModuleCapability(this, module) 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) = fun metadataElementsConfigurationName(module: KotlinGradleModule) =
module.disambiguateName("metadataElements") module.disambiguateName("metadataElements")
fun sourceElementsConfigurationName(module: KotlinGradleModule) =
module.disambiguateName("sourceElements")
private fun generateAndExportProjectStructureMetadata( private fun generateAndExportProjectStructureMetadata(
module: KotlinGradleModule module: KotlinGradleModule
) { ) {
@@ -9,7 +9,7 @@ import org.gradle.api.capabilities.Capability
import org.gradle.api.provider.Provider import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinGradleModule import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinGradleModule
internal class CalculatedCapability( internal class ComputedCapability(
val groupProvider: Provider<String>, val groupProvider: Provider<String>,
val nameValue: String, val nameValue: String,
val versionProvider: Provider<String>, val versionProvider: Provider<String>,
@@ -22,9 +22,9 @@ internal class CalculatedCapability(
override fun getVersion(): String? = versionProvider.get() override fun getVersion(): String? = versionProvider.get()
companion object { companion object {
fun fromModule(module: KotlinGradleModule): CalculatedCapability { fun fromModule(module: KotlinGradleModule): ComputedCapability {
val project = module.project val project = module.project
return CalculatedCapability( return ComputedCapability(
project.provider { project.group.toString() }, project.provider { project.group.toString() },
project.name, project.name,
project.provider { project.version.toString() }, 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? = fun capabilityStringFromModule(module: KotlinGradleModule): String? =
if (module.moduleClassifier != null) fromModule(module).notation() else null if (module.moduleClassifier != null) fromModule(module).notation() else null
} }
@@ -6,16 +6,21 @@
package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.ModuleDependency import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.attributes.Attribute import org.gradle.api.attributes.*
import org.gradle.api.attributes.AttributeContainer import org.gradle.api.capabilities.Capability
import org.gradle.api.component.AdhocComponentWithVariants import org.gradle.api.component.AdhocComponentWithVariants
import org.gradle.api.component.SoftwareComponentFactory import org.gradle.api.component.SoftwareComponentFactory
import org.gradle.api.publish.PublishingExtension import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.internal.publication.DefaultMavenPublication 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.mpp.publishedConfigurationName
import org.jetbrains.kotlin.gradle.plugin.usageByName
import org.jetbrains.kotlin.gradle.tasks.withType
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
import javax.inject.Inject import javax.inject.Inject
@@ -37,7 +42,7 @@ open class VariantPublishingConfigurator @Inject constructor(
private val softwareComponentFactory: SoftwareComponentFactory private val softwareComponentFactory: SoftwareComponentFactory
) { ) {
companion object { 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("") open fun platformComponentName(variant: KotlinGradleVariant) = variant.disambiguateName("")
@@ -59,11 +64,29 @@ open class VariantPublishingConfigurator @Inject constructor(
val componentName = platformComponentName(variant) val componentName = platformComponentName(variant)
val configurationsMap = inferMavenScopes(variant, publishConfigurations) val configurationsMap = inferMavenScopes(variant, publishConfigurations)
// FIXME: add the sources artifact of the variant to the publication!!! registerPlatformModulePublication(
// do that following the Gradle's guidelines on publishing sources variant along library variants, if possible componentName,
publishedModuleHolder,
configurationsMap,
variant.containingModule::ifMadePublic
)
registerPlatformModulePublication(componentName, publishedModuleHolder, configurationsMap, variant.containingModule::ifMadePublic) configureSourceElementsPublishing(variant)
registerPlatformVariantsInRootModule(publishedModuleHolder, variant.containingModule, publishConfigurations)
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) val platformComponent = softwareComponentFactory.adhoc(componentName)
project.components.add(platformComponent) project.components.add(platformComponent)
publishConfigurationsWithMavenScopes.forEach { configurationName, mavenScopeOrNull -> publishConfigurationsWithMavenScopes.forEach { (configurationName, mavenScopeOrNull) ->
platformComponent.addVariantsFromConfiguration(project.configurations.getByName(configurationName)) { variantDetails -> platformComponent.addVariantsFromConfiguration(project.configurations.getByName(configurationName)) { variantDetails ->
mavenScopeOrNull?.let { variantDetails.mapToMavenScope(it) } mavenScopeOrNull?.let { variantDetails.mapToMavenScope(it) }
} }
@@ -108,7 +131,7 @@ open class VariantPublishingConfigurator @Inject constructor(
val coordinates = publishedModuleHolder.publishedMavenModuleCoordinates val coordinates = publishedModuleHolder.publishedMavenModuleCoordinates
(project.dependencies.create("${coordinates.group}:${coordinates.name}:${coordinates.version}") as ModuleDependency).apply { (project.dependencies.create("${coordinates.group}:${coordinates.name}:${coordinates.version}") as ModuleDependency).apply {
if (kotlinModule.moduleClassifier != null) { 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<AbstractArchiveTask>().named(variant.sourceArchiveTaskName)
val artifactClassifier = dashSeparatedName(variant.containingModule.moduleClassifier, "sources")
return createSourcesElementsConfiguration(
variant.project,
configurationName,
sourcesArtifactTask.get(),
artifactClassifier,
ComputedCapability.fromModuleOrNull(variant.containingModule)
)
}
} }