diff --git a/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTarget.kt b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTarget.kt index 6ca5e36f7ab..cb71c6f1cbe 100644 --- a/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTarget.kt +++ b/libraries/tools/kotlin-gradle-plugin-api/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTarget.kt @@ -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 override fun getName(): String = targetName diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt index 3e2b9ded83a..73e939fed4f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt @@ -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" } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt index 67d76ca776a..704428ba331 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt @@ -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) { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt index 6b339e27f01..156a371c1ef 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinSoftwareComponent.kt @@ -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 -) : SoftwareComponentInternal { - override fun getUsages(): Set = kotlinTargets.flatMap { it.createUsageContexts() }.toSet() +) : SoftwareComponentInternal, ComponentWithVariants { + + override fun getUsages(): Set = emptySet() + + override fun getVariants(): Set = + 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 = 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 = emptySet() -} \ No newline at end of file +} diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargetPresets.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargetPresets.kt index 5a0e9db6e9c..15cc85794d9 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargetPresets.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargetPresets.kt @@ -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( @@ -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" diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt index 6b05061318b..0518cb8b871 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt @@ -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 = 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",