Remove KotlinMetadataTarget's KotlinTargetComponent in favour of KotlinSoftwareComponent.kt
^KT-44322 fixed
This commit is contained in:
committed by
Space
parent
9a5791ad6d
commit
bf5feb1b4a
+35
-25
@@ -714,16 +714,18 @@ class NewMultiplatformIT : BaseGradleIT() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gradleBuildScript().appendText("\n" + """
|
gradleBuildScript().appendText(
|
||||||
|
"\n" + """
|
||||||
kotlin.sourceSets.all {
|
kotlin.sourceSets.all {
|
||||||
it.languageSettings {
|
it.languageSettings {
|
||||||
languageVersion = '1.3'
|
languageVersion = '1.3'
|
||||||
apiVersion = '1.3'
|
apiVersion = '1.3'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
""".trimIndent())
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
listOf( "compileKotlinMetadata", "compileKotlinJvm6", "compileKotlinNodeJs").forEach {
|
listOf("compileKotlinMetadata", "compileKotlinJvm6", "compileKotlinNodeJs").forEach {
|
||||||
build(it) {
|
build(it) {
|
||||||
assertSuccessful()
|
assertSuccessful()
|
||||||
assertTasksExecuted(":$it")
|
assertTasksExecuted(":$it")
|
||||||
@@ -1015,15 +1017,20 @@ class NewMultiplatformIT : BaseGradleIT() {
|
|||||||
assertSuccessful()
|
assertSuccessful()
|
||||||
|
|
||||||
val groupDir = projectDir.resolve("repo/com/example/")
|
val groupDir = projectDir.resolve("repo/com/example/")
|
||||||
val targetArtifactIdAppendices = listOf("metadata", "jvm6", "nodejs", "linux64")
|
val targetArtifactIdAppendices = listOf(null, "jvm6", "nodejs", "linux64")
|
||||||
|
|
||||||
val sourceJarSourceRoots = targetArtifactIdAppendices.associate { artifact ->
|
val sourceJarSourceRoots = targetArtifactIdAppendices.associateWith { artifact ->
|
||||||
val sourcesJar = JarFile(groupDir.resolve("sample-lib-$artifact/1.0/sample-lib-$artifact-1.0-sources.jar"))
|
val sourcesJarPath = if (artifact != null) "sample-lib-$artifact/1.0/sample-lib-$artifact-1.0-sources.jar"
|
||||||
|
else "sample-lib/1.0/sample-lib-1.0-sources.jar"
|
||||||
|
val sourcesJar = JarFile(groupDir.resolve(sourcesJarPath))
|
||||||
val sourcesDirs = sourcesJar.entries().asSequence().map { it.name.substringBefore("/") }.toSet() - "META-INF"
|
val sourcesDirs = sourcesJar.entries().asSequence().map { it.name.substringBefore("/") }.toSet() - "META-INF"
|
||||||
artifact to sourcesDirs
|
sourcesDirs
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(setOf("commonMain"), sourceJarSourceRoots["metadata"])
|
assertEquals(
|
||||||
|
setOf("commonMain", "jvm6Main", "linux64Main", "macos64Main", "mingw64Main", "mingw86Main", "nodeJsMain"),
|
||||||
|
sourceJarSourceRoots[null]
|
||||||
|
)
|
||||||
assertEquals(setOf("commonMain", "jvm6Main"), sourceJarSourceRoots["jvm6"])
|
assertEquals(setOf("commonMain", "jvm6Main"), sourceJarSourceRoots["jvm6"])
|
||||||
assertEquals(setOf("commonMain", "nodeJsMain"), sourceJarSourceRoots["nodejs"])
|
assertEquals(setOf("commonMain", "nodeJsMain"), sourceJarSourceRoots["nodejs"])
|
||||||
assertEquals(setOf("commonMain", "linux64Main"), sourceJarSourceRoots["linux64"])
|
assertEquals(setOf("commonMain", "linux64Main"), sourceJarSourceRoots["linux64"])
|
||||||
@@ -1361,26 +1368,29 @@ class NewMultiplatformIT : BaseGradleIT() {
|
|||||||
fun testDependenciesDsl() = with(transformProjectWithPluginsDsl("newMppDependenciesDsl")) {
|
fun testDependenciesDsl() = with(transformProjectWithPluginsDsl("newMppDependenciesDsl")) {
|
||||||
val originalBuildscriptContent = gradleBuildScript("app").readText()
|
val originalBuildscriptContent = gradleBuildScript("app").readText()
|
||||||
|
|
||||||
fun testDependencies() = testResolveAllConfigurations("app", options = defaultBuildOptions().copy(warningMode = WarningMode.Summary)) {
|
fun testDependencies() =
|
||||||
assertContains(">> :app:testNonTransitiveStringNotationApiDependenciesMetadata --> junit-4.12.jar")
|
testResolveAllConfigurations("app", options = defaultBuildOptions().copy(warningMode = WarningMode.Summary)) {
|
||||||
assertEquals(
|
assertContains(">> :app:testNonTransitiveStringNotationApiDependenciesMetadata --> junit-4.12.jar")
|
||||||
1,
|
assertEquals(
|
||||||
(Regex.escape(">> :app:testNonTransitiveStringNotationApiDependenciesMetadata") + " .*").toRegex().findAll(output).count()
|
1,
|
||||||
)
|
(Regex.escape(">> :app:testNonTransitiveStringNotationApiDependenciesMetadata") + " .*").toRegex().findAll(output)
|
||||||
|
.count()
|
||||||
|
)
|
||||||
|
|
||||||
assertContains(">> :app:testNonTransitiveDependencyNotationApiDependenciesMetadata --> kotlin-reflect-${defaultBuildOptions().kotlinVersion}.jar")
|
assertContains(">> :app:testNonTransitiveDependencyNotationApiDependenciesMetadata --> kotlin-reflect-${defaultBuildOptions().kotlinVersion}.jar")
|
||||||
assertEquals(
|
assertEquals(
|
||||||
1,
|
1,
|
||||||
(Regex.escape(">> :app:testNonTransitiveStringNotationApiDependenciesMetadata") + " .*").toRegex().findAll(output).count()
|
(Regex.escape(">> :app:testNonTransitiveStringNotationApiDependenciesMetadata") + " .*").toRegex().findAll(output)
|
||||||
)
|
.count()
|
||||||
|
)
|
||||||
|
|
||||||
assertContains(">> :app:testExplicitKotlinVersionApiDependenciesMetadata --> kotlin-reflect-1.3.0.jar")
|
assertContains(">> :app:testExplicitKotlinVersionApiDependenciesMetadata --> kotlin-reflect-1.3.0.jar")
|
||||||
assertContains(">> :app:testExplicitKotlinVersionImplementationDependenciesMetadata --> kotlin-reflect-1.2.71.jar")
|
assertContains(">> :app:testExplicitKotlinVersionImplementationDependenciesMetadata --> kotlin-reflect-1.2.71.jar")
|
||||||
assertContains(">> :app:testExplicitKotlinVersionCompileOnlyDependenciesMetadata --> kotlin-reflect-1.2.70.jar")
|
assertContains(">> :app:testExplicitKotlinVersionCompileOnlyDependenciesMetadata --> kotlin-reflect-1.2.70.jar")
|
||||||
assertContains(">> :app:testExplicitKotlinVersionRuntimeOnlyDependenciesMetadata --> kotlin-reflect-1.2.60.jar")
|
assertContains(">> :app:testExplicitKotlinVersionRuntimeOnlyDependenciesMetadata --> kotlin-reflect-1.2.60.jar")
|
||||||
|
|
||||||
assertContains(">> :app:testProjectWithConfigurationApiDependenciesMetadata --> output.txt")
|
assertContains(">> :app:testProjectWithConfigurationApiDependenciesMetadata --> output.txt")
|
||||||
}
|
}
|
||||||
|
|
||||||
testDependencies()
|
testDependencies()
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -8,12 +8,13 @@ package org.jetbrains.kotlin.gradle.dsl
|
|||||||
import groovy.lang.Closure
|
import groovy.lang.Closure
|
||||||
import org.gradle.api.InvalidUserCodeException
|
import org.gradle.api.InvalidUserCodeException
|
||||||
import org.gradle.api.NamedDomainObjectCollection
|
import org.gradle.api.NamedDomainObjectCollection
|
||||||
|
import org.gradle.api.Project
|
||||||
import org.gradle.util.ConfigureUtil
|
import org.gradle.util.ConfigureUtil
|
||||||
import org.jetbrains.kotlin.gradle.plugin.*
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||||
|
|
||||||
open class KotlinMultiplatformExtension :
|
open class KotlinMultiplatformExtension(project: Project) :
|
||||||
KotlinProjectExtension(),
|
KotlinProjectExtension(project),
|
||||||
KotlinTargetContainerWithPresetFunctions,
|
KotlinTargetContainerWithPresetFunctions,
|
||||||
KotlinTargetContainerWithJsPresetFunctions,
|
KotlinTargetContainerWithJsPresetFunctions,
|
||||||
KotlinTargetContainerWithNativeShortcuts {
|
KotlinTargetContainerWithNativeShortcuts {
|
||||||
@@ -50,7 +51,7 @@ open class KotlinMultiplatformExtension :
|
|||||||
fun targetFromPreset(preset: KotlinTargetPreset<*>, configure: Closure<*>) = targetFromPreset(preset, preset.name, configure)
|
fun targetFromPreset(preset: KotlinTargetPreset<*>, configure: Closure<*>) = targetFromPreset(preset, preset.name, configure)
|
||||||
|
|
||||||
internal val rootSoftwareComponent: KotlinSoftwareComponent by lazy {
|
internal val rootSoftwareComponent: KotlinSoftwareComponent by lazy {
|
||||||
KotlinSoftwareComponentWithCoordinatesAndPublication("kotlin", targets)
|
KotlinSoftwareComponentWithCoordinatesAndPublication(project, "kotlin", targets)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-10
@@ -26,7 +26,7 @@ import kotlin.reflect.KClass
|
|||||||
private const val KOTLIN_PROJECT_EXTENSION_NAME = "kotlin"
|
private const val KOTLIN_PROJECT_EXTENSION_NAME = "kotlin"
|
||||||
|
|
||||||
internal fun Project.createKotlinExtension(extensionClass: KClass<out KotlinProjectExtension>): KotlinProjectExtension {
|
internal fun Project.createKotlinExtension(extensionClass: KClass<out KotlinProjectExtension>): KotlinProjectExtension {
|
||||||
val kotlinExt = extensions.create(KOTLIN_PROJECT_EXTENSION_NAME, extensionClass.java)
|
val kotlinExt = extensions.create(KOTLIN_PROJECT_EXTENSION_NAME, extensionClass.java, this)
|
||||||
DslObject(kotlinExt).extensions.create("experimental", ExperimentalExtension::class.java)
|
DslObject(kotlinExt).extensions.create("experimental", ExperimentalExtension::class.java)
|
||||||
return kotlinExtension
|
return kotlinExtension
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ internal val Project.multiplatformExtensionOrNull: KotlinMultiplatformExtension?
|
|||||||
internal val Project.multiplatformExtension: KotlinMultiplatformExtension
|
internal val Project.multiplatformExtension: KotlinMultiplatformExtension
|
||||||
get() = extensions.getByName(KOTLIN_PROJECT_EXTENSION_NAME) as KotlinMultiplatformExtension
|
get() = extensions.getByName(KOTLIN_PROJECT_EXTENSION_NAME) as KotlinMultiplatformExtension
|
||||||
|
|
||||||
open class KotlinProjectExtension : KotlinSourceSetContainer {
|
open class KotlinProjectExtension(internal val project: Project) : KotlinSourceSetContainer {
|
||||||
val experimental: ExperimentalExtension
|
val experimental: ExperimentalExtension
|
||||||
get() = DslObject(this).extensions.getByType(ExperimentalExtension::class.java)
|
get() = DslObject(this).extensions.getByType(ExperimentalExtension::class.java)
|
||||||
|
|
||||||
@@ -67,32 +67,32 @@ open class KotlinProjectExtension : KotlinSourceSetContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class KotlinSingleTargetExtension : KotlinProjectExtension() {
|
abstract class KotlinSingleTargetExtension(project: Project) : KotlinProjectExtension(project) {
|
||||||
abstract val target: KotlinTarget
|
abstract val target: KotlinTarget
|
||||||
|
|
||||||
open fun target(body: Closure<out KotlinTarget>) = ConfigureUtil.configure(body, target)
|
open fun target(body: Closure<out KotlinTarget>) = ConfigureUtil.configure(body, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class KotlinSingleJavaTargetExtension : KotlinSingleTargetExtension() {
|
abstract class KotlinSingleJavaTargetExtension(project: Project) : KotlinSingleTargetExtension(project) {
|
||||||
abstract override val target: KotlinWithJavaTarget<*>
|
abstract override val target: KotlinWithJavaTarget<*>
|
||||||
}
|
}
|
||||||
|
|
||||||
open class KotlinJvmProjectExtension : KotlinSingleJavaTargetExtension() {
|
open class KotlinJvmProjectExtension(project: Project) : KotlinSingleJavaTargetExtension(project) {
|
||||||
override lateinit var target: KotlinWithJavaTarget<KotlinJvmOptions>
|
override lateinit var target: KotlinWithJavaTarget<KotlinJvmOptions>
|
||||||
internal set
|
internal set
|
||||||
|
|
||||||
open fun target(body: KotlinWithJavaTarget<KotlinJvmOptions>.() -> Unit) = target.run(body)
|
open fun target(body: KotlinWithJavaTarget<KotlinJvmOptions>.() -> Unit) = target.run(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
open class Kotlin2JsProjectExtension : KotlinSingleJavaTargetExtension() {
|
open class Kotlin2JsProjectExtension(project: Project) : KotlinSingleJavaTargetExtension(project) {
|
||||||
override lateinit var target: KotlinWithJavaTarget<KotlinJsOptions>
|
override lateinit var target: KotlinWithJavaTarget<KotlinJsOptions>
|
||||||
internal set
|
internal set
|
||||||
|
|
||||||
open fun target(body: KotlinWithJavaTarget<KotlinJsOptions>.() -> Unit) = target.run(body)
|
open fun target(body: KotlinWithJavaTarget<KotlinJsOptions>.() -> Unit) = target.run(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
open class KotlinJsProjectExtension :
|
open class KotlinJsProjectExtension(project: Project) :
|
||||||
KotlinSingleTargetExtension(),
|
KotlinSingleTargetExtension(project),
|
||||||
KotlinJsCompilerTypeHolder {
|
KotlinJsCompilerTypeHolder {
|
||||||
lateinit var irPreset: KotlinJsIrSingleTargetPreset
|
lateinit var irPreset: KotlinJsIrSingleTargetPreset
|
||||||
|
|
||||||
@@ -224,14 +224,14 @@ open class KotlinJsProjectExtension :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open class KotlinCommonProjectExtension : KotlinSingleJavaTargetExtension() {
|
open class KotlinCommonProjectExtension(project: Project) : KotlinSingleJavaTargetExtension(project) {
|
||||||
override lateinit var target: KotlinWithJavaTarget<KotlinMultiplatformCommonOptions>
|
override lateinit var target: KotlinWithJavaTarget<KotlinMultiplatformCommonOptions>
|
||||||
internal set
|
internal set
|
||||||
|
|
||||||
open fun target(body: KotlinWithJavaTarget<KotlinMultiplatformCommonOptions>.() -> Unit) = target.run(body)
|
open fun target(body: KotlinWithJavaTarget<KotlinMultiplatformCommonOptions>.() -> Unit) = target.run(body)
|
||||||
}
|
}
|
||||||
|
|
||||||
open class KotlinAndroidProjectExtension : KotlinSingleTargetExtension() {
|
open class KotlinAndroidProjectExtension(project: Project) : KotlinSingleTargetExtension(project) {
|
||||||
override lateinit var target: KotlinAndroidTarget
|
override lateinit var target: KotlinAndroidTarget
|
||||||
internal set
|
internal set
|
||||||
|
|
||||||
|
|||||||
+7
-55
@@ -15,8 +15,6 @@ import org.jetbrains.kotlin.gradle.targets.metadata.isCompatibilityMetadataVaria
|
|||||||
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
internal const val COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME = "commonMainMetadataElements"
|
|
||||||
|
|
||||||
open class KotlinMetadataTarget @Inject constructor(project: Project) :
|
open class KotlinMetadataTarget @Inject constructor(project: Project) :
|
||||||
KotlinOnlyTarget<AbstractKotlinCompilation<*>>(project, KotlinPlatformType.common) {
|
KotlinOnlyTarget<AbstractKotlinCompilation<*>>(project, KotlinPlatformType.common) {
|
||||||
|
|
||||||
@@ -29,57 +27,11 @@ open class KotlinMetadataTarget @Inject constructor(project: Project) :
|
|||||||
get() = super.artifactsTaskName
|
get() = super.artifactsTaskName
|
||||||
|
|
||||||
override val kotlinComponents: Set<KotlinTargetComponent> by lazy {
|
override val kotlinComponents: Set<KotlinTargetComponent> by lazy {
|
||||||
if (!project.isKotlinGranularMetadataEnabled)
|
/*
|
||||||
super.kotlinComponents
|
Metadata Target does not have a KotlinTargetComponent on it's own.
|
||||||
else {
|
Responsibility is shifted to the root KotlinSoftwareComponent
|
||||||
val usageContexts = mutableSetOf<DefaultKotlinUsageContext>()
|
*/
|
||||||
|
emptySet<KotlinTargetComponent>()
|
||||||
// This usage value is only needed for Maven scope mapping. Don't replace it with a custom Kotlin Usage value
|
|
||||||
val javaApiUsage = project.usageByName("java-api-jars")
|
|
||||||
|
|
||||||
usageContexts += run {
|
|
||||||
val allMetadataJar = project.tasks.named(KotlinMetadataTargetConfigurator.ALL_METADATA_JAR_NAME)
|
|
||||||
val allMetadataArtifact = project.artifacts.add(Dependency.ARCHIVES_CONFIGURATION, allMetadataJar) {
|
|
||||||
it.classifier = if (project.isCompatibilityMetadataVariantEnabled) "all" else ""
|
|
||||||
}
|
|
||||||
|
|
||||||
DefaultKotlinUsageContext(
|
|
||||||
compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME),
|
|
||||||
javaApiUsage,
|
|
||||||
apiElementsConfigurationName,
|
|
||||||
overrideConfigurationArtifacts = setOf(allMetadataArtifact)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PropertiesProvider(project).enableCompatibilityMetadataVariant == true) {
|
|
||||||
// Ensure that consumers who expect Kotlin 1.2.x metadata package can still get one:
|
|
||||||
// publish the old metadata artifact:
|
|
||||||
usageContexts += run {
|
|
||||||
DefaultKotlinUsageContext(
|
|
||||||
compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME),
|
|
||||||
javaApiUsage,
|
|
||||||
/** this configuration is created by [KotlinMetadataTargetConfigurator.createCommonMainElementsConfiguration] */
|
|
||||||
COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val component =
|
|
||||||
createKotlinVariant(targetName, compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME), usageContexts).apply {
|
|
||||||
publishable = false // this component is not published on its own, its variants are included in the 'root' module
|
|
||||||
}
|
|
||||||
|
|
||||||
val sourcesJarTask =
|
|
||||||
sourcesJarTask(project, lazy { project.kotlinExtension.sourceSets.toSet() }, null, targetName.toLowerCase())
|
|
||||||
|
|
||||||
component.sourcesArtifacts = setOf(
|
|
||||||
project.artifacts.add(Dependency.ARCHIVES_CONFIGURATION, sourcesJarTask).apply {
|
|
||||||
this as ConfigurablePublishArtifact
|
|
||||||
classifier = "sources"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
setOf(component)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-110
@@ -200,116 +200,6 @@ class KotlinMultiplatformPlugin(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun configurePublishingWithMavenPublish(project: Project) = project.pluginManager.withPlugin("maven-publish") { _ ->
|
|
||||||
|
|
||||||
val targets = project.multiplatformExtension.targets
|
|
||||||
val metadataTarget = project.multiplatformExtension.metadata()
|
|
||||||
val kotlinSoftwareComponent = project.multiplatformExtension.rootSoftwareComponent
|
|
||||||
|
|
||||||
project.extensions.configure(PublishingExtension::class.java) { publishing ->
|
|
||||||
|
|
||||||
// The root publication that references the platform specific publications as its variants:
|
|
||||||
publishing.publications.create("kotlinMultiplatform", MavenPublication::class.java).apply {
|
|
||||||
from(kotlinSoftwareComponent)
|
|
||||||
(this as MavenPublicationInternal).publishWithOriginalFileName()
|
|
||||||
kotlinSoftwareComponent.publicationDelegate = this@apply
|
|
||||||
|
|
||||||
metadataTarget.kotlinComponents.filterIsInstance<KotlinTargetComponentWithPublication>()
|
|
||||||
.single().publicationDelegate = this@apply
|
|
||||||
|
|
||||||
project.whenEvaluated {
|
|
||||||
if (!metadataTarget.publishable) return@whenEvaluated
|
|
||||||
metadataTarget.kotlinComponents
|
|
||||||
.flatMap { component -> component.sourcesArtifacts }
|
|
||||||
.forEach { sourcesArtifact -> artifact(sourcesArtifact) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enforce the order of creating the publications, since the metadata publication is used in the other publications:
|
|
||||||
metadataTarget.createMavenPublications(publishing.publications)
|
|
||||||
targets
|
|
||||||
.withType(AbstractKotlinTarget::class.java).matching { it.publishable && it.name != METADATA_TARGET_NAME }
|
|
||||||
.all {
|
|
||||||
if (it is KotlinAndroidTarget || it is KotlinMetadataTarget)
|
|
||||||
// Android targets have their variants created in afterEvaluate; TODO handle this better?
|
|
||||||
// Kotlin Metadata targets rely on complete source sets hierearchy and cannot be inspected for publication earlier
|
|
||||||
project.whenEvaluated { it.createMavenPublications(publishing.publications) }
|
|
||||||
else
|
|
||||||
it.createMavenPublications(publishing.publications)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
project.components.add(kotlinSoftwareComponent)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun rewritePom(
|
|
||||||
pom: MavenPom,
|
|
||||||
pomRewriter: PomDependenciesRewriter,
|
|
||||||
shouldRewritePomDependencies: Provider<Boolean>,
|
|
||||||
includeOnlySpecifiedDependencies: Provider<Set<ModuleCoordinates>>?
|
|
||||||
) {
|
|
||||||
pom.withXml { xml ->
|
|
||||||
if (shouldRewritePomDependencies.get())
|
|
||||||
pomRewriter.rewritePomMppDependenciesToActualTargetModules(xml, includeOnlySpecifiedDependencies)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun AbstractKotlinTarget.createMavenPublications(publications: PublicationContainer) {
|
|
||||||
components
|
|
||||||
.map { gradleComponent -> gradleComponent to kotlinComponents.single { it.name == gradleComponent.name } }
|
|
||||||
.filter { (_, kotlinComponent) -> kotlinComponent.publishable }
|
|
||||||
.forEach { (gradleComponent, kotlinComponent) ->
|
|
||||||
val componentPublication = publications.create(kotlinComponent.name, MavenPublication::class.java).apply {
|
|
||||||
// do this in whenEvaluated since older Gradle versions seem to check the files in the variant eagerly:
|
|
||||||
project.whenEvaluated {
|
|
||||||
from(gradleComponent)
|
|
||||||
kotlinComponent.sourcesArtifacts.forEach { sourceArtifact ->
|
|
||||||
artifact(sourceArtifact)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(this as MavenPublicationInternal).publishWithOriginalFileName()
|
|
||||||
artifactId = kotlinComponent.defaultArtifactId
|
|
||||||
|
|
||||||
val pomRewriter = PomDependenciesRewriter(project, kotlinComponent)
|
|
||||||
val shouldRewritePomDependencies =
|
|
||||||
project.provider { PropertiesProvider(project).keepMppDependenciesIntactInPoms != true }
|
|
||||||
|
|
||||||
rewritePom(
|
|
||||||
pom,
|
|
||||||
pomRewriter,
|
|
||||||
shouldRewritePomDependencies,
|
|
||||||
dependenciesForPomRewriting(this@createMavenPublications)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
(kotlinComponent as? KotlinTargetComponentWithPublication)?.publicationDelegate = componentPublication
|
|
||||||
publicationConfigureActions.all { it.execute(componentPublication) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The metadata targets need their POMs to only include the dependencies from the commonMain API configuration.
|
|
||||||
* The actual apiElements configurations of metadata targets now contain dependencies from all source sets, but, as the consumers who
|
|
||||||
* can't read Gradle module metadata won't resolve a dependency on an MPP to the granular metadata variant and won't then choose the
|
|
||||||
* right dependencies for each source set, we put only the dependencies of the legacy common variant into the POM, i.e. commonMain API.
|
|
||||||
*/
|
|
||||||
private fun dependenciesForPomRewriting(target: AbstractKotlinTarget): Provider<Set<ModuleCoordinates>>? =
|
|
||||||
if (target !is KotlinMetadataTarget || !target.project.isKotlinGranularMetadataEnabled)
|
|
||||||
null
|
|
||||||
else {
|
|
||||||
val commonMain = target.project.kotlinExtension.sourceSets.findByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
|
||||||
if (commonMain == null)
|
|
||||||
null
|
|
||||||
else
|
|
||||||
target.project.provider {
|
|
||||||
val project = target.project
|
|
||||||
|
|
||||||
// Only the commonMain API dependencies can be published for consumers who can't read Gradle project metadata
|
|
||||||
val commonMainApi = project.sourceSetDependencyConfigurationByScope(commonMain, KotlinDependencyScope.API_SCOPE)
|
|
||||||
val commonMainDependencies = commonMainApi.allDependencies
|
|
||||||
commonMainDependencies.map { ModuleCoordinates(it.group, it.name, it.version) }.toSet()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun configureSourceSets(project: Project) = with(project.multiplatformExtension) {
|
private fun configureSourceSets(project: Project) = with(project.multiplatformExtension) {
|
||||||
val production = sourceSets.create(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
val production = sourceSets.create(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
||||||
|
|||||||
+71
-20
@@ -17,44 +17,95 @@ import org.gradle.api.component.SoftwareComponent
|
|||||||
import org.gradle.api.internal.component.SoftwareComponentInternal
|
import org.gradle.api.internal.component.SoftwareComponentInternal
|
||||||
import org.gradle.api.internal.component.UsageContext
|
import org.gradle.api.internal.component.UsageContext
|
||||||
import org.gradle.api.publish.maven.MavenPublication
|
import org.gradle.api.publish.maven.MavenPublication
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||||
import org.jetbrains.kotlin.gradle.plugin.ProjectLocalConfigurations
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.usageByName
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.metadata.COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigurator
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.metadata.isCompatibilityMetadataVariantEnabled
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
||||||
|
|
||||||
abstract class KotlinSoftwareComponent(
|
abstract class KotlinSoftwareComponent(
|
||||||
|
private val project: Project,
|
||||||
private val name: String,
|
private val name: String,
|
||||||
protected val kotlinTargets: Iterable<KotlinTarget>
|
protected val kotlinTargets: Iterable<KotlinTarget>
|
||||||
) : SoftwareComponentInternal, ComponentWithVariants {
|
) : SoftwareComponentInternal, ComponentWithVariants {
|
||||||
|
|
||||||
private val metadataTarget: KotlinMetadataTarget
|
|
||||||
get() = kotlinTargets.filterIsInstance<KotlinMetadataTarget>().single()
|
|
||||||
|
|
||||||
override fun getUsages(): Set<UsageContext> = (metadataTarget.components.single() as SoftwareComponentInternal).usages
|
|
||||||
|
|
||||||
override fun getVariants(): Set<SoftwareComponent> =
|
|
||||||
kotlinTargets.minus(metadataTarget).flatMap { it.components }.toSet()
|
|
||||||
|
|
||||||
override fun getName(): String = name
|
override fun getName(): String = name
|
||||||
|
|
||||||
|
override fun getVariants(): Set<SoftwareComponent> = kotlinTargets
|
||||||
|
.filter { target -> target !is KotlinMetadataTarget }
|
||||||
|
.flatMap { it.components }.toSet()
|
||||||
|
|
||||||
|
private val _usages: Set<UsageContext> by lazy {
|
||||||
|
val metadataTarget = project.multiplatformExtension.metadata()
|
||||||
|
|
||||||
|
if (!project.isKotlinGranularMetadataEnabled) {
|
||||||
|
val metadataCompilation = metadataTarget.compilations.getByName(MAIN_COMPILATION_NAME)
|
||||||
|
return@lazy metadataTarget.createUsageContexts(metadataCompilation)
|
||||||
|
}
|
||||||
|
|
||||||
|
mutableSetOf<UsageContext>().apply {
|
||||||
|
// This usage value is only needed for Maven scope mapping. Don't replace it with a custom Kotlin Usage value
|
||||||
|
val javaApiUsage = project.usageByName("java-api-jars")
|
||||||
|
|
||||||
|
val allMetadataJar = project.tasks.named(KotlinMetadataTargetConfigurator.ALL_METADATA_JAR_NAME)
|
||||||
|
val allMetadataArtifact = project.artifacts.add(Dependency.ARCHIVES_CONFIGURATION, allMetadataJar) { allMetadataArtifact ->
|
||||||
|
allMetadataArtifact.classifier = if (project.isCompatibilityMetadataVariantEnabled) "all" else ""
|
||||||
|
}
|
||||||
|
|
||||||
|
this += DefaultKotlinUsageContext(
|
||||||
|
compilation = metadataTarget.compilations.getByName(MAIN_COMPILATION_NAME),
|
||||||
|
usage = javaApiUsage,
|
||||||
|
dependencyConfigurationName = metadataTarget.apiElementsConfigurationName,
|
||||||
|
overrideConfigurationArtifacts = setOf(allMetadataArtifact)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if (project.isCompatibilityMetadataVariantEnabled) {
|
||||||
|
// Ensure that consumers who expect Kotlin 1.2.x metadata package can still get one:
|
||||||
|
// publish the old metadata artifact:
|
||||||
|
this += run {
|
||||||
|
DefaultKotlinUsageContext(
|
||||||
|
metadataTarget.compilations.getByName(MAIN_COMPILATION_NAME),
|
||||||
|
javaApiUsage,
|
||||||
|
/** this configuration is created by [KotlinMetadataTargetConfigurator.createCommonMainElementsConfiguration] */
|
||||||
|
COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getUsages(): Set<UsageContext> {
|
||||||
|
return _usages
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val sourcesArtifacts: Set<PublishArtifact> by lazy {
|
||||||
|
val sourcesJarTask = sourcesJarTask(project, lazy { project.kotlinExtension.sourceSets.toSet() }, null, name.toLowerCase())
|
||||||
|
val sourcesJarArtifact = project.artifacts.add(Dependency.ARCHIVES_CONFIGURATION, sourcesJarTask) { sourcesJarArtifact ->
|
||||||
|
sourcesJarArtifact.classifier = "sources"
|
||||||
|
}
|
||||||
|
setOf(sourcesJarArtifact)
|
||||||
|
}
|
||||||
|
|
||||||
// This property is declared in the parent type to allow the usages to reference it without forcing the subtypes to load,
|
// This property is declared in the parent type to allow the usages to reference it without forcing the subtypes to load,
|
||||||
// which is needed for compatibility with older Gradle versions
|
// which is needed for compatibility with older Gradle versions
|
||||||
var publicationDelegate: MavenPublication? = null
|
var publicationDelegate: MavenPublication? = null
|
||||||
}
|
}
|
||||||
|
|
||||||
class KotlinSoftwareComponentWithCoordinatesAndPublication(name: String, kotlinTargets: Iterable<KotlinTarget>) :
|
class KotlinSoftwareComponentWithCoordinatesAndPublication(project: Project, name: String, kotlinTargets: Iterable<KotlinTarget>) :
|
||||||
KotlinSoftwareComponent(name, kotlinTargets), ComponentWithCoordinates {
|
KotlinSoftwareComponent(project, name, kotlinTargets), ComponentWithCoordinates {
|
||||||
|
|
||||||
override fun getCoordinates(): ModuleVersionIdentifier = getCoordinatesFromPublicationDelegateAndProject(
|
override fun getCoordinates(): ModuleVersionIdentifier = getCoordinatesFromPublicationDelegateAndProject(
|
||||||
publicationDelegate, kotlinTargets.first().project, null
|
publicationDelegate, kotlinTargets.first().project, null
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// At the moment all KN artifacts have JAVA_API usage.
|
|
||||||
// TODO: Replace it with a specific usage
|
|
||||||
object NativeUsage {
|
|
||||||
const val KOTLIN_KLIB = "kotlin-klib"
|
|
||||||
}
|
|
||||||
|
|
||||||
interface KotlinUsageContext : UsageContext {
|
interface KotlinUsageContext : UsageContext {
|
||||||
val compilation: KotlinCompilation<*>
|
val compilation: KotlinCompilation<*>
|
||||||
val dependencyConfigurationName: String
|
val dependencyConfigurationName: String
|
||||||
@@ -117,4 +168,4 @@ class DefaultKotlinUsageContext(
|
|||||||
override fun getCapabilities(): Set<Capability> = emptySet()
|
override fun getCapabilities(): Set<Capability> = emptySet()
|
||||||
|
|
||||||
override fun getGlobalExcludes(): Set<ExcludeRule> = emptySet()
|
override fun getGlobalExcludes(): Set<ExcludeRule> = emptySet()
|
||||||
}
|
}
|
||||||
|
|||||||
+131
@@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
|
import org.gradle.api.publish.PublicationContainer
|
||||||
|
import org.gradle.api.publish.PublishingExtension
|
||||||
|
import org.gradle.api.publish.maven.MavenPom
|
||||||
|
import org.gradle.api.publish.maven.MavenPublication
|
||||||
|
import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.sourceSetDependencyConfigurationByScope
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
|
||||||
|
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
||||||
|
|
||||||
|
internal fun configurePublishingWithMavenPublish(project: Project) = project.pluginManager.withPlugin("maven-publish") {
|
||||||
|
project.extensions.configure(PublishingExtension::class.java) { publishing ->
|
||||||
|
createRootPublication(project, publishing)
|
||||||
|
createTargetPublications(project, publishing)
|
||||||
|
}
|
||||||
|
|
||||||
|
project.components.add(project.multiplatformExtension.rootSoftwareComponent)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The root publication that references the platform specific publications as its variants
|
||||||
|
*/
|
||||||
|
private fun createRootPublication(project: Project, publishing: PublishingExtension) {
|
||||||
|
val kotlinSoftwareComponent = project.multiplatformExtension.rootSoftwareComponent
|
||||||
|
|
||||||
|
publishing.publications.create("kotlinMultiplatform", MavenPublication::class.java).apply {
|
||||||
|
from(kotlinSoftwareComponent)
|
||||||
|
(this as MavenPublicationInternal).publishWithOriginalFileName()
|
||||||
|
kotlinSoftwareComponent.publicationDelegate = this@apply
|
||||||
|
kotlinSoftwareComponent.sourcesArtifacts.forEach { sourceArtifact ->
|
||||||
|
artifact(sourceArtifact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createTargetPublications(project: Project, publishing: PublishingExtension) {
|
||||||
|
val kotlin = project.multiplatformExtension
|
||||||
|
// Enforce the order of creating the publications, since the metadata publication is used in the other publications:
|
||||||
|
kotlin.targets
|
||||||
|
.withType(AbstractKotlinTarget::class.java)
|
||||||
|
.matching { it.publishable }
|
||||||
|
.all { kotlinTarget ->
|
||||||
|
if (kotlinTarget is KotlinAndroidTarget)
|
||||||
|
// Android targets have their variants created in afterEvaluate; TODO handle this better?
|
||||||
|
project.whenEvaluated { kotlinTarget.createMavenPublications(publishing.publications) }
|
||||||
|
else
|
||||||
|
kotlinTarget.createMavenPublications(publishing.publications)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun AbstractKotlinTarget.createMavenPublications(publications: PublicationContainer) {
|
||||||
|
components
|
||||||
|
.map { gradleComponent -> gradleComponent to kotlinComponents.single { it.name == gradleComponent.name } }
|
||||||
|
.filter { (_, kotlinComponent) -> kotlinComponent.publishable }
|
||||||
|
.forEach { (gradleComponent, kotlinComponent) ->
|
||||||
|
val componentPublication = publications.create(kotlinComponent.name, MavenPublication::class.java).apply {
|
||||||
|
// do this in whenEvaluated since older Gradle versions seem to check the files in the variant eagerly:
|
||||||
|
project.whenEvaluated {
|
||||||
|
from(gradleComponent)
|
||||||
|
kotlinComponent.sourcesArtifacts.forEach { sourceArtifact ->
|
||||||
|
artifact(sourceArtifact)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(this as MavenPublicationInternal).publishWithOriginalFileName()
|
||||||
|
artifactId = kotlinComponent.defaultArtifactId
|
||||||
|
|
||||||
|
val pomRewriter = PomDependenciesRewriter(project, kotlinComponent)
|
||||||
|
val shouldRewritePomDependencies =
|
||||||
|
project.provider { PropertiesProvider(project).keepMppDependenciesIntactInPoms != true }
|
||||||
|
|
||||||
|
rewritePom(
|
||||||
|
pom,
|
||||||
|
pomRewriter,
|
||||||
|
shouldRewritePomDependencies,
|
||||||
|
dependenciesForPomRewriting(this@createMavenPublications)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
(kotlinComponent as? KotlinTargetComponentWithPublication)?.publicationDelegate = componentPublication
|
||||||
|
publicationConfigureActions.all { it.execute(componentPublication) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rewritePom(
|
||||||
|
pom: MavenPom,
|
||||||
|
pomRewriter: PomDependenciesRewriter,
|
||||||
|
shouldRewritePomDependencies: Provider<Boolean>,
|
||||||
|
includeOnlySpecifiedDependencies: Provider<Set<ModuleCoordinates>>?
|
||||||
|
) {
|
||||||
|
pom.withXml { xml ->
|
||||||
|
if (shouldRewritePomDependencies.get())
|
||||||
|
pomRewriter.rewritePomMppDependenciesToActualTargetModules(xml, includeOnlySpecifiedDependencies)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The metadata targets need their POMs to only include the dependencies from the commonMain API configuration.
|
||||||
|
* The actual apiElements configurations of metadata targets now contain dependencies from all source sets, but, as the consumers who
|
||||||
|
* can't read Gradle module metadata won't resolve a dependency on an MPP to the granular metadata variant and won't then choose the
|
||||||
|
* right dependencies for each source set, we put only the dependencies of the legacy common variant into the POM, i.e. commonMain API.
|
||||||
|
*/
|
||||||
|
private fun dependenciesForPomRewriting(target: AbstractKotlinTarget): Provider<Set<ModuleCoordinates>>? =
|
||||||
|
if (target !is KotlinMetadataTarget || !target.project.isKotlinGranularMetadataEnabled)
|
||||||
|
null
|
||||||
|
else {
|
||||||
|
val commonMain = target.project.kotlinExtension.sourceSets.findByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
||||||
|
if (commonMain == null)
|
||||||
|
null
|
||||||
|
else
|
||||||
|
target.project.provider {
|
||||||
|
val project = target.project
|
||||||
|
|
||||||
|
// Only the commonMain API dependencies can be published for consumers who can't read Gradle project metadata
|
||||||
|
val commonMainApi = project.sourceSetDependencyConfigurationByScope(commonMain, KotlinDependencyScope.API_SCOPE)
|
||||||
|
val commonMainDependencies = commonMainApi.allDependencies
|
||||||
|
commonMainDependencies.map { ModuleCoordinates(it.group, it.name, it.version) }.toSet()
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
|||||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
|
import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
|
||||||
|
|
||||||
|
internal const val COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME = "commonMainMetadataElements"
|
||||||
internal const val ALL_COMPILE_METADATA_CONFIGURATION_NAME = "allSourceSetsCompileDependenciesMetadata"
|
internal const val ALL_COMPILE_METADATA_CONFIGURATION_NAME = "allSourceSetsCompileDependenciesMetadata"
|
||||||
internal const val ALL_RUNTIME_METADATA_CONFIGURATION_NAME = "allSourceSetsRuntimeDependenciesMetadata"
|
internal const val ALL_RUNTIME_METADATA_CONFIGURATION_NAME = "allSourceSetsRuntimeDependenciesMetadata"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user