[Gradle] ExternalKotlinTarget Api: Add initial APIs to configure publications
KT-54981
This commit is contained in:
committed by
Space Team
parent
c33b172988
commit
bc531610f7
@@ -5,7 +5,7 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
compileOnly(gradleKotlinDsl())
|
||||
compileOnly("com.android.tools.build:gradle:7.0.0")
|
||||
compileOnly("com.android.tools.build:gradle:7.2.1")
|
||||
compileOnly(project(":kotlin-gradle-plugin"))
|
||||
}
|
||||
|
||||
|
||||
+40
-15
@@ -7,7 +7,8 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.android
|
||||
|
||||
import com.android.build.gradle.AppExtension
|
||||
import com.android.build.api.attributes.AgpVersionAttr
|
||||
import com.android.build.gradle.LibraryExtension
|
||||
import com.android.build.gradle.internal.publishing.AndroidArtifacts
|
||||
import org.gradle.api.attributes.java.TargetJvmEnvironment
|
||||
import org.gradle.api.attributes.java.TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE
|
||||
@@ -23,7 +24,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinTargetDescr
|
||||
@OptIn(ExternalVariantApi::class)
|
||||
fun KotlinMultiplatformExtension.androidTargetPrototype(): PrototypeAndroidTarget {
|
||||
val project = this.project
|
||||
val androidExtension = project.extensions.getByType<AppExtension>()
|
||||
val androidExtension = project.extensions.getByType<LibraryExtension>()
|
||||
|
||||
/*
|
||||
Set a variant filter and only allow 'debug'.
|
||||
@@ -47,19 +48,37 @@ fun KotlinMultiplatformExtension.androidTargetPrototype(): PrototypeAndroidTarge
|
||||
platformType = KotlinPlatformType.jvm
|
||||
targetFactory = TargetFactory { delegate -> PrototypeAndroidTarget(delegate, PrototypeAndroidDsl(31)) }
|
||||
|
||||
/*
|
||||
Configure apiElements configuration attributes (project to project dependency)
|
||||
In this example we hardcoded AGP version 7.4.0-beta02 as demo
|
||||
*/
|
||||
apiElements.configure { _, configuration ->
|
||||
configuration.attributes.attribute(TARGET_JVM_ENVIRONMENT_ATTRIBUTE, project.objects.named(TargetJvmEnvironment.ANDROID))
|
||||
configuration.attributes.attribute(AgpVersionAttr.ATTRIBUTE, project.objects.named("7.4.0-beta02")) /* For demo */
|
||||
}
|
||||
|
||||
/*
|
||||
Configure runtimeElements configuration attributes (project to project dependency)
|
||||
In this example we hardcoded AGP version 7.4.0-beta02 as demo
|
||||
*/
|
||||
runtimeElements.configure { _, configuration ->
|
||||
configuration.attributes.attribute(TARGET_JVM_ENVIRONMENT_ATTRIBUTE, project.objects.named(TargetJvmEnvironment.ANDROID))
|
||||
configuration.attributes.attribute(AgpVersionAttr.ATTRIBUTE, project.objects.named("7.4.0-beta02")) /* For demo */
|
||||
}
|
||||
|
||||
/*
|
||||
Configure published configurations (maven publication):
|
||||
We override KotlinPlatformType to be androidJvm for now (to be discussed w/ Google later)
|
||||
*/
|
||||
apiElementsPublished.configure { _, configuration ->
|
||||
/* TODO w/ Google: Find a way to deprecate this attribute */
|
||||
configuration.attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.androidJvm)
|
||||
configuration.attributes.attribute(TARGET_JVM_ENVIRONMENT_ATTRIBUTE, project.objects.named(TargetJvmEnvironment.ANDROID))
|
||||
}
|
||||
|
||||
runtimeElementsPublished.configure { _, configuration ->
|
||||
/* TODO w/ Google: Find a way to deprecate this attribute */
|
||||
configuration.attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.androidJvm)
|
||||
configuration.attributes.attribute(TARGET_JVM_ENVIRONMENT_ATTRIBUTE, project.objects.named(TargetJvmEnvironment.ANDROID))
|
||||
}
|
||||
}
|
||||
@@ -67,8 +86,8 @@ fun KotlinMultiplatformExtension.androidTargetPrototype(): PrototypeAndroidTarge
|
||||
/*
|
||||
Whilst using the .all hook, we only expect the single 'debug' variant to be available through this API.
|
||||
*/
|
||||
androidExtension.applicationVariants.all { applicationVariant ->
|
||||
project.logger.quiet("Setting up applicationVariant: ${applicationVariant.name}")
|
||||
androidExtension.libraryVariants.all { androidVariant ->
|
||||
project.logger.quiet("Setting up applicationVariant: ${androidVariant.name}")
|
||||
|
||||
/*
|
||||
Create Compilations: main, unitTest and instrumentedTest
|
||||
@@ -97,21 +116,21 @@ fun KotlinMultiplatformExtension.androidTargetPrototype(): PrototypeAndroidTarge
|
||||
Wire the Kotlin Compilations output (.class files) into the Android artifacts
|
||||
by using the 'registerPreJavacGeneratedBytecode' function
|
||||
*/
|
||||
applicationVariant.registerPreJavacGeneratedBytecode(mainCompilation.output.classesDirs)
|
||||
applicationVariant.unitTestVariant.registerPreJavacGeneratedBytecode(unitTestCompilation.output.classesDirs)
|
||||
applicationVariant.testVariant.registerPreJavacGeneratedBytecode(instrumentedTestCompilation.output.classesDirs)
|
||||
androidVariant.registerPreJavacGeneratedBytecode(mainCompilation.output.classesDirs)
|
||||
androidVariant.unitTestVariant.registerPreJavacGeneratedBytecode(unitTestCompilation.output.classesDirs)
|
||||
androidVariant.testVariant.registerPreJavacGeneratedBytecode(instrumentedTestCompilation.output.classesDirs)
|
||||
|
||||
|
||||
/*
|
||||
Add dependencies coming from Kotlin to Android by adding all dependencies from Kotlin to the variants
|
||||
compileConfiguration or runtimeConfiguration
|
||||
*/
|
||||
applicationVariant.compileConfiguration.extendsFrom(mainCompilation.configurations.compileDependencyConfiguration)
|
||||
applicationVariant.runtimeConfiguration.extendsFrom(mainCompilation.configurations.runtimeDependencyConfiguration)
|
||||
applicationVariant.unitTestVariant.compileConfiguration.extendsFrom(unitTestCompilation.configurations.compileDependencyConfiguration)
|
||||
applicationVariant.unitTestVariant.runtimeConfiguration.extendsFrom(unitTestCompilation.configurations.runtimeDependencyConfiguration)
|
||||
applicationVariant.testVariant.compileConfiguration.extendsFrom(instrumentedTestCompilation.configurations.compileDependencyConfiguration)
|
||||
applicationVariant.testVariant.runtimeConfiguration.extendsFrom(instrumentedTestCompilation.configurations.runtimeDependencyConfiguration)
|
||||
androidVariant.compileConfiguration.extendsFrom(mainCompilation.configurations.compileDependencyConfiguration)
|
||||
androidVariant.runtimeConfiguration.extendsFrom(mainCompilation.configurations.runtimeDependencyConfiguration)
|
||||
androidVariant.unitTestVariant.compileConfiguration.extendsFrom(unitTestCompilation.configurations.compileDependencyConfiguration)
|
||||
androidVariant.unitTestVariant.runtimeConfiguration.extendsFrom(unitTestCompilation.configurations.runtimeDependencyConfiguration)
|
||||
androidVariant.testVariant.compileConfiguration.extendsFrom(instrumentedTestCompilation.configurations.compileDependencyConfiguration)
|
||||
androidVariant.testVariant.runtimeConfiguration.extendsFrom(instrumentedTestCompilation.configurations.runtimeDependencyConfiguration)
|
||||
|
||||
|
||||
/*
|
||||
@@ -148,12 +167,18 @@ fun KotlinMultiplatformExtension.androidTargetPrototype(): PrototypeAndroidTarge
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Add .aar artifacts to publications!
|
||||
*/
|
||||
androidTarget.apiElementsPublishedConfiguration.outgoing.artifact(androidVariant.packageLibraryProvider)
|
||||
androidTarget.runtimeElementsPublishedConfiguration.outgoing.artifact(androidVariant.packageLibraryProvider)
|
||||
|
||||
/*
|
||||
"Disable" configurations from plain Android plugin
|
||||
This hack will not be necessary in the final implementation
|
||||
*/
|
||||
project.configurations.findByName("${applicationVariant.name}ApiElements")?.isCanBeConsumed = false
|
||||
project.configurations.findByName("${applicationVariant.name}RuntimeElements")?.isCanBeConsumed = false
|
||||
project.configurations.findByName("${androidVariant.name}ApiElements")?.isCanBeConsumed = false
|
||||
project.configurations.findByName("${androidVariant.name}RuntimeElements")?.isCanBeConsumed = false
|
||||
}
|
||||
|
||||
return androidTarget
|
||||
|
||||
+9
-3
@@ -20,6 +20,7 @@ import org.gradle.api.internal.component.SoftwareComponentInternal
|
||||
import org.gradle.api.internal.component.UsageContext
|
||||
import org.gradle.api.internal.project.ProjectInternal
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
@@ -58,7 +59,8 @@ abstract class AbstractKotlinTarget(
|
||||
override val publishable: Boolean
|
||||
get() = true
|
||||
|
||||
internal open val kotlinComponents: Set<KotlinTargetComponent> by lazy {
|
||||
@InternalKotlinGradlePluginApi
|
||||
override val kotlinComponents: Set<KotlinTargetComponent> by lazy {
|
||||
val mainCompilation = compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||
val usageContexts = createUsageContexts(mainCompilation)
|
||||
|
||||
@@ -144,14 +146,18 @@ abstract class AbstractKotlinTarget(
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal val publicationConfigureActions: DomainObjectSet<Action<MavenPublication>> = project
|
||||
.objects
|
||||
private val publicationConfigureActions: DomainObjectSet<Action<MavenPublication>> = project.objects
|
||||
.domainObjectSet(Action::class.java) as DomainObjectSet<Action<MavenPublication>>
|
||||
|
||||
override fun mavenPublication(action: Action<MavenPublication>) {
|
||||
publicationConfigureActions.add(action)
|
||||
}
|
||||
|
||||
@InternalKotlinGradlePluginApi
|
||||
override fun onPublicationCreated(publication: MavenPublication) {
|
||||
publicationConfigureActions.all { action -> action.execute(publication) }
|
||||
}
|
||||
|
||||
override var preset: KotlinTargetPreset<out KotlinTarget>? = null
|
||||
internal set
|
||||
}
|
||||
|
||||
+6
-1
@@ -5,9 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp
|
||||
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent
|
||||
|
||||
internal interface InternalKotlinTarget : KotlinTarget
|
||||
internal interface InternalKotlinTarget : KotlinTarget {
|
||||
val kotlinComponents: Set<KotlinTargetComponent>
|
||||
fun onPublicationCreated(publication: MavenPublication)
|
||||
}
|
||||
|
||||
internal val KotlinTarget.internal: InternalKotlinTarget
|
||||
get() = (this as? InternalKotlinTarget) ?: throw IllegalArgumentException(
|
||||
|
||||
+9
-10
@@ -19,14 +19,12 @@ import org.gradle.api.internal.component.UsageContext
|
||||
import org.gradle.api.provider.SetProperty
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.ProjectLocalConfigurations
|
||||
import org.jetbrains.kotlin.gradle.plugin.usageByName
|
||||
import org.jetbrains.kotlin.gradle.targets.metadata.*
|
||||
import org.jetbrains.kotlin.gradle.targets.metadata.COMMON_MAIN_ELEMENTS_CONFIGURATION_NAME
|
||||
import org.jetbrains.kotlin.gradle.targets.metadata.getCommonSourceSetsForMetadataCompilation
|
||||
import org.jetbrains.kotlin.gradle.targets.metadata.isCompatibilityMetadataVariantEnabled
|
||||
import org.jetbrains.kotlin.gradle.targets.metadata.isKotlinGranularMetadataEnabled
|
||||
import org.jetbrains.kotlin.gradle.utils.setProperty
|
||||
|
||||
abstract class KotlinSoftwareComponent(
|
||||
@@ -40,11 +38,12 @@ abstract class KotlinSoftwareComponent(
|
||||
override fun getVariants(): Set<SoftwareComponent> = kotlinTargets
|
||||
.filter { target -> target !is KotlinMetadataTarget }
|
||||
.flatMap { target ->
|
||||
val targetPublishableComponentNames =
|
||||
(target as? AbstractKotlinTarget)?.kotlinComponents?.mapNotNullTo(mutableSetOf()) { component ->
|
||||
component.name.takeIf { component.publishable }
|
||||
}
|
||||
target.components.filter { targetPublishableComponentNames?.contains(it.name) ?: true }
|
||||
val targetPublishableComponentNames = target.internal.kotlinComponents
|
||||
.filter { component -> component.publishable }
|
||||
.map { component -> component.name }
|
||||
.toSet()
|
||||
|
||||
target.components.filter { it.name in targetPublishableComponentNames }
|
||||
}.toSet()
|
||||
|
||||
private val _usages: Set<UsageContext> by lazy {
|
||||
|
||||
+4
-4
@@ -62,7 +62,7 @@ private fun createTargetPublications(project: Project, publishing: PublishingExt
|
||||
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)
|
||||
.withType(InternalKotlinTarget::class.java)
|
||||
.matching { it.publishable }
|
||||
.all { kotlinTarget ->
|
||||
if (kotlinTarget is KotlinAndroidTarget)
|
||||
@@ -73,7 +73,7 @@ private fun createTargetPublications(project: Project, publishing: PublishingExt
|
||||
}
|
||||
}
|
||||
|
||||
private fun AbstractKotlinTarget.createMavenPublications(publications: PublicationContainer) {
|
||||
private fun InternalKotlinTarget.createMavenPublications(publications: PublicationContainer) {
|
||||
components
|
||||
.map { gradleComponent -> gradleComponent to kotlinComponents.single { it.name == gradleComponent.name } }
|
||||
.filter { (_, kotlinComponent) -> kotlinComponent.publishableOnCurrentHost }
|
||||
@@ -102,7 +102,7 @@ private fun AbstractKotlinTarget.createMavenPublications(publications: Publicati
|
||||
}
|
||||
|
||||
(kotlinComponent as? KotlinTargetComponentWithPublication)?.publicationDelegate = componentPublication
|
||||
publicationConfigureActions.all { it.execute(componentPublication) }
|
||||
onPublicationCreated(componentPublication)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ private fun rewritePom(
|
||||
* 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>>? =
|
||||
private fun dependenciesForPomRewriting(target: InternalKotlinTarget): Provider<Set<ModuleCoordinates>>? =
|
||||
if (target !is KotlinMetadataTarget || !target.project.isKotlinGranularMetadataEnabled)
|
||||
null
|
||||
else {
|
||||
|
||||
+14
-3
@@ -7,8 +7,9 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.external
|
||||
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.InternalKotlinTarget
|
||||
|
||||
@ExternalKotlinTargetApi
|
||||
@@ -23,5 +24,15 @@ abstract class DecoratedExternalKotlinTarget internal constructor(
|
||||
|
||||
val runtimeElementsConfiguration: Configuration = delegate.runtimeElementsConfiguration
|
||||
|
||||
internal val logger: Logger = Logging.getLogger("${ExternalKotlinTargetImpl::class.qualifiedName}: $name")
|
||||
}
|
||||
val apiElementsPublishedConfiguration: Configuration = delegate.apiElementsPublishedConfiguration
|
||||
|
||||
val runtimeElementsPublishedConfiguration: Configuration = delegate.runtimeElementsPublishedConfiguration
|
||||
|
||||
internal val logger: Logger = delegate.logger
|
||||
}
|
||||
|
||||
internal val ExternalKotlinTargetImpl.decoratedInstance: DecoratedExternalKotlinTarget
|
||||
get() = project.multiplatformExtension.targets.getByName(name) as DecoratedExternalKotlinTarget
|
||||
|
||||
internal val ExternalKotlinTargetImpl.decoratedInstanceOrNull: DecoratedExternalKotlinTarget?
|
||||
get() = project.multiplatformExtensionOrNull?.targets?.findByName(name) as? DecoratedExternalKotlinTarget
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.external
|
||||
|
||||
import org.gradle.api.artifacts.ModuleVersionIdentifier
|
||||
import org.gradle.api.artifacts.PublishArtifact
|
||||
import org.gradle.api.component.ComponentWithCoordinates
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinTargetComponentWithPublication
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.external.ExternalKotlinTargetComponent.TargetProvider
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.getCoordinatesFromPublicationDelegateAndProject
|
||||
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
|
||||
|
||||
internal class ExternalKotlinTargetComponent(
|
||||
val targetProvider: TargetProvider
|
||||
) : KotlinTargetComponentWithPublication, ComponentWithCoordinates {
|
||||
|
||||
/*
|
||||
Target creation requires this component. We will provide the target once it is required
|
||||
*/
|
||||
fun interface TargetProvider {
|
||||
operator fun invoke(): DecoratedExternalKotlinTarget
|
||||
|
||||
companion object {
|
||||
fun byTargetName(extension: KotlinMultiplatformExtension, targetName: String) = TargetProvider {
|
||||
extension.targets.getByName(targetName) as DecoratedExternalKotlinTarget
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Required for getting correct coordinates */
|
||||
override var publicationDelegate: MavenPublication? = null
|
||||
|
||||
override val target: KotlinTarget by lazy { targetProvider() }
|
||||
|
||||
override val publishable: Boolean
|
||||
get() = target.publishable
|
||||
|
||||
override val publishableOnCurrentHost: Boolean
|
||||
get() = true
|
||||
|
||||
override val defaultArtifactId: String
|
||||
get() = dashSeparatedName(target.project.name, target.name.toLowerCase())
|
||||
|
||||
override val sourcesArtifacts: Set<PublishArtifact>
|
||||
get() = emptySet()
|
||||
|
||||
override fun getName(): String = target.name
|
||||
|
||||
override fun getCoordinates(): ModuleVersionIdentifier =
|
||||
getCoordinatesFromPublicationDelegateAndProject(publicationDelegate, target.project, null)
|
||||
}
|
||||
|
||||
|
||||
+32
-15
@@ -5,39 +5,46 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp.external
|
||||
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.*
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.attributes.AttributeContainer
|
||||
import org.gradle.api.component.SoftwareComponent
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.gradle.api.logging.Logging
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.jetbrains.kotlin.gradle.InternalKotlinGradlePluginApi
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.HierarchyAttributeContainer
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.InternalKotlinTarget
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.buildAdhocComponentsFromKotlinVariants
|
||||
|
||||
internal class ExternalKotlinTargetImpl internal constructor(
|
||||
override val project: Project,
|
||||
override val targetName: String,
|
||||
override val platformType: KotlinPlatformType,
|
||||
override val publishable: Boolean,
|
||||
val defaultConfiguration: Configuration,
|
||||
val apiElementsConfiguration: Configuration,
|
||||
val runtimeElementsConfiguration: Configuration,
|
||||
override val publishable: Boolean,
|
||||
internal val kotlinComponents: Set<KotlinTargetComponent>,
|
||||
val apiElementsPublishedConfiguration: Configuration,
|
||||
val runtimeElementsPublishedConfiguration: Configuration,
|
||||
val kotlinTargetComponent: ExternalKotlinTargetComponent,
|
||||
private val artifactsTaskLocator: ArtifactsTaskLocator,
|
||||
) : InternalKotlinTarget {
|
||||
|
||||
|
||||
fun interface ArtifactsTaskLocator {
|
||||
fun locate(target: ExternalKotlinTargetImpl): TaskProvider<out Task>
|
||||
}
|
||||
|
||||
val kotlin = project.multiplatformExtension
|
||||
|
||||
override val preset: Nothing? = null
|
||||
|
||||
internal val logger: Logger = Logging.getLogger("${ExternalKotlinTargetImpl::class.qualifiedName}: $name")
|
||||
|
||||
override val useDisambiguationClassifierAsSourceSetNamePrefix: Boolean = true
|
||||
|
||||
override val overrideDisambiguationClassifierOnIdeImport: String? = null
|
||||
@@ -58,26 +65,36 @@ internal class ExternalKotlinTargetImpl internal constructor(
|
||||
override val runtimeElementsConfigurationName: String
|
||||
get() = runtimeElementsConfiguration.name
|
||||
|
||||
@InternalKotlinGradlePluginApi
|
||||
override val kotlinComponents: Set<KotlinTargetComponent> = setOf(kotlinTargetComponent)
|
||||
|
||||
override val components: Set<SoftwareComponent> by lazy {
|
||||
project.buildAdhocComponentsFromKotlinVariants(kotlinComponents)
|
||||
logger.debug("Creating SoftwareComponent")
|
||||
setOf(ExternalKotlinTargetSoftwareComponent(this))
|
||||
}
|
||||
|
||||
override val compilations: NamedDomainObjectContainer<ExternalDecoratedKotlinCompilation> by lazy {
|
||||
project.container(ExternalDecoratedKotlinCompilation::class.java)
|
||||
}
|
||||
|
||||
@Suppress("unchecked_cast")
|
||||
private val mavenPublicationActions = project.objects.domainObjectSet(Action::class.java)
|
||||
as DomainObjectSet<Action<MavenPublication>>
|
||||
|
||||
override fun mavenPublication(action: Action<MavenPublication>) {
|
||||
TODO("Not yet implemented")
|
||||
mavenPublicationActions.add(action)
|
||||
}
|
||||
|
||||
override val preset: Nothing? = null
|
||||
|
||||
override fun getAttributes(): AttributeContainer {
|
||||
TODO("Not yet implemented")
|
||||
@InternalKotlinGradlePluginApi
|
||||
override fun onPublicationCreated(publication: MavenPublication) {
|
||||
mavenPublicationActions.all { action -> action.execute(publication) }
|
||||
}
|
||||
|
||||
private val attributeContainer = HierarchyAttributeContainer(parent = null)
|
||||
|
||||
override fun getAttributes(): AttributeContainer = attributeContainer
|
||||
|
||||
internal fun onCreated() {
|
||||
artifactsTask
|
||||
components
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2010-2022 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.external
|
||||
|
||||
import org.gradle.api.artifacts.ModuleVersionIdentifier
|
||||
import org.gradle.api.component.ComponentWithCoordinates
|
||||
import org.gradle.api.component.ComponentWithVariants
|
||||
import org.gradle.api.component.SoftwareComponent
|
||||
import org.gradle.api.component.SoftwareComponentFactory
|
||||
import org.gradle.api.internal.component.SoftwareComponentInternal
|
||||
import org.gradle.api.internal.component.UsageContext
|
||||
import org.gradle.api.internal.project.ProjectInternal
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||
import org.jetbrains.kotlin.tooling.core.UnsafeApi
|
||||
|
||||
internal fun ExternalKotlinTargetSoftwareComponent(
|
||||
target: ExternalKotlinTargetImpl,
|
||||
): ExternalKotlinTargetSoftwareComponent {
|
||||
val softwareComponentFactory = (target.project as ProjectInternal).services.get(SoftwareComponentFactory::class.java)
|
||||
val adhocSoftwareComponent = softwareComponentFactory.adhoc(target.targetName)
|
||||
|
||||
adhocSoftwareComponent.addVariantsFromConfiguration(target.apiElementsPublishedConfiguration) { details ->
|
||||
details.mapToMavenScope("compile")
|
||||
}
|
||||
|
||||
adhocSoftwareComponent.addVariantsFromConfiguration(target.runtimeElementsPublishedConfiguration) { details ->
|
||||
details.mapToMavenScope("runtime")
|
||||
}
|
||||
|
||||
@OptIn(UnsafeApi::class)
|
||||
return ExternalKotlinTargetSoftwareComponent(
|
||||
target.project.multiplatformExtension,
|
||||
adhocSoftwareComponent as SoftwareComponentInternal,
|
||||
target.kotlinTargetComponent
|
||||
)
|
||||
}
|
||||
|
||||
internal class ExternalKotlinTargetSoftwareComponent @UnsafeApi constructor(
|
||||
private val multiplatformExtension: KotlinMultiplatformExtension,
|
||||
private val adhocSoftwareComponent: SoftwareComponentInternal,
|
||||
private val kotlinTargetComponent: ExternalKotlinTargetComponent
|
||||
) : ComponentWithCoordinates, ComponentWithVariants, SoftwareComponentInternal {
|
||||
override fun getName(): String = adhocSoftwareComponent.name
|
||||
override fun getUsages(): Set<UsageContext> = adhocSoftwareComponent.usages
|
||||
override fun getVariants(): Set<SoftwareComponent> = multiplatformExtension.metadata().components
|
||||
override fun getCoordinates(): ModuleVersionIdentifier = kotlinTargetComponent.coordinates
|
||||
}
|
||||
+41
-12
@@ -7,12 +7,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp.external
|
||||
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.attributes.Category
|
||||
import org.gradle.api.attributes.Usage
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.jetbrains.kotlin.gradle.ExternalKotlinTargetApi
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.markConsumable
|
||||
import org.jetbrains.kotlin.gradle.plugin.usesPlatformOf
|
||||
import org.jetbrains.kotlin.gradle.tasks.locateOrRegisterTask
|
||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||
@@ -26,6 +28,16 @@ fun <T : DecoratedExternalKotlinTarget> KotlinMultiplatformExtension.createExter
|
||||
val apiElementsConfiguration = project.configurations.maybeCreate(lowerCamelCaseName(descriptor.targetName, "apiElements"))
|
||||
val runtimeElementsConfiguration = project.configurations.maybeCreate(lowerCamelCaseName(descriptor.targetName, "runtimeElements"))
|
||||
|
||||
val apiElementsPublishedConfiguration =
|
||||
project.configurations.maybeCreate(lowerCamelCaseName(descriptor.targetName, "apiElements-published"))
|
||||
|
||||
val runtimeElementsPublishedConfiguration =
|
||||
project.configurations.maybeCreate(lowerCamelCaseName(descriptor.targetName, "runtimeElements-published"))
|
||||
|
||||
val kotlinTargetComponent = ExternalKotlinTargetComponent(
|
||||
ExternalKotlinTargetComponent.TargetProvider.byTargetName(this, descriptor.targetName)
|
||||
)
|
||||
|
||||
val artifactsTaskLocator = ExternalKotlinTargetImpl.ArtifactsTaskLocator { target ->
|
||||
target.project.locateOrRegisterTask<Jar>(lowerCamelCaseName(descriptor.targetName, "jar"))
|
||||
}
|
||||
@@ -34,25 +46,28 @@ fun <T : DecoratedExternalKotlinTarget> KotlinMultiplatformExtension.createExter
|
||||
project = project,
|
||||
targetName = descriptor.targetName,
|
||||
platformType = descriptor.platformType,
|
||||
publishable = true,
|
||||
defaultConfiguration = defaultConfiguration,
|
||||
apiElementsConfiguration = apiElementsConfiguration,
|
||||
runtimeElementsConfiguration = runtimeElementsConfiguration,
|
||||
publishable = true,
|
||||
kotlinComponents = emptySet(),
|
||||
apiElementsPublishedConfiguration = apiElementsPublishedConfiguration,
|
||||
runtimeElementsPublishedConfiguration = runtimeElementsPublishedConfiguration,
|
||||
kotlinTargetComponent = kotlinTargetComponent,
|
||||
artifactsTaskLocator = artifactsTaskLocator
|
||||
)
|
||||
|
||||
apiElementsConfiguration.isCanBeConsumed = true
|
||||
apiElementsConfiguration.isCanBeResolved = false
|
||||
apiElementsConfiguration.usesPlatformOf(target)
|
||||
apiElementsConfiguration.attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(target))
|
||||
apiElementsConfiguration.attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
|
||||
target.setupApiElements(apiElementsConfiguration)
|
||||
target.setupApiElements(apiElementsPublishedConfiguration)
|
||||
target.setupRuntimeElements(runtimeElementsConfiguration)
|
||||
target.setupRuntimeElements(runtimeElementsPublishedConfiguration)
|
||||
apiElementsConfiguration.markConsumable()
|
||||
runtimeElementsConfiguration.markConsumable()
|
||||
|
||||
runtimeElementsConfiguration.isCanBeConsumed = true
|
||||
runtimeElementsConfiguration.isCanBeResolved = false
|
||||
runtimeElementsConfiguration.usesPlatformOf(target)
|
||||
runtimeElementsConfiguration.attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerRuntimeUsage(target))
|
||||
runtimeElementsConfiguration.attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
|
||||
/* Those configurations can not be resolved but also not consumed (not suitable for project to proejct dependencies */
|
||||
apiElementsPublishedConfiguration.isCanBeConsumed = false
|
||||
apiElementsPublishedConfiguration.isCanBeResolved = false
|
||||
runtimeElementsPublishedConfiguration.isCanBeResolved = false
|
||||
runtimeElementsPublishedConfiguration.isCanBeConsumed = false
|
||||
|
||||
val decorated = descriptor.targetFactory.create(DecoratedExternalKotlinTarget.Delegate(target))
|
||||
target.onCreated()
|
||||
@@ -60,6 +75,8 @@ fun <T : DecoratedExternalKotlinTarget> KotlinMultiplatformExtension.createExter
|
||||
descriptor.configure?.invoke(decorated)
|
||||
descriptor.apiElements.configure?.invoke(decorated, apiElementsConfiguration)
|
||||
descriptor.runtimeElements.configure?.invoke(decorated, runtimeElementsConfiguration)
|
||||
descriptor.apiElementsPublished.configure?.invoke(decorated, apiElementsPublishedConfiguration)
|
||||
descriptor.runtimeElementsPublished.configure?.invoke(decorated, runtimeElementsPublishedConfiguration)
|
||||
|
||||
targets.add(decorated)
|
||||
decorated.logger.info("Created ${descriptor.platformType} target")
|
||||
@@ -72,3 +89,15 @@ fun <T : DecoratedExternalKotlinTarget> KotlinMultiplatformExtension.createExter
|
||||
): T {
|
||||
return createExternalKotlinTarget(ExternalKotlinTargetDescriptor(descriptor))
|
||||
}
|
||||
|
||||
private fun ExternalKotlinTargetImpl.setupApiElements(configuration: Configuration) {
|
||||
configuration.usesPlatformOf(this)
|
||||
configuration.attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(this))
|
||||
configuration.attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
|
||||
}
|
||||
|
||||
private fun ExternalKotlinTargetImpl.setupRuntimeElements(configuration: Configuration) {
|
||||
configuration.usesPlatformOf(this)
|
||||
configuration.attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.producerRuntimeUsage(this))
|
||||
configuration.attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.objects.named(Category.LIBRARY))
|
||||
}
|
||||
|
||||
+15
-2
@@ -6,7 +6,9 @@
|
||||
package org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.*
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.DependencySet
|
||||
import org.gradle.api.artifacts.PublishArtifactSet
|
||||
import org.gradle.api.attributes.Attribute
|
||||
import org.gradle.api.attributes.AttributeContainer
|
||||
import org.gradle.api.capabilities.Capability
|
||||
@@ -97,4 +99,15 @@ internal fun copyAttributes(from: AttributeContainer, to: AttributeContainer, ke
|
||||
}
|
||||
|
||||
internal inline fun <reified T> Project.listProperty(noinline itemsProvider: () -> Iterable<T>) =
|
||||
objects.listProperty(T::class.java).apply { set(provider(itemsProvider)) }
|
||||
objects.listProperty(T::class.java).apply { set(provider(itemsProvider)) }
|
||||
|
||||
|
||||
internal fun Configuration.markConsumable(): Configuration = apply {
|
||||
this.isCanBeConsumed = true
|
||||
this.isCanBeResolved = false
|
||||
}
|
||||
|
||||
internal fun Configuration.markResolvable(): Configuration = apply {
|
||||
this.isCanBeConsumed = false
|
||||
this.isCanBeResolved = true
|
||||
}
|
||||
+23
-3
@@ -7,15 +7,20 @@
|
||||
|
||||
package org.jetbrains.kotlin.gradle.externalTargetApi
|
||||
|
||||
import org.gradle.api.publish.PublishingExtension
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
|
||||
import org.jetbrains.kotlin.gradle.android.androidTargetPrototype
|
||||
import org.jetbrains.kotlin.gradle.androidApplication
|
||||
import org.jetbrains.kotlin.gradle.androidLibrary
|
||||
import org.jetbrains.kotlin.gradle.assumeAndroidSdkAvailable
|
||||
import org.jetbrains.kotlin.gradle.buildProjectWithMPP
|
||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||
import org.jetbrains.kotlin.gradle.kpm.idea.mavenCentralCacheRedirector
|
||||
import org.jetbrains.kotlin.gradle.utils.getByType
|
||||
import org.junit.Test
|
||||
import kotlin.test.BeforeTest
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.fail
|
||||
|
||||
class ExternalAndroidTargetPrototypeSmokeTest {
|
||||
|
||||
@@ -27,7 +32,7 @@ class ExternalAndroidTargetPrototypeSmokeTest {
|
||||
@Test
|
||||
fun `apply prototype - evaluate - compilations exist`() {
|
||||
val project = buildProjectWithMPP()
|
||||
project.androidApplication { compileSdk = 31 }
|
||||
project.androidLibrary { compileSdk = 31 }
|
||||
val androidTargetPrototype = project.multiplatformExtension.androidTargetPrototype()
|
||||
project.evaluate()
|
||||
|
||||
@@ -40,7 +45,7 @@ class ExternalAndroidTargetPrototypeSmokeTest {
|
||||
@Test
|
||||
fun `apply prototype - evaluate - configurations can be resolved`() {
|
||||
val project = buildProjectWithMPP()
|
||||
project.androidApplication { compileSdk = 31 }
|
||||
project.androidLibrary { compileSdk = 31 }
|
||||
|
||||
val androidTargetPrototype = project.multiplatformExtension.androidTargetPrototype()
|
||||
project.repositories.mavenLocal()
|
||||
@@ -52,4 +57,19 @@ class ExternalAndroidTargetPrototypeSmokeTest {
|
||||
compilation.runtimeDependencyFiles?.files
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `apply prototype - with maven publish plugin - publication exists`() {
|
||||
val project = buildProjectWithMPP()
|
||||
project.androidLibrary { compileSdk = 31 }
|
||||
project.plugins.apply(MavenPublishPlugin::class.java)
|
||||
project.multiplatformExtension.androidTargetPrototype()
|
||||
project.evaluate()
|
||||
|
||||
val publishing = project.extensions.getByType<PublishingExtension>()
|
||||
val androidPublication = publishing.publications.getByName("android") as MavenPublication
|
||||
if (androidPublication.artifacts.size != 1) fail("Expected one artifact. Found ${androidPublication.artifacts}")
|
||||
val aarArtifact = androidPublication.artifacts.first()
|
||||
assertEquals("aar", aarArtifact.extension)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user