Extract custom publishing dsl to buildsrc-compat
It will be used also in kotlin-test KT-61969
This commit is contained in:
committed by
Space Team
parent
38ed3216fd
commit
f3240757ed
@@ -1,6 +1,4 @@
|
|||||||
@file:Suppress("UNUSED_VARIABLE", "NAME_SHADOWING")
|
@file:Suppress("UNUSED_VARIABLE", "NAME_SHADOWING")
|
||||||
import org.gradle.api.internal.component.SoftwareComponentInternal
|
|
||||||
import org.gradle.api.internal.component.UsageContext
|
|
||||||
import org.gradle.jvm.tasks.Jar
|
import org.gradle.jvm.tasks.Jar
|
||||||
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
|
||||||
@@ -13,6 +11,7 @@ import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
|||||||
import org.jetbrains.kotlin.gradle.tasks.UsesKotlinJavaToolchain
|
import org.jetbrains.kotlin.gradle.tasks.UsesKotlinJavaToolchain
|
||||||
import plugins.configureDefaultPublishing
|
import plugins.configureDefaultPublishing
|
||||||
import plugins.configureKotlinPomAttributes
|
import plugins.configureKotlinPomAttributes
|
||||||
|
import plugins.publishing.*
|
||||||
import kotlin.io.path.copyTo
|
import kotlin.io.path.copyTo
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
@@ -789,11 +788,6 @@ tasks {
|
|||||||
|
|
||||||
configureDefaultPublishing()
|
configureDefaultPublishing()
|
||||||
|
|
||||||
open class ComponentsFactoryAccess
|
|
||||||
@javax.inject.Inject
|
|
||||||
constructor(val factory: SoftwareComponentFactory)
|
|
||||||
|
|
||||||
val componentFactory = objects.newInstance<ComponentsFactoryAccess>().factory
|
|
||||||
|
|
||||||
val emptyJavadocJar by tasks.creating(org.gradle.api.tasks.bundling.Jar::class) {
|
val emptyJavadocJar by tasks.creating(org.gradle.api.tasks.bundling.Jar::class) {
|
||||||
archiveClassifier.set("javadoc")
|
archiveClassifier.set("javadoc")
|
||||||
@@ -906,173 +900,6 @@ publishing {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun copyAttributes(from: AttributeContainer, to: AttributeContainer,) {
|
|
||||||
// capture type argument T
|
|
||||||
fun <T : Any> copyOneAttribute(from: AttributeContainer, to: AttributeContainer, key: Attribute<T>) {
|
|
||||||
val value = checkNotNull(from.getAttribute(key))
|
|
||||||
to.attribute(key, value)
|
|
||||||
}
|
|
||||||
for (key in from.keySet()) {
|
|
||||||
copyOneAttribute(from, to, key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MultiModuleMavenPublishingConfiguration() {
|
|
||||||
val modules = mutableMapOf<String, Module>()
|
|
||||||
|
|
||||||
class Module(val name: String) {
|
|
||||||
val variants = mutableMapOf<String, Variant>()
|
|
||||||
val includes = mutableSetOf<Module>()
|
|
||||||
|
|
||||||
class Variant(
|
|
||||||
val configurationName: String
|
|
||||||
) {
|
|
||||||
var name: String = configurationName
|
|
||||||
val attributesConfigurations = mutableListOf<AttributeContainer.() -> Unit>()
|
|
||||||
fun attributes(code: AttributeContainer.() -> Unit) {
|
|
||||||
attributesConfigurations += code
|
|
||||||
}
|
|
||||||
|
|
||||||
val artifactsWithConfigurations = mutableListOf<Pair<Any, ConfigurablePublishArtifact.() -> Unit>>()
|
|
||||||
fun artifact(file: Any, code: ConfigurablePublishArtifact.() -> Unit = {}) {
|
|
||||||
artifactsWithConfigurations += file to code
|
|
||||||
}
|
|
||||||
|
|
||||||
val configurationConfigurations = mutableListOf<Configuration.() -> Unit>()
|
|
||||||
fun configuration(code: Configuration.() -> Unit) {
|
|
||||||
configurationConfigurations += code
|
|
||||||
}
|
|
||||||
|
|
||||||
val variantDetailsConfigurations = mutableListOf<ConfigurationVariantDetails.() -> Unit>()
|
|
||||||
fun configureVariantDetails(code: ConfigurationVariantDetails.() -> Unit) {
|
|
||||||
variantDetailsConfigurations += code
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val mavenPublicationConfigurations = mutableListOf<MavenPublication.() -> Unit>()
|
|
||||||
fun mavenPublication(code: MavenPublication.() -> Unit) {
|
|
||||||
mavenPublicationConfigurations += code
|
|
||||||
}
|
|
||||||
|
|
||||||
fun variant(fromConfigurationName: String, code: Variant.() -> Unit = {}): Variant {
|
|
||||||
val variant = variants.getOrPut(fromConfigurationName) { Variant(fromConfigurationName) }
|
|
||||||
variant.code()
|
|
||||||
return variant
|
|
||||||
}
|
|
||||||
|
|
||||||
fun include(vararg modules: Module) {
|
|
||||||
includes.addAll(modules)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun module(name: String, code: Module.() -> Unit): Module {
|
|
||||||
val module = modules.getOrPut(name) { Module(name) }
|
|
||||||
module.code()
|
|
||||||
return module
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun configureMultiModuleMavenPublishing(code: MultiModuleMavenPublishingConfiguration.() -> Unit) {
|
|
||||||
val publishingConfiguration = MultiModuleMavenPublishingConfiguration()
|
|
||||||
publishingConfiguration.code()
|
|
||||||
|
|
||||||
val components = publishingConfiguration
|
|
||||||
.modules
|
|
||||||
.mapValues { (_, module) -> project.createModulePublication(module) }
|
|
||||||
|
|
||||||
val componentsWithExternals = publishingConfiguration
|
|
||||||
.modules
|
|
||||||
.filter { (_, module) -> module.includes.isNotEmpty() }
|
|
||||||
.mapValues { (moduleName, module) ->
|
|
||||||
val mainComponent = components[moduleName] ?: error("Component with name $moduleName wasn't created")
|
|
||||||
val externalComponents = module.includes
|
|
||||||
.map { components[it.name] ?: error("Component with name ${it.name} wasn't created") }
|
|
||||||
.toSet()
|
|
||||||
ComponentWithExternalVariants(mainComponent, externalComponents)
|
|
||||||
}
|
|
||||||
|
|
||||||
// override some components wih items from componentsWithExternals
|
|
||||||
val mergedComponents = components + componentsWithExternals
|
|
||||||
|
|
||||||
val publicationsContainer = publishing.publications
|
|
||||||
for ((componentName, component) in mergedComponents) {
|
|
||||||
publicationsContainer.create<MavenPublication>(componentName) {
|
|
||||||
from(component)
|
|
||||||
val module = publishingConfiguration.modules[componentName]!!
|
|
||||||
module.mavenPublicationConfigurations.forEach { configure -> configure() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun Project.createModulePublication(module: MultiModuleMavenPublishingConfiguration.Module): SoftwareComponent {
|
|
||||||
val component = componentFactory.adhoc(module.name)
|
|
||||||
module.variants.values.forEach { addVariant(component, it) }
|
|
||||||
|
|
||||||
val newNames = module.variants.map { it.key to it.value.name }.filter { it.first != it.second }.toMap()
|
|
||||||
return if (newNames.isNotEmpty()) {
|
|
||||||
ComponentWithRenamedVariants(newNames, component as SoftwareComponentInternal)
|
|
||||||
} else {
|
|
||||||
component
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Project.addVariant(component: AdhocComponentWithVariants, variant: MultiModuleMavenPublishingConfiguration.Module.Variant) {
|
|
||||||
val configuration = configurations.getOrCreate(variant.configurationName)
|
|
||||||
configuration.apply {
|
|
||||||
isCanBeResolved = false
|
|
||||||
isCanBeConsumed = true
|
|
||||||
|
|
||||||
variant.attributesConfigurations.forEach { configure -> attributes.configure() }
|
|
||||||
}
|
|
||||||
|
|
||||||
for ((artifactNotation, configure) in variant.artifactsWithConfigurations) {
|
|
||||||
artifacts.add(configuration.name, artifactNotation) {
|
|
||||||
configure()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (configure in variant.configurationConfigurations) {
|
|
||||||
configuration.apply(configure)
|
|
||||||
}
|
|
||||||
|
|
||||||
component.addVariantsFromConfiguration(configuration) {
|
|
||||||
variant.variantDetailsConfigurations.forEach { configure -> configure() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class RenamedVariant(val newName: String, context: UsageContext) : UsageContext by context {
|
|
||||||
override fun getName(): String = newName
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ComponentWithRenamedVariants(
|
|
||||||
val newNames: Map<String, String>,
|
|
||||||
private val base: SoftwareComponentInternal
|
|
||||||
): SoftwareComponentInternal by base {
|
|
||||||
|
|
||||||
override fun getName(): String = base.name
|
|
||||||
override fun getUsages(): Set<UsageContext> {
|
|
||||||
return base.usages.map {
|
|
||||||
val newName = newNames[it.name]
|
|
||||||
if (newName != null) {
|
|
||||||
RenamedVariant(newName, it)
|
|
||||||
} else {
|
|
||||||
it
|
|
||||||
}
|
|
||||||
}.toSet()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ComponentWithExternalVariants(
|
|
||||||
private val mainComponent: SoftwareComponent,
|
|
||||||
private val externalComponents: Set<SoftwareComponent>
|
|
||||||
) : ComponentWithVariants, SoftwareComponentInternal {
|
|
||||||
override fun getName(): String = mainComponent.name
|
|
||||||
|
|
||||||
override fun getUsages(): Set<UsageContext> = (mainComponent as SoftwareComponentInternal).usages
|
|
||||||
|
|
||||||
override fun getVariants(): Set<SoftwareComponent> = externalComponents
|
|
||||||
}
|
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
|
|
||||||
|
|||||||
+199
@@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* 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 plugins.publishing
|
||||||
|
|
||||||
|
import getOrCreate
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.artifacts.ConfigurablePublishArtifact
|
||||||
|
import org.gradle.api.artifacts.Configuration
|
||||||
|
import org.gradle.api.attributes.Attribute
|
||||||
|
import org.gradle.api.attributes.AttributeContainer
|
||||||
|
import org.gradle.api.component.*
|
||||||
|
import org.gradle.api.internal.component.SoftwareComponentInternal
|
||||||
|
import org.gradle.api.internal.component.UsageContext
|
||||||
|
import org.gradle.api.publish.PublishingExtension
|
||||||
|
import org.gradle.api.publish.maven.MavenPublication
|
||||||
|
import org.gradle.kotlin.dsl.create
|
||||||
|
import org.gradle.kotlin.dsl.extra
|
||||||
|
import org.gradle.kotlin.dsl.getByType
|
||||||
|
import org.gradle.kotlin.dsl.newInstance
|
||||||
|
|
||||||
|
private open class ComponentsFactoryAccess
|
||||||
|
@javax.inject.Inject
|
||||||
|
constructor(val factory: SoftwareComponentFactory)
|
||||||
|
|
||||||
|
val Project.componentFactory: SoftwareComponentFactory
|
||||||
|
get() = findProperty("_componentFactory") as SoftwareComponentFactory?
|
||||||
|
?: objects.newInstance<ComponentsFactoryAccess>().factory
|
||||||
|
.also { project.extra["_componentFactory"] = it }
|
||||||
|
|
||||||
|
fun copyAttributes(from: AttributeContainer, to: AttributeContainer,) {
|
||||||
|
// capture type argument T
|
||||||
|
fun <T : Any> copyOneAttribute(from: AttributeContainer, to: AttributeContainer, key: Attribute<T>) {
|
||||||
|
val value = checkNotNull(from.getAttribute(key))
|
||||||
|
to.attribute(key, value)
|
||||||
|
}
|
||||||
|
for (key in from.keySet()) {
|
||||||
|
copyOneAttribute(from, to, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MultiModuleMavenPublishingConfiguration() {
|
||||||
|
val modules = mutableMapOf<String, Module>()
|
||||||
|
|
||||||
|
class Module(val name: String) {
|
||||||
|
val variants = mutableMapOf<String, Variant>()
|
||||||
|
val includes = mutableSetOf<Module>()
|
||||||
|
|
||||||
|
class Variant(
|
||||||
|
val configurationName: String
|
||||||
|
) {
|
||||||
|
var name: String = configurationName
|
||||||
|
val attributesConfigurations = mutableListOf<AttributeContainer.() -> Unit>()
|
||||||
|
fun attributes(code: AttributeContainer.() -> Unit) {
|
||||||
|
attributesConfigurations += code
|
||||||
|
}
|
||||||
|
|
||||||
|
val artifactsWithConfigurations = mutableListOf<Pair<Any, ConfigurablePublishArtifact.() -> Unit>>()
|
||||||
|
fun artifact(file: Any, code: ConfigurablePublishArtifact.() -> Unit = {}) {
|
||||||
|
artifactsWithConfigurations += file to code
|
||||||
|
}
|
||||||
|
|
||||||
|
val configurationConfigurations = mutableListOf<Configuration.() -> Unit>()
|
||||||
|
fun configuration(code: Configuration.() -> Unit) {
|
||||||
|
configurationConfigurations += code
|
||||||
|
}
|
||||||
|
|
||||||
|
val variantDetailsConfigurations = mutableListOf<ConfigurationVariantDetails.() -> Unit>()
|
||||||
|
fun configureVariantDetails(code: ConfigurationVariantDetails.() -> Unit) {
|
||||||
|
variantDetailsConfigurations += code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val mavenPublicationConfigurations = mutableListOf<MavenPublication.() -> Unit>()
|
||||||
|
fun mavenPublication(code: MavenPublication.() -> Unit) {
|
||||||
|
mavenPublicationConfigurations += code
|
||||||
|
}
|
||||||
|
|
||||||
|
fun variant(fromConfigurationName: String, code: Variant.() -> Unit = {}): Variant {
|
||||||
|
val variant = variants.getOrPut(fromConfigurationName) { Variant(fromConfigurationName) }
|
||||||
|
variant.code()
|
||||||
|
return variant
|
||||||
|
}
|
||||||
|
|
||||||
|
fun include(vararg modules: Module) {
|
||||||
|
includes.addAll(modules)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun module(name: String, code: Module.() -> Unit): Module {
|
||||||
|
val module = modules.getOrPut(name) { Module(name) }
|
||||||
|
module.code()
|
||||||
|
return module
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Project.configureMultiModuleMavenPublishing(code: MultiModuleMavenPublishingConfiguration.() -> Unit) {
|
||||||
|
val publishingConfiguration = MultiModuleMavenPublishingConfiguration()
|
||||||
|
publishingConfiguration.code()
|
||||||
|
|
||||||
|
val components = publishingConfiguration
|
||||||
|
.modules
|
||||||
|
.mapValues { (_, module) -> project.createModulePublication(module) }
|
||||||
|
|
||||||
|
val componentsWithExternals = publishingConfiguration
|
||||||
|
.modules
|
||||||
|
.filter { (_, module) -> module.includes.isNotEmpty() }
|
||||||
|
.mapValues { (moduleName, module) ->
|
||||||
|
val mainComponent = components[moduleName] ?: error("Component with name $moduleName wasn't created")
|
||||||
|
val externalComponents = module.includes
|
||||||
|
.map { components[it.name] ?: error("Component with name ${it.name} wasn't created") }
|
||||||
|
.toSet()
|
||||||
|
ComponentWithExternalVariants(mainComponent, externalComponents)
|
||||||
|
}
|
||||||
|
|
||||||
|
// override some components wih items from componentsWithExternals
|
||||||
|
val mergedComponents = components + componentsWithExternals
|
||||||
|
|
||||||
|
val publicationsContainer = project.extensions.getByType<PublishingExtension>().publications
|
||||||
|
for ((componentName, component) in mergedComponents) {
|
||||||
|
publicationsContainer.create<MavenPublication>(componentName) {
|
||||||
|
from(component)
|
||||||
|
val module = publishingConfiguration.modules[componentName]!!
|
||||||
|
module.mavenPublicationConfigurations.forEach { configure -> configure() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun Project.createModulePublication(module: MultiModuleMavenPublishingConfiguration.Module): SoftwareComponent {
|
||||||
|
val component = componentFactory.adhoc(module.name)
|
||||||
|
module.variants.values.forEach { addVariant(component, it) }
|
||||||
|
|
||||||
|
val newNames = module.variants.map { it.key to it.value.name }.filter { it.first != it.second }.toMap()
|
||||||
|
return if (newNames.isNotEmpty()) {
|
||||||
|
ComponentWithRenamedVariants(newNames, component as SoftwareComponentInternal)
|
||||||
|
} else {
|
||||||
|
component
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Project.addVariant(component: AdhocComponentWithVariants, variant: MultiModuleMavenPublishingConfiguration.Module.Variant) {
|
||||||
|
val configuration = configurations.getOrCreate(variant.configurationName)
|
||||||
|
configuration.apply {
|
||||||
|
isCanBeResolved = false
|
||||||
|
isCanBeConsumed = true
|
||||||
|
|
||||||
|
variant.attributesConfigurations.forEach { configure -> attributes.configure() }
|
||||||
|
}
|
||||||
|
|
||||||
|
for ((artifactNotation, configure) in variant.artifactsWithConfigurations) {
|
||||||
|
artifacts.add(configuration.name, artifactNotation) {
|
||||||
|
configure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (configure in variant.configurationConfigurations) {
|
||||||
|
configuration.apply(configure)
|
||||||
|
}
|
||||||
|
|
||||||
|
component.addVariantsFromConfiguration(configuration) {
|
||||||
|
variant.variantDetailsConfigurations.forEach { configure -> configure() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RenamedVariant(val newName: String, context: UsageContext) : UsageContext by context {
|
||||||
|
override fun getName(): String = newName
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ComponentWithRenamedVariants(
|
||||||
|
val newNames: Map<String, String>,
|
||||||
|
private val base: SoftwareComponentInternal
|
||||||
|
): SoftwareComponentInternal by base {
|
||||||
|
|
||||||
|
override fun getName(): String = base.name
|
||||||
|
override fun getUsages(): Set<UsageContext> {
|
||||||
|
return base.usages.map {
|
||||||
|
val newName = newNames[it.name]
|
||||||
|
if (newName != null) {
|
||||||
|
RenamedVariant(newName, it)
|
||||||
|
} else {
|
||||||
|
it
|
||||||
|
}
|
||||||
|
}.toSet()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class ComponentWithExternalVariants(
|
||||||
|
private val mainComponent: SoftwareComponent,
|
||||||
|
private val externalComponents: Set<SoftwareComponent>
|
||||||
|
) : ComponentWithVariants, SoftwareComponentInternal {
|
||||||
|
override fun getName(): String = mainComponent.name
|
||||||
|
|
||||||
|
override fun getUsages(): Set<UsageContext> = (mainComponent as SoftwareComponentInternal).usages
|
||||||
|
|
||||||
|
override fun getVariants(): Set<SoftwareComponent> = externalComponents
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user