Publish different targets as different software components

This commit is contained in:
Ilya Matveev
2018-08-23 13:54:24 +07:00
committed by Ilya Matveev
parent 91308508bd
commit c23296a0d8
6 changed files with 85 additions and 22 deletions
@@ -9,8 +9,14 @@ import org.gradle.api.Named
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.attributes.HasAttributes
import org.gradle.api.component.ComponentWithCoordinates
import org.gradle.api.internal.component.UsageContext
interface KotlinTargetComponent : ComponentWithCoordinates {
val target: KotlinTarget
val publishable: Boolean
}
interface KotlinTarget: Named, HasAttributes {
val targetName: String
val disambiguationClassifier: String? get() = targetName
@@ -27,6 +33,10 @@ interface KotlinTarget: Named, HasAttributes {
val apiElementsConfigurationName: String
val runtimeElementsConfigurationName: String
val publishable: Boolean
val component: KotlinTargetComponent
fun createUsageContexts(): Set<UsageContext>
override fun getName(): String = targetName
@@ -436,6 +436,7 @@ open class KotlinNativeTargetConfigurator(
group = BasePlugin.BUILD_GROUP
description = "Links ${kind.description} from the '${compilation.name}' " +
"compilation for target '${compilation.platformType.name}'"
enabled = compilation.target.konanTarget.enabledOnCurrentHost
optimized = buildType.optimized
debuggable = buildType.debuggable
@@ -474,6 +475,10 @@ open class KotlinNativeTargetConfigurator(
}
private fun Project.createKlibPublishableArtifact(compilation: KotlinNativeCompilation, compileTask: KotlinNativeCompile) {
if (!compilation.target.konanTarget.enabledOnCurrentHost) {
return
}
val apiElements = configurations.getByName(compilation.target.apiElementsConfigurationName)
val klibArtifact = DefaultPublishArtifact(
compilation.name,
@@ -484,7 +489,6 @@ open class KotlinNativeTargetConfigurator(
compileTask.outputFile.get(),
compileTask
)
compilation.target.disambiguationClassifier?.let { klibArtifact.classifier = it }
project.extensions.getByType(DefaultArtifactPublicationSet::class.java).addCandidate(klibArtifact)
with(apiElements.outgoing) {
@@ -503,17 +507,17 @@ open class KotlinNativeTargetConfigurator(
group = BasePlugin.BUILD_GROUP
description = "Compiles a klibrary from the '${compilation.name}' " +
"compilation for target '${compilation.platformType.name}'"
enabled = compilation.target.konanTarget.enabledOnCurrentHost
outputs.file(outputFile)
outputFile.set(provider {
val targetSubDirectory = compilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty()
val classifier = compilation.target.disambiguationClassifier?.let { "-$it" }.orEmpty()
val compilationName = compilation.compilationName
val klibName = if (compilation.name == KotlinCompilation.MAIN_COMPILATION_NAME)
project.name
else
compilationName
File(project.buildDir, "classes/kotlin/$targetSubDirectory$compilationName/$klibName$classifier.klib")
File(project.buildDir, "classes/kotlin/$targetSubDirectory$compilationName/$klibName.klib")
})
dependsOnCompilerDownloading()
@@ -537,23 +541,23 @@ open class KotlinNativeTargetConfigurator(
}
}
override fun configureArchivesAndComponent(target: KotlinNativeTarget) = with(target.project) {
if (!HostManager().isEnabled(target.konanTarget)) {
return
}
override fun configureArchivesAndComponent(target: KotlinNativeTarget) : Unit = with(target.project) {
tasks.create(target.artifactsTaskName)
target.compilations.all {
createKlibCompilationTask(it)
createBinaryLinkTasks(it)
}
with(configurations.getByName(target.apiElementsConfigurationName)) {
outgoing.attributes.attribute(ArtifactAttributes.ARTIFACT_FORMAT, NativeArtifactFormat.KLIB)
}
}
private fun Task.dependsOnCompilerDownloading() =
dependsOn(KonanCompilerDownloadTask.KONAN_DOWNLOAD_TASK_NAME)
object NativeArtifactFormat {
const val KLIB = "org.jerbrains.kotlin.klib"
const val KLIB = "org.jetbrains.kotlin.klib"
}
}
@@ -90,22 +90,40 @@ class KotlinMultiplatformPlugin(
}
}
private fun configurePublishingWithMavenPublish(project: Project) = project.pluginManager.withPlugin("maven-publish") {
private fun configurePublishingWithMavenPublish(project: Project) = project.pluginManager.withPlugin("maven-publish") { _ ->
val targets = project.multiplatformExtension!!.targets
val kotlinSoftwareComponent = KotlinSoftwareComponent(project, "kotlin", targets)
project.afterEvaluate { project -> // Use afterEvaluate because publications configuration is no more lazy since Gradle 4.9
project.extensions.configure(PublishingExtension::class.java) { publishing ->
// The root publication.
publishing.publications.create("kotlin", MavenPublication::class.java) { publication ->
publication.from(kotlinSoftwareComponent)
(publication as MavenPublicationInternal).publishWithOriginalFileName()
publication.artifactId = project.name
publication.groupId = project.group.toString()
}
// Create separate publications for all publishable targets
kotlinSoftwareComponent.variants.filter { it.publishable }.forEach { variant ->
val coordinates = variant.coordinates
val name = variant.target.disambiguateName("kotlin")
publishing.publications.create(name, MavenPublication::class.java) { publication ->
publication.from(variant)
(publication as MavenPublicationInternal).publishWithOriginalFileName()
publication.artifactId = coordinates.name
publication.groupId = coordinates.group
publication.version = coordinates.version
}
}
}
}
project.components.add(kotlinSoftwareComponent)
targets.all {
project.components.add(it.component)
}
}
private fun configureSourceSets(project: Project) = with (project.kotlinExtension as KotlinMultiplatformExtension) {
@@ -6,24 +6,28 @@
package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.DependencyConstraint
import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.artifacts.PublishArtifact
import org.gradle.api.artifacts.*
import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.attributes.Usage
import org.gradle.api.capabilities.Capability
import org.gradle.api.component.ComponentWithVariants
import org.gradle.api.internal.artifacts.DefaultModuleVersionIdentifier
import org.gradle.api.internal.component.SoftwareComponentInternal
import org.gradle.api.internal.component.UsageContext
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.plugin.KotlinTargetComponent
import org.jetbrains.kotlin.gradle.plugin.usageByName
class KotlinSoftwareComponent(
private val project: Project,
private val name: String,
private val kotlinTargets: Iterable<KotlinTarget>
) : SoftwareComponentInternal {
override fun getUsages(): Set<UsageContext> = kotlinTargets.flatMap { it.createUsageContexts() }.toSet()
) : SoftwareComponentInternal, ComponentWithVariants {
override fun getUsages(): Set<UsageContext> = emptySet()
override fun getVariants(): Set<KotlinTargetComponent> =
kotlinTargets.map { it.component }.toSet()
override fun getName(): String = name
@@ -33,6 +37,24 @@ class KotlinSoftwareComponent(
}
}
class KotlinVariant(
private val project: Project,
override val target: KotlinTarget
) : SoftwareComponentInternal, KotlinTargetComponent {
override fun getCoordinates() = DefaultModuleVersionIdentifier(
project.group.toString(),
"${project.name}-${target.name.toLowerCase()}",
project.version.toString()
)
override fun getUsages(): Set<UsageContext> = target.createUsageContexts()
override fun getName(): String = target.name
override val publishable: Boolean
get() = target.publishable
}
// At the moment all KN artifacts have JAVA_API usage.
// TODO: Replace it with a specific usage
object NativeUsage {
@@ -73,4 +95,4 @@ internal class KotlinPlatformUsageContext(
// FIXME this is a stub for a function that is not present in the Gradle API that we compile against
fun getGlobalExcludes(): Set<Any> = emptySet()
}
}
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.gradle.tasks.KonanCompilerDownloadTask
import org.jetbrains.kotlin.gradle.tasks.KonanCompilerDownloadTask.Companion.KONAN_DOWNLOAD_TASK_NAME
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget
abstract class KotlinOnlyTargetPreset<T : KotlinCompilation>(
@@ -264,6 +265,9 @@ class KotlinNativeTargetPreset(
}
}
internal val KonanTarget.enabledOnCurrentHost
get() = HostManager().isEnabled(this)
internal val KonanTarget.presetName: String
get() = when(this) {
KonanTarget.ANDROID_ARM32 -> "androidNativeArm32"
@@ -11,15 +11,12 @@ import org.gradle.api.attributes.Attribute
import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.internal.component.UsageContext
import org.gradle.api.plugins.JavaPlugin
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationToRunnableFiles
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.konan.target.KonanTarget
abstract class AbstractKotlinTarget (
override val project: Project
final override val project: Project
) : KotlinTarget {
private val attributeContainer = HierarchyAttributeContainer(parent = null)
@@ -39,6 +36,11 @@ abstract class AbstractKotlinTarget (
override fun toString(): String = "target $name ($platformType)"
override val publishable: Boolean
get() = true
override val component: KotlinTargetComponent = KotlinVariant(project, this)
override fun createUsageContexts(): Set<UsageContext> =
setOf(
KotlinPlatformUsageContext(
@@ -134,6 +136,9 @@ class KotlinNativeTarget(
override val artifactsTaskName: String
get() = disambiguateName("link")
override val publishable: Boolean
get() = konanTarget.enabledOnCurrentHost
companion object {
val konanTargetAttribute = Attribute.of(
"org.jetbrains.kotlin.native.target",