[gradle][plugin][konan] deployment of kotlin-native artifacts via maven machinery

This commit is contained in:
Vasily Levchenko
2018-02-15 21:11:48 +03:00
committed by Vasily Levchenko
parent ddcbe68a5b
commit 5185a17c24
6 changed files with 122 additions and 12 deletions
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.gradle.plugin
import groovy.lang.Closure
import org.gradle.api.Task
import org.gradle.api.file.FileCollection
import org.gradle.api.internal.project.ProjectInternal
@@ -68,6 +69,8 @@ abstract class KonanCompileConfig<T: KonanCompileTask>(name: String,
override fun entryPoint(entryPoint: String) = forEach { it.entryPoint(entryPoint) }
override fun measureTime(flag: Boolean) = forEach { it.measureTime(flag) }
override fun dependencies(closure: Closure<Unit>) = forEach { it.dependencies(closure) }
}
open class KonanProgram(name: String,
@@ -84,5 +84,6 @@ open class KonanInteropLibrary(name: String,
override fun link(vararg files: Any) = forEach { it.link(*files) }
override fun link(files: FileCollection) = forEach { it.link(files) }
override fun dependencies(closure: Closure<Unit>) = forEach { it.dependencies(closure) }
}
@@ -17,9 +17,23 @@
package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.*
import org.gradle.api.artifacts.PublishArtifact
import org.gradle.api.attributes.Usage
import org.gradle.api.component.ComponentWithVariants
import org.gradle.api.component.SoftwareComponent
import org.gradle.api.file.FileCollection
import org.gradle.api.internal.FeaturePreviews
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.plugins.AppliedPlugin
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.internal.PublicationInternal
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.publish.maven.internal.publication.MavenPublicationInternal
import org.gradle.language.cpp.internal.NativeVariant
import org.gradle.language.nativeplatform.internal.Names
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
import org.jetbrains.kotlin.gradle.plugin.KonanPlugin.Companion.COMPILE_ALL_TASK_NAME
import org.jetbrains.kotlin.gradle.plugin.tasks.*
@@ -242,6 +256,18 @@ open class KonanExtension {
var jvmArgs = mutableListOf<String>()
}
open class KonanSoftwareComponent(val project: ProjectInternal?): SoftwareComponentInternal, ComponentWithVariants {
private val usages = mutableSetOf<UsageContext>()
override fun getUsages(): MutableSet<out UsageContext> = usages
private val variants = mutableSetOf<SoftwareComponent>()
override fun getName() = "main"
override fun getVariants(): Set<out SoftwareComponent> = variants
fun addVariant(component: SoftwareComponent) = variants.add(component)
}
class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderRegistry)
: Plugin<ProjectInternal> {
@@ -259,6 +285,7 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR
internal const val KONAN_DOWNLOAD_TASK_NAME = "checkKonanCompiler"
internal const val KONAN_GENERATE_CMAKE_TASK_NAME = "generateCMake"
internal const val COMPILE_ALL_TASK_NAME = "compileKonan"
internal const val KONAN_MAIN_VARIANT = "konan_main_variant"
internal const val KONAN_EXTENSION_NAME = "konan"
@@ -272,15 +299,20 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR
project.delete(it.artifact)
}
override fun apply(project: ProjectInternal?) {
if (project == null) { return }
if (project == null) {
return
}
registry.register(KonanToolingModelBuilder)
project.plugins.apply("base")
// Create necessary tasks and extensions.
project.tasks.create(KONAN_DOWNLOAD_TASK_NAME, KonanCompilerDownloadTask::class.java)
project.tasks.create(KONAN_GENERATE_CMAKE_TASK_NAME, KonanGenerateCMakeTask::class.java)
project.extensions.create(KONAN_EXTENSION_NAME, KonanExtension::class.java)
project.extensions.create(KonanArtifactContainer::class.java, ARTIFACTS_CONTAINER_NAME, KonanArtifactContainer::class.java, project)
val mainVariant = project.extensions.create(ComponentWithVariants::class.java, KONAN_MAIN_VARIANT, KonanSoftwareComponent::class.java, project)
val container = project.extensions.create(KonanArtifactContainer::class.java, ARTIFACTS_CONTAINER_NAME, KonanArtifactContainer::class.java, project)
// Set additional project properties like konan.home, konan.build.targets etc.
if (!project.hasProperty(ProjectProperty.KONAN_HOME)) {
@@ -306,7 +338,7 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR
doLast {
for (task in project.tasks
.withType(KonanCompileProgramTask::class.java)
.matching { !it.isCrossCompile}) {
.matching { !it.isCrossCompile }) {
project.exec {
with(it) {
commandLine(task.artifact.canonicalPath)
@@ -318,8 +350,38 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR
}
}
}
//project.gradle.experimentalFeatures.enable()
project.gradle.services.get(FeaturePreviews::class.java).enableFeature(FeaturePreviews.Feature.GRADLE_METADATA)
// Enable multiplatform support
project.pluginManager.apply(KotlinNativePlatformPlugin::class.java)
project.afterEvaluate {
val konanSoftwareComponent = mainVariant as KonanSoftwareComponent
project.pluginManager.withPlugin("maven-publish") {
container.all {
val buildingConfig = it
val artifactId = buildingConfig.name
project.extensions.configure(PublishingExtension::class.java) {
val publishing = it
it.publications.create(artifactId, MavenPublication::class.java) {
it.artifactId = artifactId
it.groupId = project.group.toString()
it.from(konanSoftwareComponent)
(it as MavenPublicationInternal).publishWithOriginalFileName()
}
for (v in konanSoftwareComponent.variants) {
// TODO: with gradle 4.7 don't forget to change to SoftwareComponentsWithCoordinates
val name = "${v.name}/$artifactId"
publishing.publications.create(name, MavenPublication::class.java) {
it.artifactId = "${artifactId}-${v.name}"
it.groupId = project.group.toString()
it.version = project.version.toString()
it.from(v)
(it as MavenPublicationInternal).publishWithOriginalFileName()
}
}
}
}
}
}
}
}
@@ -31,6 +31,7 @@ interface KonanArtifactWithLibrariesSpec: KonanArtifactSpec {
fun libraries(configure: KonanLibrariesSpec.() -> Unit)
fun noDefaultLibs(flag: Boolean)
fun dependencies(closure: Closure<Unit>)
}
interface KonanBuildingSpec: KonanArtifactWithLibrariesSpec {
@@ -20,18 +20,21 @@ import groovy.lang.Closure
import org.gradle.api.Action
import org.gradle.api.DefaultTask
import org.gradle.api.Project
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Nested
import org.gradle.api.tasks.OutputFile
import org.gradle.api.artifacts.Configuration
import org.gradle.api.artifacts.PublishArtifact
import org.gradle.api.attributes.Attribute
import org.gradle.api.attributes.Usage
import org.gradle.api.tasks.*
import org.gradle.language.cpp.CppBinary
import org.gradle.language.cpp.internal.NativeVariant
import org.gradle.language.nativeplatform.internal.Names
import org.gradle.nativeplatform.Linkage
import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.gradle.plugin.KonanArtifactSpec
import org.jetbrains.kotlin.gradle.plugin.KonanArtifactWithLibrariesSpec
import org.jetbrains.kotlin.gradle.plugin.KonanLibrariesSpec
import org.jetbrains.kotlin.gradle.plugin.konanTargets
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget
import java.io.File
import java.util.*
internal val Project.host
get() = HostManager.host.visibleName
@@ -63,6 +66,8 @@ abstract class KonanArtifactTask: KonanTargetableTask(), KonanArtifactSpec {
@Internal lateinit var destinationDir: File
@Internal lateinit var artifactName: String
@Internal lateinit var platformConfiguration: Configuration
@Internal lateinit var configuration: Configuration
protected val artifactFullName: String
@Internal get() = "$artifactPrefix$artifactName$artifactSuffix"
@@ -80,8 +85,39 @@ abstract class KonanArtifactTask: KonanTargetableTask(), KonanArtifactSpec {
super.init(target)
this.destinationDir = destinationDir
this.artifactName = artifactName
configuration = project.configurations.maybeCreate("artifact$artifactName")
platformConfiguration = project.configurations.create("artifact${artifactName}_${target.name}")
platformConfiguration.extendsFrom(configuration)
platformConfiguration.attributes{
it.attribute(Usage.USAGE_ATTRIBUTE, project.objects.named(Usage::class.java, Usage.NATIVE_LINK))
it.attribute(CppBinary.LINKAGE_ATTRIBUTE, Linkage.STATIC)
it.attribute(CppBinary.OPTIMIZED_ATTRIBUTE, false)
it.attribute(CppBinary.DEBUGGABLE_ATTRIBUTE, false)
it.attribute(Attribute.of("org.gradle.native.kotlin.platform", String::class.java), target.name)
}
project.pluginManager.withPlugin("maven-publish") {
platformConfiguration.artifacts.add(object: PublishArtifact {
override fun getName() = "${artifact.name}/${target.name}"
override fun getExtension() = if (artifactSuffix.startsWith('.')) artifactSuffix.substring(1) else artifactSuffix
override fun getType() = artifactSuffix
override fun getClassifier():String? = target.name
override fun getFile() = artifact
override fun getDate() = Date(artifact.lastModified())
override fun getBuildDependencies(): TaskDependency = this@KonanArtifactTask.taskDependencies
})
val objectFactory = project.objects
val linkUsage = objectFactory.named(Usage::class.java, Usage.NATIVE_LINK)
val runtimeUsage = objectFactory.named(Usage::class.java, Usage.NATIVE_RUNTIME)
val konanSoftwareComponent = project.extensions.getByName(KonanPlugin.KONAN_MAIN_VARIANT) as KonanSoftwareComponent
konanSoftwareComponent.addVariant(NativeVariant(Names.of(target.name), linkUsage, null, linkUsage, platformConfiguration))
}
}
fun dependencies(closure: Closure<Unit>) {
if (konanTarget in project.konanTargets)
project.dependencies(closure)
}
// DSL.
override fun artifactName(name: String) {
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.gradle.plugin.tasks
import org.gradle.api.artifacts.FileCollectionDependency
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.*
import org.jetbrains.kotlin.gradle.plugin.*
@@ -98,6 +99,12 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec {
addArgs("-repo", libraries.repos.map { it.canonicalPath })
if (platformConfiguration.files.isNotEmpty()) {
platformConfiguration.files.filter { it.name.endsWith(".klib") }.forEach {
addFileArgs("-library", project.files(it.absolutePath))
}
}
addFileArgs("-library", libraries.files)
addArgs("-library", libraries.namedKlibs)
addArgs("-library", libraries.artifacts.map { it.artifact.canonicalPath })