Merge commit 'ffdd43b8083c4fd7795799e351f23d997534a43e'; commit 'af3bf257ba1584fd2f3d690fe76c48778699e29b'; commit '83d22a3744df1b79545070fbb9ea13ee1182a614'; commit 'b7cf915e884caea8cabc2db5f611fa5d5a7536e8'; commit '522a5b8c3ffd84c11cb70efead9c152e8d62cd37'; commit '37a117574f314263360350964e80ce182c093e31' into move-packages-on-master
This commit is contained in:
-7
@@ -1,7 +0,0 @@
|
|||||||
<component name="InspectionProjectProfileManager">
|
|
||||||
<settings>
|
|
||||||
<option name="PROJECT_PROFILE" value="idea.default" />
|
|
||||||
<option name="USE_PROJECT_PROFILE" value="true" />
|
|
||||||
<version value="1.0" />
|
|
||||||
</settings>
|
|
||||||
</component>
|
|
||||||
+788
@@ -0,0 +1,788 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.api.artifacts.*
|
||||||
|
import org.gradle.api.artifacts.type.ArtifactTypeDefinition
|
||||||
|
import org.gradle.api.attributes.Usage
|
||||||
|
import org.gradle.api.attributes.Usage.USAGE_ATTRIBUTE
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.internal.artifacts.ArtifactAttributes
|
||||||
|
import org.gradle.api.internal.artifacts.publish.DefaultPublishArtifact
|
||||||
|
import org.gradle.api.internal.plugins.DefaultArtifactPublicationSet
|
||||||
|
import org.gradle.api.internal.plugins.DslObject
|
||||||
|
import org.gradle.api.plugins.BasePlugin
|
||||||
|
import org.gradle.api.plugins.JavaBasePlugin
|
||||||
|
import org.gradle.api.tasks.Copy
|
||||||
|
import org.gradle.api.tasks.Delete
|
||||||
|
import org.gradle.api.tasks.Exec
|
||||||
|
import org.gradle.api.tasks.bundling.Jar
|
||||||
|
import org.gradle.api.tasks.testing.Test
|
||||||
|
import org.gradle.language.base.plugins.LifecycleBasePlugin
|
||||||
|
import org.gradle.language.jvm.tasks.ProcessResources
|
||||||
|
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeBinaryContainer
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.MAIN_COMPILATION_NAME
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation.Companion.TEST_COMPILATION_NAME
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinNativeCompile
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.CInteropProcess
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinNativeLink
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
|
abstract class AbstractKotlinTargetConfigurator<KotlinTargetType : KotlinTarget>(
|
||||||
|
protected val createDefaultSourceSets: Boolean,
|
||||||
|
protected val createTestCompilation: Boolean
|
||||||
|
) {
|
||||||
|
open fun configureTarget(
|
||||||
|
target: KotlinTargetType
|
||||||
|
) {
|
||||||
|
configureCompilationDefaults(target)
|
||||||
|
configureCompilations(target)
|
||||||
|
defineConfigurationsForTarget(target)
|
||||||
|
configureArchivesAndComponent(target)
|
||||||
|
configureTest(target)
|
||||||
|
configureBuild(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
abstract protected fun configureArchivesAndComponent(target: KotlinTargetType)
|
||||||
|
abstract protected fun configureTest(target: KotlinTargetType)
|
||||||
|
|
||||||
|
private fun Project.registerOutputsForStaleOutputCleanup(kotlinCompilation: KotlinCompilation<*>) {
|
||||||
|
val cleanTask = tasks.getByName(LifecycleBasePlugin.CLEAN_TASK_NAME) as Delete
|
||||||
|
cleanTask.delete(kotlinCompilation.output.allOutputs)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun configureCompilations(platformTarget: KotlinTargetType) {
|
||||||
|
val project = platformTarget.project
|
||||||
|
val main = platformTarget.compilations.create(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
|
||||||
|
platformTarget.compilations.all {
|
||||||
|
project.registerOutputsForStaleOutputCleanup(it)
|
||||||
|
it.compileDependencyFiles = project.configurations.maybeCreate(it.compileDependencyConfigurationName)
|
||||||
|
if (it is KotlinCompilationToRunnableFiles) {
|
||||||
|
it.runtimeDependencyFiles = project.configurations.maybeCreate(it.runtimeDependencyConfigurationName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createTestCompilation) {
|
||||||
|
platformTarget.compilations.create(KotlinCompilation.TEST_COMPILATION_NAME).apply {
|
||||||
|
compileDependencyFiles = project.files(
|
||||||
|
main.output.allOutputs,
|
||||||
|
project.configurations.maybeCreate(compileDependencyConfigurationName)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (this is KotlinCompilationToRunnableFiles) {
|
||||||
|
runtimeDependencyFiles = project.files(
|
||||||
|
output.allOutputs,
|
||||||
|
main.output.allOutputs,
|
||||||
|
project.configurations.maybeCreate(runtimeDependencyConfigurationName)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun configureCompilationDefaults(target: KotlinTargetType) {
|
||||||
|
val project = target.project
|
||||||
|
|
||||||
|
target.compilations.all { compilation ->
|
||||||
|
defineConfigurationsForCompilation(compilation)
|
||||||
|
|
||||||
|
if (createDefaultSourceSets) {
|
||||||
|
project.kotlinExtension.sourceSets.maybeCreate(compilation.defaultSourceSetName).also { sourceSet ->
|
||||||
|
compilation.source(sourceSet) // also adds dependencies, requires the configurations for target and source set to exist at this point
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compilation is KotlinCompilationWithResources) {
|
||||||
|
configureResourceProcessing(compilation, project.files(Callable { compilation.allKotlinSourceSets.map { it.resources } }))
|
||||||
|
}
|
||||||
|
|
||||||
|
createLifecycleTask(compilation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun configureResourceProcessing(
|
||||||
|
compilation: KotlinCompilationWithResources<*>,
|
||||||
|
resourceSet: FileCollection
|
||||||
|
) {
|
||||||
|
val project = compilation.target.project
|
||||||
|
|
||||||
|
val resourcesTask = project.tasks.maybeCreate(compilation.processResourcesTaskName, ProcessResources::class.java)
|
||||||
|
resourcesTask.description = "Processes $resourceSet."
|
||||||
|
DslObject(resourcesTask).conventionMapping.map("destinationDir") { project.file(compilation.output.resourcesDir) }
|
||||||
|
resourcesTask.from(resourceSet)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun createLifecycleTask(compilation: KotlinCompilation<*>) {
|
||||||
|
val project = compilation.target.project
|
||||||
|
|
||||||
|
compilation.output.classesDirs.from(project.files().builtBy(compilation.compileAllTaskName))
|
||||||
|
|
||||||
|
project.tasks.create(compilation.compileAllTaskName).apply {
|
||||||
|
group = LifecycleBasePlugin.BUILD_GROUP
|
||||||
|
description = "Assembles outputs for compilation '${compilation.name}' of target '${compilation.target.name}'"
|
||||||
|
dependsOn(compilation.compileKotlinTaskName)
|
||||||
|
if (compilation is KotlinCompilationWithResources) {
|
||||||
|
dependsOn(compilation.processResourcesTaskName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected open fun defineConfigurationsForTarget(target: KotlinTargetType) {
|
||||||
|
val project = target.project
|
||||||
|
|
||||||
|
val configurations = project.configurations
|
||||||
|
|
||||||
|
val defaultConfiguration = configurations.maybeCreate(target.defaultConfigurationName).apply {
|
||||||
|
setupAsLocalTargetSpecificConfigurationIfSupported(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
val mainCompilation = target.compilations.maybeCreate(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
|
||||||
|
val compileConfiguration = configurations.maybeCreate(mainCompilation.deprecatedCompileConfigurationName)
|
||||||
|
val implementationConfiguration = configurations.maybeCreate(mainCompilation.implementationConfigurationName)
|
||||||
|
|
||||||
|
val runtimeOnlyConfiguration = configurations.maybeCreate(mainCompilation.runtimeOnlyConfigurationName)
|
||||||
|
|
||||||
|
val apiElementsConfiguration = configurations.maybeCreate(target.apiElementsConfigurationName).apply {
|
||||||
|
description = "API elements for main."
|
||||||
|
isVisible = false
|
||||||
|
isCanBeResolved = false
|
||||||
|
isCanBeConsumed = true
|
||||||
|
attributes.attribute<Usage>(USAGE_ATTRIBUTE, KotlinUsages.producerApiUsage(target))
|
||||||
|
extendsFrom(configurations.maybeCreate(mainCompilation.apiConfigurationName))
|
||||||
|
if (mainCompilation is KotlinCompilationToRunnableFiles) {
|
||||||
|
val runtimeConfiguration = configurations.maybeCreate(mainCompilation.deprecatedRuntimeConfigurationName)
|
||||||
|
extendsFrom(runtimeConfiguration)
|
||||||
|
}
|
||||||
|
usesPlatformOf(target)
|
||||||
|
setupAsPublicConfigurationIfSupported(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mainCompilation is KotlinCompilationToRunnableFiles<*>) {
|
||||||
|
val runtimeElementsConfiguration = configurations.maybeCreate(target.runtimeElementsConfigurationName).apply {
|
||||||
|
description = "Elements of runtime for main."
|
||||||
|
isVisible = false
|
||||||
|
isCanBeConsumed = true
|
||||||
|
isCanBeResolved = false
|
||||||
|
attributes.attribute<Usage>(USAGE_ATTRIBUTE, KotlinUsages.producerRuntimeUsage(target))
|
||||||
|
val runtimeConfiguration = configurations.maybeCreate(mainCompilation.deprecatedRuntimeConfigurationName)
|
||||||
|
extendsFrom(implementationConfiguration, runtimeOnlyConfiguration, runtimeConfiguration)
|
||||||
|
usesPlatformOf(target)
|
||||||
|
setupAsPublicConfigurationIfSupported(target)
|
||||||
|
}
|
||||||
|
defaultConfiguration.extendsFrom(runtimeElementsConfiguration)
|
||||||
|
} else {
|
||||||
|
defaultConfiguration.extendsFrom(apiElementsConfiguration)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createTestCompilation) {
|
||||||
|
val testCompilation = target.compilations.getByName(KotlinCompilation.TEST_COMPILATION_NAME)
|
||||||
|
val compileTestsConfiguration = configurations.maybeCreate(testCompilation.deprecatedCompileConfigurationName)
|
||||||
|
val testImplementationConfiguration = configurations.maybeCreate(testCompilation.implementationConfigurationName)
|
||||||
|
val testRuntimeOnlyConfiguration = configurations.maybeCreate(testCompilation.runtimeOnlyConfigurationName)
|
||||||
|
|
||||||
|
compileTestsConfiguration.extendsFrom(compileConfiguration)
|
||||||
|
testImplementationConfiguration.extendsFrom(implementationConfiguration)
|
||||||
|
testRuntimeOnlyConfiguration.extendsFrom(runtimeOnlyConfiguration)
|
||||||
|
|
||||||
|
if (mainCompilation is KotlinCompilationToRunnableFiles && testCompilation is KotlinCompilationToRunnableFiles) {
|
||||||
|
val runtimeConfiguration = configurations.maybeCreate(mainCompilation.deprecatedRuntimeConfigurationName)
|
||||||
|
val testRuntimeConfiguration = configurations.maybeCreate(testCompilation.deprecatedRuntimeConfigurationName)
|
||||||
|
testRuntimeConfiguration.extendsFrom(runtimeConfiguration)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun configureBuild(target: KotlinTargetType) {
|
||||||
|
val project = target.project
|
||||||
|
|
||||||
|
val buildNeeded = project.tasks.getByName(JavaBasePlugin.BUILD_NEEDED_TASK_NAME)
|
||||||
|
val buildDependent = project.tasks.getByName(JavaBasePlugin.BUILD_DEPENDENTS_TASK_NAME)
|
||||||
|
|
||||||
|
if (createTestCompilation) {
|
||||||
|
val testCompilation = target.compilations.getByName(KotlinCompilation.TEST_COMPILATION_NAME)
|
||||||
|
if (testCompilation is KotlinCompilationToRunnableFiles) {
|
||||||
|
addDependsOnTaskInOtherProjects(buildNeeded, true, testCompilation.deprecatedRuntimeConfigurationName)
|
||||||
|
addDependsOnTaskInOtherProjects(buildDependent, false, testCompilation.deprecatedRuntimeConfigurationName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addDependsOnTaskInOtherProjects(task: Task, useDependedOn: Boolean, configurationName: String) {
|
||||||
|
val project = task.project
|
||||||
|
val configuration = project.configurations.getByName(configurationName)
|
||||||
|
task.dependsOn(configuration.getTaskDependencyFromProjectDependency(useDependedOn, task.name))
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val testTaskNameSuffix = "test"
|
||||||
|
|
||||||
|
fun defineConfigurationsForCompilation(
|
||||||
|
compilation: KotlinCompilation<*>
|
||||||
|
) {
|
||||||
|
val target = compilation.target
|
||||||
|
val configurations = target.project.configurations
|
||||||
|
|
||||||
|
val compileConfiguration = configurations.maybeCreate(compilation.deprecatedCompileConfigurationName).apply {
|
||||||
|
setupAsLocalTargetSpecificConfigurationIfSupported(target)
|
||||||
|
isVisible = false
|
||||||
|
isCanBeResolved = true // Needed for IDE import
|
||||||
|
description = "Dependencies for $compilation (deprecated, use '${compilation.implementationConfigurationName} ' instead)."
|
||||||
|
}
|
||||||
|
|
||||||
|
val apiConfiguration = configurations.maybeCreate(compilation.apiConfigurationName).apply {
|
||||||
|
extendsFrom(compileConfiguration)
|
||||||
|
isVisible = false
|
||||||
|
isCanBeConsumed = false
|
||||||
|
isCanBeResolved = false
|
||||||
|
description = "API dependencies for $compilation."
|
||||||
|
}
|
||||||
|
|
||||||
|
val implementationConfiguration = configurations.maybeCreate(compilation.implementationConfigurationName).apply {
|
||||||
|
extendsFrom(compileConfiguration, apiConfiguration)
|
||||||
|
isVisible = false
|
||||||
|
isCanBeConsumed = false
|
||||||
|
isCanBeResolved = false
|
||||||
|
description = "Implementation only dependencies for $compilation."
|
||||||
|
}
|
||||||
|
|
||||||
|
val compileOnlyConfiguration = configurations.maybeCreate(compilation.compileOnlyConfigurationName).apply {
|
||||||
|
setupAsLocalTargetSpecificConfigurationIfSupported(target)
|
||||||
|
isVisible = false
|
||||||
|
isCanBeResolved = true // Needed for IDE import
|
||||||
|
description = "Compile only dependencies for $compilation."
|
||||||
|
}
|
||||||
|
|
||||||
|
val compileClasspathConfiguration = configurations.maybeCreate(compilation.compileDependencyConfigurationName).apply {
|
||||||
|
extendsFrom(compileOnlyConfiguration, implementationConfiguration)
|
||||||
|
usesPlatformOf(target)
|
||||||
|
isVisible = false
|
||||||
|
isCanBeConsumed = false
|
||||||
|
attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.consumerApiUsage(compilation.target))
|
||||||
|
description = "Compile classpath for $compilation."
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compilation is KotlinCompilationToRunnableFiles) {
|
||||||
|
val runtimeConfiguration = configurations.maybeCreate(compilation.deprecatedRuntimeConfigurationName).apply {
|
||||||
|
setupAsLocalTargetSpecificConfigurationIfSupported(target)
|
||||||
|
extendsFrom(compileConfiguration)
|
||||||
|
isVisible = false
|
||||||
|
isCanBeResolved = true // Needed for IDE import
|
||||||
|
description =
|
||||||
|
"Runtime dependencies for $compilation (deprecated, use '${compilation.runtimeOnlyConfigurationName} ' instead)."
|
||||||
|
}
|
||||||
|
|
||||||
|
val runtimeOnlyConfiguration = configurations.maybeCreate(compilation.runtimeOnlyConfigurationName).apply {
|
||||||
|
isVisible = false
|
||||||
|
isCanBeConsumed = false
|
||||||
|
isCanBeResolved = false
|
||||||
|
description = "Runtime only dependencies for $compilation."
|
||||||
|
}
|
||||||
|
|
||||||
|
val runtimeClasspathConfiguration = configurations.maybeCreate(compilation.runtimeDependencyConfigurationName).apply {
|
||||||
|
extendsFrom(runtimeOnlyConfiguration, runtimeConfiguration, implementationConfiguration)
|
||||||
|
usesPlatformOf(target)
|
||||||
|
isVisible = false
|
||||||
|
isCanBeConsumed = false
|
||||||
|
isCanBeResolved = true
|
||||||
|
attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.consumerRuntimeUsage(compilation.target))
|
||||||
|
description = "Runtime classpath of $compilation."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val KotlinCompilation<*>.deprecatedCompileConfigurationName: String
|
||||||
|
get() = disambiguateName("compile")
|
||||||
|
|
||||||
|
internal val KotlinCompilationToRunnableFiles<*>.deprecatedRuntimeConfigurationName: String
|
||||||
|
get() = disambiguateName("runtime")
|
||||||
|
|
||||||
|
open class KotlinTargetConfigurator<KotlinCompilationType : KotlinCompilation<*>>(
|
||||||
|
createDefaultSourceSets: Boolean,
|
||||||
|
createTestCompilation: Boolean
|
||||||
|
) : AbstractKotlinTargetConfigurator<KotlinOnlyTarget<KotlinCompilationType>>(
|
||||||
|
createDefaultSourceSets,
|
||||||
|
createTestCompilation
|
||||||
|
) {
|
||||||
|
|
||||||
|
override fun configureArchivesAndComponent(target: KotlinOnlyTarget<KotlinCompilationType>) {
|
||||||
|
val project = target.project
|
||||||
|
|
||||||
|
val mainCompilation = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
|
||||||
|
val jar = project.tasks.create(target.artifactsTaskName, Jar::class.java)
|
||||||
|
jar.description = "Assembles a jar archive containing the main classes."
|
||||||
|
jar.group = BasePlugin.BUILD_GROUP
|
||||||
|
jar.from(mainCompilation.output.allOutputs)
|
||||||
|
|
||||||
|
val apiElementsConfiguration = project.configurations.getByName(target.apiElementsConfigurationName)
|
||||||
|
|
||||||
|
target.disambiguationClassifier?.let { jar.appendix = it.toLowerCase() }
|
||||||
|
|
||||||
|
// Workaround: adding the artifact during configuration seems to interfere with the Java plugin, which results into missing
|
||||||
|
// task dependency 'assemble -> jar' if the Java plugin is applied after this steps
|
||||||
|
project.afterEvaluate {
|
||||||
|
project.artifacts.add(Dependency.ARCHIVES_CONFIGURATION, jar) { jarArtifact ->
|
||||||
|
jarArtifact.builtBy(jar)
|
||||||
|
jarArtifact.type = ArtifactTypeDefinition.JAR_TYPE
|
||||||
|
|
||||||
|
addJar(apiElementsConfiguration, jarArtifact)
|
||||||
|
|
||||||
|
if (mainCompilation is KotlinCompilationToRunnableFiles<*>) {
|
||||||
|
val runtimeConfiguration = project.configurations.getByName(mainCompilation.deprecatedRuntimeConfigurationName)
|
||||||
|
val runtimeElementsConfiguration = project.configurations.getByName(target.runtimeElementsConfigurationName)
|
||||||
|
addJar(runtimeConfiguration, jarArtifact)
|
||||||
|
addJar(runtimeElementsConfiguration, jarArtifact)
|
||||||
|
// TODO Check Gradle's special split into variants for classes & resources -- do we need that too?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun configureTest(target: KotlinOnlyTarget<KotlinCompilationType>) {
|
||||||
|
val testCompilation = target.compilations.findByName(KotlinCompilation.TEST_COMPILATION_NAME) as? KotlinCompilationToRunnableFiles<*>
|
||||||
|
?: return // Otherwise, there is no runtime classpath
|
||||||
|
|
||||||
|
target.project.tasks.create(lowerCamelCaseName(target.targetName, testTaskNameSuffix), Test::class.java).apply {
|
||||||
|
project.afterEvaluate {
|
||||||
|
// use afterEvaluate to override the JavaPlugin defaults for Test tasks
|
||||||
|
conventionMapping.map("testClassesDirs") { testCompilation.output.classesDirs }
|
||||||
|
conventionMapping.map("classpath") { testCompilation.runtimeDependencyFiles }
|
||||||
|
description = "Runs the unit tests."
|
||||||
|
group = JavaBasePlugin.VERIFICATION_GROUP
|
||||||
|
target.project.tasks.findByName(JavaBasePlugin.CHECK_TASK_NAME)?.dependsOn(this@apply)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addJar(configuration: Configuration, jarArtifact: PublishArtifact) {
|
||||||
|
val publications = configuration.outgoing
|
||||||
|
|
||||||
|
// Configure an implicit variant
|
||||||
|
publications.artifacts.add(jarArtifact)
|
||||||
|
publications.attributes.attribute(ArtifactAttributes.ARTIFACT_FORMAT, ArtifactTypeDefinition.JAR_TYPE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
open class KotlinNativeTargetConfigurator(
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : AbstractKotlinTargetConfigurator<KotlinNativeTarget>(
|
||||||
|
createDefaultSourceSets = true,
|
||||||
|
createTestCompilation = true
|
||||||
|
) {
|
||||||
|
private fun Project.klibOutputDirectory(
|
||||||
|
compilation: KotlinNativeCompilation
|
||||||
|
): File {
|
||||||
|
val targetSubDirectory = compilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty()
|
||||||
|
return buildDir.resolve("classes/kotlin/$targetSubDirectory${compilation.name}")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun AbstractKotlinNativeCompile.addCompilerPlugins() {
|
||||||
|
SubpluginEnvironment
|
||||||
|
.loadSubplugins(project, kotlinPluginVersion)
|
||||||
|
.addSubpluginOptions(project, this, compilerPluginOptions)
|
||||||
|
compilerPluginClasspath = project.configurations.getByName(NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
|
// region Artifact creation.
|
||||||
|
private fun Project.createKlibArtifact(
|
||||||
|
compilation: KotlinNativeCompilation,
|
||||||
|
artifactFile: File,
|
||||||
|
classifier: String?,
|
||||||
|
producingTask: Task,
|
||||||
|
copy: Boolean = false
|
||||||
|
) {
|
||||||
|
if (!compilation.target.konanTarget.enabledOnCurrentHost) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val apiElements = configurations.getByName(compilation.target.apiElementsConfigurationName)
|
||||||
|
|
||||||
|
val realProducingTask: Task
|
||||||
|
// TODO: Someone remove this HACK PLEASE!
|
||||||
|
val realArtifactFile = if (copy) {
|
||||||
|
realProducingTask = project.tasks.create("copy${producingTask.name.capitalize()}", Copy::class.java) {
|
||||||
|
val targetSubDirectory = compilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty()
|
||||||
|
it.destinationDir = project.buildDir.resolve("libs/$targetSubDirectory${compilation.name}")
|
||||||
|
it.from(artifactFile)
|
||||||
|
it.dependsOn(producingTask)
|
||||||
|
}
|
||||||
|
realProducingTask.destinationDir.resolve(artifactFile.name)
|
||||||
|
} else {
|
||||||
|
realProducingTask = producingTask
|
||||||
|
artifactFile
|
||||||
|
}
|
||||||
|
|
||||||
|
val klibArtifact = DefaultPublishArtifact(
|
||||||
|
compilation.name,
|
||||||
|
"klib",
|
||||||
|
"klib",
|
||||||
|
classifier,
|
||||||
|
Date(),
|
||||||
|
realArtifactFile,
|
||||||
|
realProducingTask
|
||||||
|
)
|
||||||
|
project.extensions.getByType(DefaultArtifactPublicationSet::class.java).addCandidate(klibArtifact)
|
||||||
|
|
||||||
|
with(apiElements.outgoing) {
|
||||||
|
artifacts.add(klibArtifact)
|
||||||
|
attributes.attribute(ArtifactAttributes.ARTIFACT_FORMAT, NativeArtifactFormat.KLIB)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Project.createRegularKlibArtifact(
|
||||||
|
compilation: KotlinNativeCompilation,
|
||||||
|
compileTask: KotlinNativeCompile
|
||||||
|
) = createKlibArtifact(compilation, compileTask.outputFile.get(), null, compileTask)
|
||||||
|
|
||||||
|
private fun Project.createCInteropKlibArtifact(
|
||||||
|
interop: DefaultCInteropSettings,
|
||||||
|
interopTask: CInteropProcess
|
||||||
|
) = createKlibArtifact(interop.compilation, interopTask.outputFile, "cinterop-${interop.name}", interopTask, copy = true)
|
||||||
|
// endregion.
|
||||||
|
|
||||||
|
// region Task creation.
|
||||||
|
private fun Project.createLinkTask(binary: NativeBinary) {
|
||||||
|
tasks.create(
|
||||||
|
binary.linkTaskName,
|
||||||
|
KotlinNativeLink::class.java
|
||||||
|
).apply {
|
||||||
|
val target = binary.target
|
||||||
|
this.binary = binary
|
||||||
|
group = BasePlugin.BUILD_GROUP
|
||||||
|
description = "Links ${binary.outputKind.description} '${binary.name}' for a target '${target.name}'."
|
||||||
|
enabled = target.konanTarget.enabledOnCurrentHost
|
||||||
|
destinationDir = binary.outputDirectory
|
||||||
|
addCompilerPlugins()
|
||||||
|
|
||||||
|
tasks.maybeCreate(target.artifactsTaskName).dependsOn(this)
|
||||||
|
tasks.maybeCreate(LifecycleBasePlugin.ASSEMBLE_TASK_NAME).dependsOn(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Project.createRunTask(binary: Executable) {
|
||||||
|
val taskName = binary.runTaskName ?: return
|
||||||
|
// TODO provide a special exec task for tests.
|
||||||
|
tasks.create(taskName, Exec::class.java).apply {
|
||||||
|
if (binary.isDefaultTestExecutable) {
|
||||||
|
group = LifecycleBasePlugin.VERIFICATION_GROUP
|
||||||
|
description = "Executes Kotlin/Native unit tests for target ${binary.target.name}."
|
||||||
|
tasks.maybeCreate(LifecycleBasePlugin.CHECK_TASK_NAME).dependsOn(this)
|
||||||
|
if (project.hasProperty("teamcity.version")) {
|
||||||
|
args("--ktest_logger=TEAMCITY")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
group = RUN_GROUP
|
||||||
|
description = "Executes Kotlin/Native executable ${binary.name} for target ${binary.target.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
enabled = binary.target.konanTarget.isCurrentHost
|
||||||
|
|
||||||
|
executable = binary.outputFile.absolutePath
|
||||||
|
workingDir = project.projectDir
|
||||||
|
|
||||||
|
onlyIf { binary.outputFile.exists() }
|
||||||
|
dependsOn(binary.linkTaskName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Project.createKlibCompilationTask(compilation: KotlinNativeCompilation) {
|
||||||
|
val compileTask = tasks.create(
|
||||||
|
compilation.compileKotlinTaskName,
|
||||||
|
KotlinNativeCompile::class.java
|
||||||
|
).apply {
|
||||||
|
this.compilation = compilation
|
||||||
|
group = BasePlugin.BUILD_GROUP
|
||||||
|
description = "Compiles a klibrary from the '${compilation.name}' " +
|
||||||
|
"compilation for target '${compilation.platformType.name}'."
|
||||||
|
enabled = compilation.target.konanTarget.enabledOnCurrentHost
|
||||||
|
|
||||||
|
destinationDir = klibOutputDirectory(compilation)
|
||||||
|
addCompilerPlugins()
|
||||||
|
compilation.output.addClassesDir {
|
||||||
|
project.files(this.outputFile).builtBy(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
project.tasks.getByName(compilation.compileAllTaskName).dependsOn(compileTask)
|
||||||
|
|
||||||
|
if (compilation.compilationName == KotlinCompilation.MAIN_COMPILATION_NAME) {
|
||||||
|
project.tasks.getByName(compilation.target.artifactsTaskName).apply {
|
||||||
|
dependsOn(compileTask)
|
||||||
|
}
|
||||||
|
project.tasks.getByName(LifecycleBasePlugin.ASSEMBLE_TASK_NAME).apply {
|
||||||
|
dependsOn(compileTask)
|
||||||
|
}
|
||||||
|
createRegularKlibArtifact(compilation, compileTask)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Project.createCInteropTasks(compilation: KotlinNativeCompilation) {
|
||||||
|
compilation.cinterops.all { interop ->
|
||||||
|
val interopTask = tasks.create(interop.interopProcessingTaskName, CInteropProcess::class.java).apply {
|
||||||
|
settings = interop
|
||||||
|
destinationDir = provider { klibOutputDirectory(compilation) }
|
||||||
|
group = INTEROP_GROUP
|
||||||
|
description = "Generates Kotlin/Native interop library '${interop.name}' " +
|
||||||
|
"for compilation '${compilation.name}'" +
|
||||||
|
"of target '${konanTarget.name}'."
|
||||||
|
enabled = compilation.target.konanTarget.enabledOnCurrentHost
|
||||||
|
|
||||||
|
val interopOutput = project.files(outputFileProvider).builtBy(this)
|
||||||
|
with(compilation) {
|
||||||
|
project.dependencies.add(compileDependencyConfigurationName, interopOutput)
|
||||||
|
if (isMainCompilation) {
|
||||||
|
target.compilations.findByName(TEST_COMPILATION_NAME)?.let {
|
||||||
|
project.dependencies.add(it.compileDependencyConfigurationName, interopOutput)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
project.dependencies.add(target.apiElementsConfigurationName, interopOutput)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
createCInteropKlibArtifact(interop, interopTask)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// endregion.
|
||||||
|
|
||||||
|
// region Configuration.
|
||||||
|
override fun configureTarget(target: KotlinNativeTarget) {
|
||||||
|
super.configureTarget(target)
|
||||||
|
configureBinaries(target)
|
||||||
|
configureFrameworkExport(target)
|
||||||
|
configureCInterops(target)
|
||||||
|
warnAboutIncorrectDependencies(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun configureArchivesAndComponent(target: KotlinNativeTarget): Unit = with(target.project) {
|
||||||
|
tasks.create(target.artifactsTaskName)
|
||||||
|
target.compilations.all {
|
||||||
|
createKlibCompilationTask(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
with(configurations.getByName(target.apiElementsConfigurationName)) {
|
||||||
|
outgoing.attributes.attribute(ArtifactAttributes.ARTIFACT_FORMAT, NativeArtifactFormat.KLIB)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun configureTest(target: KotlinNativeTarget) {
|
||||||
|
target.binaries.defaultTestExecutable {
|
||||||
|
compilation = target.compilations.maybeCreate(KotlinCompilation.TEST_COMPILATION_NAME)
|
||||||
|
// Allow accessing the test binary using the old getters (e.g. compilations.test.getBinary('EXECUTABLE', 'DEBUG'))
|
||||||
|
compilation.binaries[NativeOutputKind.EXECUTABLE to KotlinNativeBinaryContainer.DEFAULT_TEST_BUILD_TYPE] = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun configureCInterops(target: KotlinNativeTarget): Unit = with(target.project) {
|
||||||
|
target.compilations.all { compilation ->
|
||||||
|
createCInteropTasks(compilation)
|
||||||
|
compilation.cinterops.all {
|
||||||
|
defineConfigurationsForCInterop(compilation, it, target, configurations)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createTestCompilation) {
|
||||||
|
val mainCompilation = target.compilations.getByName(MAIN_COMPILATION_NAME)
|
||||||
|
target.compilations.findByName(TEST_COMPILATION_NAME)?.apply {
|
||||||
|
cinterops.all {
|
||||||
|
it.dependencyFiles += mainCompilation.output.allOutputs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun configureBinaries(target: KotlinNativeTarget) {
|
||||||
|
val project = target.project
|
||||||
|
// Create link and run tasks.
|
||||||
|
target.binaries.all {
|
||||||
|
project.createLinkTask(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
target.binaries.withType(Executable::class.java).all {
|
||||||
|
project.createRunTask(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
target.binaries.prefixGroups.all { prefixGroup ->
|
||||||
|
val linkGroupTask = project.tasks.maybeCreate(prefixGroup.linkTaskName)
|
||||||
|
prefixGroup.binaries.all {
|
||||||
|
linkGroupTask.dependsOn(it.linkTaskName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an aggregate link task for each compilation.
|
||||||
|
target.compilations.all {
|
||||||
|
project.tasks.create(it.binariesTaskName)
|
||||||
|
}
|
||||||
|
|
||||||
|
project.whenEvaluated {
|
||||||
|
target.binaries.forEach {
|
||||||
|
project.tasks.getByName(it.compilation.binariesTaskName).dependsOn(it.linkTaskName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create binaries for output kinds declared using the old DSL.
|
||||||
|
project.whenEvaluated {
|
||||||
|
target.compilations.all { compilation ->
|
||||||
|
val binaries = target.binaries
|
||||||
|
val konanTarget = compilation.target.konanTarget
|
||||||
|
val name = compilation.name
|
||||||
|
val buildTypes = compilation.buildTypes
|
||||||
|
val availableOutputKinds = compilation.outputKinds.filter { it.availableFor(konanTarget) }
|
||||||
|
|
||||||
|
val configure: NativeBinary.() -> Unit = {
|
||||||
|
this.compilation = compilation
|
||||||
|
linkerOpts.addAll(compilation.linkerOpts)
|
||||||
|
if (this is Executable) {
|
||||||
|
entryPoint = compilation.entryPoint
|
||||||
|
}
|
||||||
|
compilation.binaries[outputKind to buildType] = this
|
||||||
|
}
|
||||||
|
|
||||||
|
for (kind in availableOutputKinds) {
|
||||||
|
when (kind) {
|
||||||
|
NativeOutputKind.EXECUTABLE -> binaries.executable(name, buildTypes, configure)
|
||||||
|
NativeOutputKind.DYNAMIC -> binaries.sharedLib(name, buildTypes, configure)
|
||||||
|
NativeOutputKind.STATIC -> binaries.staticLib(name, buildTypes, configure)
|
||||||
|
NativeOutputKind.FRAMEWORK -> binaries.framework(name, buildTypes, configure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Allow setting linker options for the default test executable using the
|
||||||
|
// corresponding properties of the test compilation.
|
||||||
|
target.binaries.getDefaultTestExecutable().apply {
|
||||||
|
linkerOpts.addAll(target.compilations.getByName(TEST_COMPILATION_NAME).linkerOpts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun configureFrameworkExport(target: KotlinNativeTarget) {
|
||||||
|
val project = target.project
|
||||||
|
|
||||||
|
target.compilations.all {
|
||||||
|
// Allow resolving api configurations directly to be able to check that
|
||||||
|
// all exported dependency are also added in the corresponding api configurations.
|
||||||
|
// The check is performed during a link task execution.
|
||||||
|
project.configurations.maybeCreate(it.apiConfigurationName).apply {
|
||||||
|
isCanBeResolved = true
|
||||||
|
usesPlatformOf(target)
|
||||||
|
attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.consumerApiUsage(target))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
target.binaries.withType(Framework::class.java).all { framework ->
|
||||||
|
val exportConfiguration = project.configurations.maybeCreate(framework.exportConfigurationName).apply {
|
||||||
|
isVisible = false
|
||||||
|
isTransitive = false
|
||||||
|
isCanBeConsumed = false
|
||||||
|
isCanBeResolved = true
|
||||||
|
usesPlatformOf(target)
|
||||||
|
attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.consumerApiUsage(target))
|
||||||
|
description = "Dependenceis to be exported in framework ${framework.name} for target ${target.targetName}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun defineConfigurationsForTarget(target: KotlinNativeTarget) {
|
||||||
|
super.defineConfigurationsForTarget(target)
|
||||||
|
val configurations = target.project.configurations
|
||||||
|
|
||||||
|
// The configuration and the main compilation are created by the base class.
|
||||||
|
val mainCompilation = target.compilations.getByName(MAIN_COMPILATION_NAME)
|
||||||
|
configurations.getByName(target.apiElementsConfigurationName).apply {
|
||||||
|
// K/N compiler doesn't divide libraries into implementation and api ones. So we need to add implementation
|
||||||
|
// dependencies into the outgoing configuration.
|
||||||
|
extendsFrom(configurations.getByName(mainCompilation.implementationConfigurationName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun warnAboutIncorrectDependencies(target: KotlinNativeTarget) = target.project.whenEvaluated {
|
||||||
|
|
||||||
|
val compileOnlyDependencies = target.compilations.mapNotNull {
|
||||||
|
val dependencies = configurations.getByName(it.compileOnlyConfigurationName).allDependencies
|
||||||
|
if (dependencies.isNotEmpty()) {
|
||||||
|
it to dependencies
|
||||||
|
} else null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Dependency.stringCoordinates(): String = buildString {
|
||||||
|
group?.let { append(it).append(':') }
|
||||||
|
append(name)
|
||||||
|
version?.let { append(':').append(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compileOnlyDependencies.isNotEmpty()) {
|
||||||
|
with(target.project.logger) {
|
||||||
|
warn("A compileOnly dependency is used in the Kotlin/Native target '${target.name}':")
|
||||||
|
compileOnlyDependencies.forEach {
|
||||||
|
warn(
|
||||||
|
"""
|
||||||
|
Compilation: ${it.first.name}
|
||||||
|
|
||||||
|
Dependencies:
|
||||||
|
${it.second.joinToString(separator = "\n") { it.stringCoordinates() }}
|
||||||
|
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
warn("Such dependencies are not applicable for Kotlin/Native, consider changing the dependency type to 'implementation' or 'api'.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// endregion.
|
||||||
|
|
||||||
|
object NativeArtifactFormat {
|
||||||
|
const val KLIB = "org.jetbrains.kotlin.klib"
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val INTEROP_GROUP = "interop"
|
||||||
|
const val RUN_GROUP = "run"
|
||||||
|
|
||||||
|
protected fun defineConfigurationsForCInterop(
|
||||||
|
compilation: KotlinNativeCompilation,
|
||||||
|
cinterop: CInteropSettings,
|
||||||
|
target: KotlinTarget,
|
||||||
|
configurations: ConfigurationContainer
|
||||||
|
) {
|
||||||
|
val compileOnlyConfiguration = configurations.getByName(compilation.compileOnlyConfigurationName)
|
||||||
|
val implementationConfiguration = configurations.getByName(compilation.implementationConfigurationName)
|
||||||
|
|
||||||
|
cinterop.dependencyFiles = configurations.maybeCreate(cinterop.dependencyConfigurationName).apply {
|
||||||
|
extendsFrom(compileOnlyConfiguration, implementationConfiguration)
|
||||||
|
usesPlatformOf(target)
|
||||||
|
isVisible = false
|
||||||
|
isCanBeConsumed = false
|
||||||
|
attributes.attribute(USAGE_ATTRIBUTE, KotlinUsages.consumerApiUsage(target))
|
||||||
|
description = "Dependencies for cinterop '${cinterop.name}' (compilation '${compilation.name}')."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun Project.usageByName(usageName: String): Usage =
|
||||||
|
project.objects.named(Usage::class.java, usageName)
|
||||||
|
|
||||||
|
fun Configuration.usesPlatformOf(target: KotlinTarget): Configuration {
|
||||||
|
attributes.attribute(KotlinPlatformType.attribute, target.platformType)
|
||||||
|
// TODO: Provide an universal way to copy attributes from the target.
|
||||||
|
if (target is KotlinNativeTarget) {
|
||||||
|
attributes.attribute(KotlinNativeTarget.konanTargetAttribute, target.konanTarget.name)
|
||||||
|
}
|
||||||
|
return this
|
||||||
|
}
|
||||||
+437
@@ -0,0 +1,437 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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 groovy.lang.Closure
|
||||||
|
import org.gradle.api.*
|
||||||
|
import org.gradle.api.artifacts.ConfigurablePublishArtifact
|
||||||
|
import org.gradle.api.artifacts.Dependency
|
||||||
|
import org.gradle.api.artifacts.PublishArtifact
|
||||||
|
import org.gradle.api.attributes.Attribute
|
||||||
|
import org.gradle.api.attributes.AttributeContainer
|
||||||
|
import org.gradle.api.attributes.Usage.JAVA_API
|
||||||
|
import org.gradle.api.attributes.Usage.JAVA_RUNTIME_JARS
|
||||||
|
import org.gradle.api.plugins.JavaPlugin
|
||||||
|
import org.gradle.api.publish.maven.MavenPublication
|
||||||
|
import org.gradle.util.ConfigureUtil
|
||||||
|
import org.gradle.util.WrapUtil
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeBinaryContainer
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
|
||||||
|
abstract class AbstractKotlinTarget(
|
||||||
|
final override val project: Project
|
||||||
|
) : KotlinTarget {
|
||||||
|
private val attributeContainer = HierarchyAttributeContainer(parent = null)
|
||||||
|
|
||||||
|
override fun getAttributes(): AttributeContainer = attributeContainer
|
||||||
|
|
||||||
|
override val defaultConfigurationName: String
|
||||||
|
get() = disambiguateName("default")
|
||||||
|
|
||||||
|
override val apiElementsConfigurationName: String
|
||||||
|
get() = disambiguateName("apiElements")
|
||||||
|
|
||||||
|
override val runtimeElementsConfigurationName: String
|
||||||
|
get() = disambiguateName("runtimeElements")
|
||||||
|
|
||||||
|
override val artifactsTaskName: String
|
||||||
|
get() = disambiguateName("jar")
|
||||||
|
|
||||||
|
override fun toString(): String = "target $name ($platformType)"
|
||||||
|
|
||||||
|
override val publishable: Boolean
|
||||||
|
get() = true
|
||||||
|
|
||||||
|
override val components: Set<KotlinTargetComponent> by lazy {
|
||||||
|
val mainCompilation = compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
val usageContexts = createUsageContexts(mainCompilation)
|
||||||
|
setOf(
|
||||||
|
if (isGradleVersionAtLeast(4, 7)) {
|
||||||
|
val componentName = mainCompilation.target.name
|
||||||
|
createKotlinVariant(componentName, mainCompilation, usageContexts).apply {
|
||||||
|
sourcesArtifacts = setOf(
|
||||||
|
sourcesJarArtifact(
|
||||||
|
mainCompilation, componentName,
|
||||||
|
dashSeparatedName(target.name.toLowerCase(), componentName.toLowerCase())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
KotlinVariant(mainCompilation, usageContexts)
|
||||||
|
}
|
||||||
|
).also { project.components.addAll(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun createKotlinVariant(
|
||||||
|
componentName: String,
|
||||||
|
compilation: KotlinCompilation<*>,
|
||||||
|
usageContexts: Set<DefaultKotlinUsageContext>
|
||||||
|
): KotlinVariant {
|
||||||
|
|
||||||
|
val kotlinExtension = project.kotlinExtension as? KotlinMultiplatformExtension
|
||||||
|
?: return KotlinVariantWithCoordinates(compilation, usageContexts)
|
||||||
|
|
||||||
|
if (targetName == KotlinMultiplatformPlugin.METADATA_TARGET_NAME)
|
||||||
|
return KotlinVariantWithCoordinates(compilation, usageContexts)
|
||||||
|
|
||||||
|
val separateMetadataTarget = kotlinExtension.targets.getByName(KotlinMultiplatformPlugin.METADATA_TARGET_NAME)
|
||||||
|
|
||||||
|
val result = if (kotlinExtension.isGradleMetadataAvailable) {
|
||||||
|
KotlinVariantWithMetadataVariant(compilation, usageContexts, separateMetadataTarget)
|
||||||
|
} else {
|
||||||
|
// we should only add the Kotlin metadata dependency if we publish no Gradle metadata related to Kotlin MPP;
|
||||||
|
// with metadata, such a dependency would get invalid, since a platform module should only depend on modules for that
|
||||||
|
// same platform, not Kotlin metadata modules
|
||||||
|
KotlinVariantWithMetadataDependency(compilation, usageContexts, separateMetadataTarget)
|
||||||
|
}
|
||||||
|
|
||||||
|
result.componentName = componentName
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createUsageContexts(
|
||||||
|
producingCompilation: KotlinCompilation<*>
|
||||||
|
): Set<DefaultKotlinUsageContext> {
|
||||||
|
// Here, `JAVA_API` and `JAVA_RUNTIME_JARS` are used intentionally as Gradle needs this for
|
||||||
|
// ordering of the usage contexts (prioritizing the dependencies) when merging them into the POM;
|
||||||
|
// These Java usages should not be replaced with the custom Kotlin usages.
|
||||||
|
return listOfNotNull(
|
||||||
|
JAVA_API to apiElementsConfigurationName,
|
||||||
|
(JAVA_RUNTIME_JARS to runtimeElementsConfigurationName).takeIf { producingCompilation is KotlinCompilationToRunnableFiles }
|
||||||
|
).mapTo(mutableSetOf()) { (usageName, dependenciesConfigurationName) ->
|
||||||
|
DefaultKotlinUsageContext(
|
||||||
|
producingCompilation,
|
||||||
|
project.usageByName(usageName),
|
||||||
|
dependenciesConfigurationName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun sourcesJarArtifact(
|
||||||
|
producingCompilation: KotlinCompilation<*>,
|
||||||
|
componentName: String,
|
||||||
|
artifactNameAppendix: String,
|
||||||
|
classifierPrefix: String? = null
|
||||||
|
): PublishArtifact {
|
||||||
|
val sourcesJarTask = sourcesJarTask(producingCompilation, componentName, artifactNameAppendix)
|
||||||
|
val sourceArtifactConfigurationName = producingCompilation.disambiguateName("sourceArtifacts")
|
||||||
|
return producingCompilation.target.project.run {
|
||||||
|
(configurations.findByName(sourceArtifactConfigurationName) ?: run {
|
||||||
|
val configuration = configurations.create(sourceArtifactConfigurationName) {
|
||||||
|
it.isCanBeResolved = false
|
||||||
|
it.isCanBeConsumed = false
|
||||||
|
}
|
||||||
|
artifacts.add(sourceArtifactConfigurationName, sourcesJarTask)
|
||||||
|
configuration
|
||||||
|
}).artifacts.single().apply {
|
||||||
|
this as ConfigurablePublishArtifact
|
||||||
|
classifier = dashSeparatedName(classifierPrefix, "sources")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
internal val publicationConfigureActions =
|
||||||
|
WrapUtil.toDomainObjectSet(Action::class.java) as DomainObjectSet<Action<MavenPublication>>
|
||||||
|
|
||||||
|
override fun mavenPublication(action: Action<MavenPublication>) {
|
||||||
|
publicationConfigureActions.add(action)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mavenPublication(action: Closure<Unit>) =
|
||||||
|
mavenPublication(ConfigureUtil.configureUsing(action))
|
||||||
|
|
||||||
|
override var preset: KotlinTargetPreset<out KotlinTarget>? = null
|
||||||
|
internal set
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KotlinTarget.disambiguateName(simpleName: String) =
|
||||||
|
lowerCamelCaseName(targetName, simpleName)
|
||||||
|
|
||||||
|
open class KotlinAndroidTarget(
|
||||||
|
override val targetName: String,
|
||||||
|
project: Project
|
||||||
|
) : AbstractKotlinTarget(project) {
|
||||||
|
|
||||||
|
override var disambiguationClassifier: String? = null
|
||||||
|
internal set
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.androidJvm
|
||||||
|
|
||||||
|
private val compilationFactory = KotlinJvmAndroidCompilationFactory(project, this)
|
||||||
|
|
||||||
|
override val compilations: NamedDomainObjectContainer<out KotlinJvmAndroidCompilation> =
|
||||||
|
project.container(compilationFactory.itemClass, compilationFactory)
|
||||||
|
|
||||||
|
/** Names of the Android library variants that should be published from the target's project within the default publications which are
|
||||||
|
* set up if the `maven-publish` Gradle plugin is applied.
|
||||||
|
*
|
||||||
|
* Item examples:
|
||||||
|
* * 'release' (in case no product flavors were defined)
|
||||||
|
* * 'fooRelease' (for the release build type of a flavor 'foo')
|
||||||
|
* * 'fooBarRelease' (for the release build type multi-dimensional flavors 'foo' and 'bar').
|
||||||
|
*
|
||||||
|
* If set to null, which can also be done with [publishAllLibraryVariants],
|
||||||
|
* all library variants will be published, but not test or application variants. */
|
||||||
|
var publishLibraryVariants: List<String>? = listOf()
|
||||||
|
// Workaround for Groovy GString items in a list:
|
||||||
|
set(value) { field = value?.map(Any::toString) }
|
||||||
|
|
||||||
|
/** Add Android library variant names to [publishLibraryVariants]. */
|
||||||
|
fun publishLibraryVariants(vararg names: String) {
|
||||||
|
publishLibraryVariants = publishLibraryVariants.orEmpty() + names
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set up all of the Android library variants to be published from this target's project within the default publications, which are
|
||||||
|
* set up if the `maven-publish` Gradle plugin is applied. This overrides the variants chosen with [publishLibraryVariants] */
|
||||||
|
fun publishAllLibraryVariants() {
|
||||||
|
publishLibraryVariants = null
|
||||||
|
}
|
||||||
|
|
||||||
|
/** If true, a publication will be created per merged product flavor, with the build types used as classifiers for the artifacts
|
||||||
|
* published within each publication. If set to false, each Android variant will have a separate publication. */
|
||||||
|
var publishLibraryVariantsGroupedByFlavor = false
|
||||||
|
|
||||||
|
private fun checkPublishLibraryVariantsExist() {
|
||||||
|
// Capture type parameter T
|
||||||
|
fun <T> AbstractAndroidProjectHandler<T>.getLibraryVariantNames() =
|
||||||
|
mutableSetOf<String>().apply {
|
||||||
|
forEachVariant(project) {
|
||||||
|
if (getLibraryOutputTask(it) != null)
|
||||||
|
add(getVariantName(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val variantNames =
|
||||||
|
KotlinAndroidPlugin.androidTargetHandler(project.getKotlinPluginVersion()!!, this)
|
||||||
|
.getLibraryVariantNames()
|
||||||
|
|
||||||
|
val missingVariants =
|
||||||
|
publishLibraryVariants?.minus(variantNames).orEmpty()
|
||||||
|
|
||||||
|
if (missingVariants.isNotEmpty())
|
||||||
|
throw InvalidUserDataException(
|
||||||
|
"Kotlin target '$targetName' tried to set up publishing for Android build variants that are not library variants " +
|
||||||
|
"or do not exist:\n" + missingVariants.joinToString("\n") { "* $it" } +
|
||||||
|
"\nCheck the 'publishLibraryVariants' property, it should point to existing Android library variants. Publishing " +
|
||||||
|
"of application and test variants is not supported."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val components by lazy {
|
||||||
|
checkPublishLibraryVariantsExist()
|
||||||
|
|
||||||
|
KotlinAndroidPlugin.androidTargetHandler(project.getKotlinPluginVersion()!!, this).doCreateComponents()
|
||||||
|
.also { project.components.addAll(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capture the type parameter T for `AbstractAndroidProjectHandler`
|
||||||
|
private fun <T> AbstractAndroidProjectHandler<T>.doCreateComponents(): Set<KotlinTargetComponent> {
|
||||||
|
if (!isGradleVersionAtLeast(4, 7))
|
||||||
|
return emptySet()
|
||||||
|
|
||||||
|
val publishableVariants = mutableListOf<T>()
|
||||||
|
.apply { forEachVariant(project) { add(it) } }
|
||||||
|
.toList() // Defensive copy against unlikely modification by the lambda that captures the list above in forEachVariant { }
|
||||||
|
.filter { getLibraryOutputTask(it) != null && publishLibraryVariants?.contains(getVariantName(it)) ?: true }
|
||||||
|
|
||||||
|
val publishableVariantGroups = publishableVariants.groupBy { variant ->
|
||||||
|
val flavorNames = getFlavorNames(variant)
|
||||||
|
if (publishLibraryVariantsGroupedByFlavor) {
|
||||||
|
// For each flavor, we group its variants (which differ only in the build type) in a single component in order to publish
|
||||||
|
// all of the build types of the flavor as a single module with the build type as the classifier of the artifacts
|
||||||
|
flavorNames
|
||||||
|
} else {
|
||||||
|
flavorNames + getBuildTypeName(variant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return publishableVariantGroups.map { (flavorGroupNameParts, androidVariants) ->
|
||||||
|
val nestedVariants = androidVariants.mapTo(mutableSetOf()) { androidVariant ->
|
||||||
|
val androidVariantName = getVariantName(androidVariant)
|
||||||
|
val compilation = compilations.getByName(androidVariantName)
|
||||||
|
|
||||||
|
val flavorNames = getFlavorNames(androidVariant)
|
||||||
|
val buildTypeName = getBuildTypeName(androidVariant)
|
||||||
|
|
||||||
|
val artifactClassifier = buildTypeName.takeIf { it != "release" && publishLibraryVariantsGroupedByFlavor }
|
||||||
|
|
||||||
|
val usageContexts = createAndroidUsageContexts(androidVariant, compilation, artifactClassifier)
|
||||||
|
createKotlinVariant(
|
||||||
|
lowerCamelCaseName(compilation.target.name, *flavorGroupNameParts.toTypedArray()),
|
||||||
|
compilation,
|
||||||
|
usageContexts
|
||||||
|
).apply {
|
||||||
|
sourcesArtifacts = setOf(
|
||||||
|
sourcesJarArtifact(
|
||||||
|
compilation, compilation.disambiguateName(""),
|
||||||
|
dashSeparatedName(
|
||||||
|
compilation.target.name.toLowerCase(),
|
||||||
|
*flavorNames.map { it.toLowerCase() }.toTypedArray(),
|
||||||
|
buildTypeName.takeIf { it != "release" }?.toLowerCase()
|
||||||
|
),
|
||||||
|
classifierPrefix = artifactClassifier
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!publishLibraryVariantsGroupedByFlavor) {
|
||||||
|
defaultArtifactIdSuffix =
|
||||||
|
dashSeparatedName(
|
||||||
|
(getFlavorNames(androidVariant) + getBuildTypeName(androidVariant).takeIf { it != "release" })
|
||||||
|
.map { it?.toLowerCase() }
|
||||||
|
).takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (publishLibraryVariantsGroupedByFlavor) {
|
||||||
|
JointAndroidKotlinTargetComponent(
|
||||||
|
this@KotlinAndroidTarget,
|
||||||
|
nestedVariants,
|
||||||
|
flavorGroupNameParts,
|
||||||
|
nestedVariants.flatMap { it.sourcesArtifacts }.toSet()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
nestedVariants.single()
|
||||||
|
} as KotlinTargetComponent
|
||||||
|
}.toSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> AbstractAndroidProjectHandler<T>.createAndroidUsageContexts(
|
||||||
|
variant: T,
|
||||||
|
compilation: KotlinCompilation<*>,
|
||||||
|
artifactClassifier: String?
|
||||||
|
): Set<DefaultKotlinUsageContext> {
|
||||||
|
val variantName = getVariantName(variant)
|
||||||
|
val outputTask = getLibraryOutputTask(variant) ?: return emptySet()
|
||||||
|
val artifact = run {
|
||||||
|
val archivesConfigurationName = lowerCamelCaseName(targetName, variantName, "archives")
|
||||||
|
project.configurations.maybeCreate(archivesConfigurationName).apply {
|
||||||
|
isCanBeConsumed = false
|
||||||
|
isCanBeResolved = false
|
||||||
|
}
|
||||||
|
project.artifacts.add(archivesConfigurationName, outputTask) { artifact ->
|
||||||
|
artifact.classifier = artifactClassifier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val apiElementsConfigurationName = lowerCamelCaseName(variantName, "apiElements")
|
||||||
|
val runtimeElementsConfigurationName = lowerCamelCaseName(variantName, "runtimeElements")
|
||||||
|
|
||||||
|
// Here, `JAVA_API` and `JAVA_RUNTIME_JARS` are used intentionally as Gradle needs this for
|
||||||
|
// ordering of the usage contexts (prioritizing the dependencies) when merging them into the POM;
|
||||||
|
// These Java usages should not be replaced with the custom Kotlin usages.
|
||||||
|
return listOf(
|
||||||
|
apiElementsConfigurationName to JAVA_API,
|
||||||
|
runtimeElementsConfigurationName to JAVA_RUNTIME_JARS
|
||||||
|
).mapTo(mutableSetOf()) { (dependencyConfigurationName, usageName) ->
|
||||||
|
DefaultKotlinUsageContext(
|
||||||
|
compilation,
|
||||||
|
project.usageByName(usageName),
|
||||||
|
dependencyConfigurationName,
|
||||||
|
overrideConfigurationArtifacts = setOf(artifact)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class KotlinWithJavaTarget<KotlinOptionsType : KotlinCommonOptions>(
|
||||||
|
project: Project,
|
||||||
|
override val platformType: KotlinPlatformType,
|
||||||
|
override val targetName: String
|
||||||
|
) : AbstractKotlinTarget(project) {
|
||||||
|
override var disambiguationClassifier: String? = null
|
||||||
|
internal set
|
||||||
|
|
||||||
|
override val defaultConfigurationName: String
|
||||||
|
get() = Dependency.DEFAULT_CONFIGURATION
|
||||||
|
|
||||||
|
override val apiElementsConfigurationName: String
|
||||||
|
get() = JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME
|
||||||
|
|
||||||
|
override val runtimeElementsConfigurationName: String
|
||||||
|
get() = JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME
|
||||||
|
|
||||||
|
override val artifactsTaskName: String
|
||||||
|
get() = JavaPlugin.JAR_TASK_NAME
|
||||||
|
|
||||||
|
override val compilations: NamedDomainObjectContainer<KotlinWithJavaCompilation<KotlinOptionsType>> =
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
project.container(
|
||||||
|
KotlinWithJavaCompilation::class.java as Class<KotlinWithJavaCompilation<KotlinOptionsType>>,
|
||||||
|
KotlinWithJavaCompilationFactory(project, this)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
open class KotlinOnlyTarget<T : KotlinCompilation<*>>(
|
||||||
|
project: Project,
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
) : AbstractKotlinTarget(project) {
|
||||||
|
|
||||||
|
override lateinit var compilations: NamedDomainObjectContainer<T>
|
||||||
|
internal set
|
||||||
|
|
||||||
|
override lateinit var targetName: String
|
||||||
|
internal set
|
||||||
|
|
||||||
|
override var disambiguationClassifier: String? = null
|
||||||
|
internal set
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeTarget(
|
||||||
|
project: Project,
|
||||||
|
val konanTarget: KonanTarget
|
||||||
|
) : KotlinOnlyTarget<KotlinNativeCompilation>(project, KotlinPlatformType.native) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
attributes.attribute(konanTargetAttribute, konanTarget.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
val binaries = if(isGradleVersionAtLeast(4, 2)) {
|
||||||
|
// Use newInstance to allow accessing binaries by their names in Groovy using the extension mechanism.
|
||||||
|
project.objects.newInstance(KotlinNativeBinaryContainer::class.java, this, WrapUtil.toDomainObjectSet(NativeBinary::class.java))
|
||||||
|
} else {
|
||||||
|
KotlinNativeBinaryContainer(this, WrapUtil.toDomainObjectSet(NativeBinary::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun binaries(configure: KotlinNativeBinaryContainer.() -> Unit) {
|
||||||
|
binaries.configure()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun binaries(configure: Closure<*>) {
|
||||||
|
ConfigureUtil.configure(configure, binaries)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val artifactsTaskName: String
|
||||||
|
get() = disambiguateName("binaries")
|
||||||
|
|
||||||
|
override val publishable: Boolean
|
||||||
|
get() = konanTarget.enabledOnCurrentHost
|
||||||
|
|
||||||
|
// User-visible constants
|
||||||
|
val DEBUG = NativeBuildType.DEBUG
|
||||||
|
val RELEASE = NativeBuildType.RELEASE
|
||||||
|
|
||||||
|
val EXECUTABLE = NativeOutputKind.EXECUTABLE
|
||||||
|
val FRAMEWORK = NativeOutputKind.FRAMEWORK
|
||||||
|
val DYNAMIC = NativeOutputKind.DYNAMIC
|
||||||
|
val STATIC = NativeOutputKind.STATIC
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val konanTargetAttribute = Attribute.of(
|
||||||
|
"org.jetbrains.kotlin.native.target",
|
||||||
|
String::class.java
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+330
@@ -0,0 +1,330 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.artifacts.Dependency
|
||||||
|
import org.gradle.api.internal.file.FileResolver
|
||||||
|
import org.gradle.api.plugins.JavaPlugin
|
||||||
|
import org.gradle.internal.reflect.Instantiator
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.KotlinNativeProjectProperty
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.hasProperty
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.konanHome
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinTask
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
|
||||||
|
import org.jetbrains.kotlin.konan.KonanVersion
|
||||||
|
import org.jetbrains.kotlin.konan.target.HostManager
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
abstract class KotlinOnlyTargetPreset<T : KotlinCompilation<*>>(
|
||||||
|
protected val project: Project,
|
||||||
|
private val instantiator: Instantiator,
|
||||||
|
private val fileResolver: FileResolver,
|
||||||
|
protected val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinOnlyTarget<T>> {
|
||||||
|
|
||||||
|
protected open fun createKotlinTargetConfigurator(): KotlinTargetConfigurator<T> =
|
||||||
|
KotlinTargetConfigurator(createDefaultSourceSets = true, createTestCompilation = true)
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinOnlyTarget<T> {
|
||||||
|
val result = KotlinOnlyTarget<T>(project, platformType).apply {
|
||||||
|
targetName = name
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinOnlyTargetPreset
|
||||||
|
|
||||||
|
val compilationFactory = createCompilationFactory(this)
|
||||||
|
compilations = project.container(compilationFactory.itemClass, compilationFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
createKotlinTargetConfigurator().configureTarget(result)
|
||||||
|
|
||||||
|
result.compilations.all { compilation ->
|
||||||
|
buildCompilationProcessor(compilation).run()
|
||||||
|
if (compilation.name == KotlinCompilation.MAIN_COMPILATION_NAME) {
|
||||||
|
sourcesJarTask(compilation, result.targetName, result.targetName.toLowerCase())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun createCompilationFactory(forTarget: KotlinOnlyTarget<T>): KotlinCompilationFactory<T>
|
||||||
|
protected abstract val platformType: KotlinPlatformType
|
||||||
|
internal abstract fun buildCompilationProcessor(compilation: T): KotlinSourceSetProcessor<*>
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinMetadataTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinCommonCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(
|
||||||
|
forTarget: KotlinOnlyTarget<KotlinCommonCompilation>
|
||||||
|
): KotlinCompilationFactory<KotlinCommonCompilation> =
|
||||||
|
KotlinCommonCompilationFactory(forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.common
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinCommonCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return KotlinCommonSourceSetProcessor(project, compilation, tasksProvider, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "metadata"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createKotlinTargetConfigurator(): KotlinTargetConfigurator<KotlinCommonCompilation> =
|
||||||
|
KotlinTargetConfigurator(createDefaultSourceSets = false, createTestCompilation = false)
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinOnlyTarget<KotlinCommonCompilation> =
|
||||||
|
super.createTarget(name).apply {
|
||||||
|
val mainCompilation = compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
val commonMainSourceSet = project.kotlinExtension.sourceSets.getByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
||||||
|
|
||||||
|
mainCompilation.source(commonMainSourceSet)
|
||||||
|
|
||||||
|
project.afterEvaluate {
|
||||||
|
// Since there's no default source set, apply language settings from commonMain:
|
||||||
|
val compileKotlinMetadata = project.tasks.getByName(mainCompilation.compileKotlinTaskName) as KotlinCompile<*>
|
||||||
|
applyLanguageSettingsToKotlinTask(commonMainSourceSet.languageSettings, compileKotlinMetadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinJvmCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinJvmCompilation>): KotlinCompilationFactory<KotlinJvmCompilation> =
|
||||||
|
KotlinJvmCompilationFactory(forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.jvm
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinJvmCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return Kotlin2JvmSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "jvm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinJsCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinJsCompilation>) =
|
||||||
|
KotlinJsCompilationFactory(project, forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.js
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinJsCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return Kotlin2JsSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinAndroidTargetPreset(
|
||||||
|
private val project: Project,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinAndroidTarget> {
|
||||||
|
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinAndroidTarget {
|
||||||
|
val result = KotlinAndroidTarget(name, project).apply {
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinAndroidTargetPreset
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinAndroidPlugin.applyToTarget(kotlinPluginVersion, result)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "android"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmWithJavaTargetPreset(
|
||||||
|
private val project: Project,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinWithJavaTarget<KotlinJvmOptions>> {
|
||||||
|
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinWithJavaTarget<KotlinJvmOptions> {
|
||||||
|
project.plugins.apply(JavaPlugin::class.java)
|
||||||
|
|
||||||
|
val target = KotlinWithJavaTarget<KotlinJvmOptions>(project, KotlinPlatformType.jvm, name).apply {
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinJvmWithJavaTargetPreset
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractKotlinPlugin.configureTarget(target) { compilation ->
|
||||||
|
Kotlin2JvmSourceSetProcessor(project, KotlinTasksProvider(name), compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
target.compilations.getByName("test").run {
|
||||||
|
val main = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
|
||||||
|
compileDependencyFiles = project.files(
|
||||||
|
main.output.allOutputs,
|
||||||
|
project.configurations.maybeCreate(compileDependencyConfigurationName)
|
||||||
|
)
|
||||||
|
runtimeDependencyFiles = project.files(
|
||||||
|
output.allOutputs,
|
||||||
|
main.output.allOutputs,
|
||||||
|
project.configurations.maybeCreate(runtimeDependencyConfigurationName)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "jvmWithJava"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeTargetPreset(
|
||||||
|
private val name: String,
|
||||||
|
val project: Project,
|
||||||
|
val konanTarget: KonanTarget,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinNativeTarget> {
|
||||||
|
|
||||||
|
init {
|
||||||
|
// This is required to obtain Kotlin/Native home in CLion plugin:
|
||||||
|
setupNativeHomePrivateProperty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName(): String = name
|
||||||
|
|
||||||
|
private fun setupNativeHomePrivateProperty() = with(project) {
|
||||||
|
if (!hasProperty(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY))
|
||||||
|
extensions.extraProperties.set(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY, konanHome)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupNativeCompiler() = with(project) {
|
||||||
|
if (!hasProperty(KotlinNativeProjectProperty.KONAN_HOME_OVERRIDE)) {
|
||||||
|
NativeCompilerDownloader(this).downloadIfNeeded()
|
||||||
|
logger.info("Kotlin/Native distribution: $konanHome")
|
||||||
|
} else {
|
||||||
|
logger.info("User-provided Kotlin/Native distribution: $konanHome")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We declare default K/N dependencies as files to avoid searching them in remote repos (see KT-28128).
|
||||||
|
private fun defaultLibs(target: KonanTarget? = null): List<Dependency> = with(project) {
|
||||||
|
|
||||||
|
val relPath = if (target != null) "platform/${target.name}" else "common"
|
||||||
|
|
||||||
|
file("$konanHome/klib/$relPath")
|
||||||
|
.listFiles { file -> file.isDirectory }
|
||||||
|
?.sortedBy { dir -> dir.name.toLowerCase() }
|
||||||
|
?.map { dir -> dependencies.create(files(dir)) } ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinNativeTarget {
|
||||||
|
setupNativeCompiler()
|
||||||
|
|
||||||
|
val result = KotlinNativeTarget(project, konanTarget).apply {
|
||||||
|
targetName = name
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinNativeTargetPreset
|
||||||
|
|
||||||
|
val compilationFactory = KotlinNativeCompilationFactory(project, this)
|
||||||
|
compilations = project.container(compilationFactory.itemClass, compilationFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinNativeTargetConfigurator(kotlinPluginVersion).configureTarget(result)
|
||||||
|
|
||||||
|
// Allow IDE to resolve the libraries provided by the compiler by adding them into dependencies.
|
||||||
|
result.compilations.all { compilation ->
|
||||||
|
val target = compilation.target.konanTarget
|
||||||
|
// First, put common libs:
|
||||||
|
defaultLibs().forEach {
|
||||||
|
project.dependencies.add(compilation.compileDependencyConfigurationName, it)
|
||||||
|
}
|
||||||
|
// Then, platform-specific libs:
|
||||||
|
defaultLibs(target).forEach {
|
||||||
|
project.dependencies.add(compilation.compileDependencyConfigurationName, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!konanTarget.enabledOnCurrentHost) {
|
||||||
|
with(HostManager()) {
|
||||||
|
val supportedHosts = enabledTargetsByHost.filterValues { konanTarget in it }.keys
|
||||||
|
val supportedHostsString =
|
||||||
|
if (supportedHosts.size == 1)
|
||||||
|
"a ${supportedHosts.single()} host" else
|
||||||
|
"one of the host platforms: ${supportedHosts.joinToString(", ")}"
|
||||||
|
project.logger.warn(
|
||||||
|
"Target '$name' for platform ${konanTarget} is ignored during build on this ${HostManager.host} machine. " +
|
||||||
|
"You can build it with $supportedHostsString."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY = "konanHome"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val KonanTarget.isCurrentHost: Boolean
|
||||||
|
get() = this == HostManager.host
|
||||||
|
|
||||||
|
internal val KonanTarget.enabledOnCurrentHost
|
||||||
|
get() = HostManager().isEnabled(this)
|
||||||
|
|
||||||
|
internal val KotlinNativeCompilation.isMainCompilation: Boolean
|
||||||
|
get() = name == KotlinCompilation.MAIN_COMPILATION_NAME
|
||||||
+471
@@ -0,0 +1,471 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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 groovy.lang.Closure
|
||||||
|
import org.gradle.api.Action
|
||||||
|
import org.gradle.api.NamedDomainObjectContainer
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.attributes.AttributeContainer
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.file.SourceDirectorySet
|
||||||
|
import org.gradle.api.tasks.SourceSet
|
||||||
|
import org.gradle.util.ConfigureUtil
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.*
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.defaultSourceSetLanguageSettingsChecker
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.getSourceSetHierarchy
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.*
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
|
internal fun KotlinCompilation<*>.composeName(prefix: String? = null, suffix: String? = null): String {
|
||||||
|
val compilationNamePart = compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }
|
||||||
|
val targetNamePart = target.disambiguationClassifier
|
||||||
|
|
||||||
|
return lowerCamelCaseName(prefix, targetNamePart, compilationNamePart, suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val KotlinCompilation<*>.defaultSourceSetName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName)
|
||||||
|
|
||||||
|
abstract class AbstractKotlinCompilation<T : KotlinCommonOptions>(
|
||||||
|
target: KotlinTarget,
|
||||||
|
override val compilationName: String
|
||||||
|
) : KotlinCompilation<T>, HasKotlinDependencies {
|
||||||
|
|
||||||
|
override val kotlinOptions: T
|
||||||
|
get() = compileKotlinTask.kotlinOptions
|
||||||
|
|
||||||
|
override fun kotlinOptions(configure: T.() -> Unit) =
|
||||||
|
configure(kotlinOptions)
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override val compileKotlinTask: KotlinCompile<T>
|
||||||
|
get() = (target.project.tasks.getByName(compileKotlinTaskName) as KotlinCompile<T>)
|
||||||
|
|
||||||
|
// Don't declare this property in the constructor to avoid NPE
|
||||||
|
// when an overriding property of a subclass is accessed instead.
|
||||||
|
override val target: KotlinTarget = target
|
||||||
|
|
||||||
|
private val attributeContainer = HierarchyAttributeContainer(target.attributes)
|
||||||
|
|
||||||
|
override fun getAttributes(): AttributeContainer = attributeContainer
|
||||||
|
|
||||||
|
override val kotlinSourceSets: MutableSet<KotlinSourceSet> = mutableSetOf()
|
||||||
|
|
||||||
|
override val allKotlinSourceSets: Set<KotlinSourceSet>
|
||||||
|
get() = kotlinSourceSets.flatMapTo(mutableSetOf()) { it.getSourceSetHierarchy() }
|
||||||
|
|
||||||
|
override val defaultSourceSet: KotlinSourceSet
|
||||||
|
get() = target.project.kotlinExtension.sourceSets.getByName(defaultSourceSetName)
|
||||||
|
|
||||||
|
override fun defaultSourceSet(configure: KotlinSourceSet.() -> Unit) =
|
||||||
|
configure(defaultSourceSet)
|
||||||
|
|
||||||
|
override val output: KotlinCompilationOutput by lazy {
|
||||||
|
DefaultKotlinCompilationOutput(
|
||||||
|
target.project,
|
||||||
|
Callable { target.project.buildDir.resolve("processedResources/${target.targetName}/$name") })
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun addSourcesToCompileTask(sourceSet: KotlinSourceSet, addAsCommonSources: Boolean) {
|
||||||
|
fun AbstractKotlinCompile<*>.configureAction() {
|
||||||
|
source(sourceSet.kotlin)
|
||||||
|
sourceFilesExtensions(sourceSet.customSourceFilesExtensions)
|
||||||
|
if (addAsCommonSources) {
|
||||||
|
commonSourceSet += sourceSet.kotlin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note! Invocation of withType-all results in preliminary task instantiation.
|
||||||
|
// After fix of this issue the following code should be uncommented:
|
||||||
|
// if (useLazyTaskConfiguration) {
|
||||||
|
// (target.project.tasks.named(compileKotlinTaskName) as TaskProvider<AbstractKotlinCompile<*>>).configure {
|
||||||
|
// it.configureAction()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
target.project.tasks
|
||||||
|
// To configure a task that may have not yet been created at this point, use 'withType-matching-all`:
|
||||||
|
.withType(AbstractKotlinCompile::class.java)
|
||||||
|
.matching { it.name == compileKotlinTaskName }
|
||||||
|
.all { compileKotlinTask ->
|
||||||
|
compileKotlinTask.configureAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun source(sourceSet: KotlinSourceSet) {
|
||||||
|
if (kotlinSourceSets.add(sourceSet)) {
|
||||||
|
//TODO possibly issue with forced instantiation
|
||||||
|
target.project.whenEvaluated {
|
||||||
|
sourceSet.getSourceSetHierarchy().forEach { sourceSet ->
|
||||||
|
val isCommonSource =
|
||||||
|
CompilationSourceSetUtil.sourceSetsInMultipleCompilations(project)?.contains(sourceSet) ?: false
|
||||||
|
|
||||||
|
addSourcesToCompileTask(sourceSet, addAsCommonSources = isCommonSource)
|
||||||
|
|
||||||
|
// Use `forced = false` since `api`, `implementation`, and `compileOnly` may be missing in some cases like
|
||||||
|
// old Java & Android projects:
|
||||||
|
addExtendsFromRelation(apiConfigurationName, sourceSet.apiConfigurationName, forced = false)
|
||||||
|
addExtendsFromRelation(implementationConfigurationName, sourceSet.implementationConfigurationName, forced = false)
|
||||||
|
addExtendsFromRelation(compileOnlyConfigurationName, sourceSet.compileOnlyConfigurationName, forced = false)
|
||||||
|
|
||||||
|
if (this@AbstractKotlinCompilation is KotlinCompilationToRunnableFiles<*>) {
|
||||||
|
addExtendsFromRelation(runtimeOnlyConfigurationName, sourceSet.runtimeOnlyConfigurationName, forced = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceSet.name != defaultSourceSetName) {
|
||||||
|
kotlinExtension.sourceSets.findByName(defaultSourceSetName)?.let { defaultSourceSet ->
|
||||||
|
// Temporary solution for checking consistency across source sets participating in a compilation that may
|
||||||
|
// not be interconnected with the dependsOn relation: check the settings as if the default source set of
|
||||||
|
// the compilation depends on the one added to the compilation:
|
||||||
|
defaultSourceSetLanguageSettingsChecker.runAllChecks(
|
||||||
|
defaultSourceSet,
|
||||||
|
sourceSet
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }.orEmpty(),
|
||||||
|
"compileClasspath"
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileKotlinTaskName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
"compile",
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
"Kotlin",
|
||||||
|
target.targetName
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "classes")
|
||||||
|
|
||||||
|
override lateinit var compileDependencyFiles: FileCollection
|
||||||
|
|
||||||
|
override val apiConfigurationName: String
|
||||||
|
get() = disambiguateName("api")
|
||||||
|
|
||||||
|
override val implementationConfigurationName: String
|
||||||
|
get() = disambiguateName("implementation")
|
||||||
|
|
||||||
|
override val compileOnlyConfigurationName: String
|
||||||
|
get() = disambiguateName("compileOnly")
|
||||||
|
|
||||||
|
override val runtimeOnlyConfigurationName: String
|
||||||
|
get() = disambiguateName("runtimeOnly")
|
||||||
|
|
||||||
|
override fun dependencies(configure: KotlinDependencyHandler.() -> Unit): Unit =
|
||||||
|
DefaultKotlinDependencyHandler(this, target.project).run(configure)
|
||||||
|
|
||||||
|
override fun dependencies(configureClosure: Closure<Any?>) =
|
||||||
|
dependencies f@{ ConfigureUtil.configure(configureClosure, this@f) }
|
||||||
|
|
||||||
|
override fun toString(): String = "compilation '$compilationName' ($target)"
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AbstractKotlinCompilationToRunnableFiles<T : KotlinCommonOptions>(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<T>(target, name), KotlinCompilationToRunnableFiles<T> {
|
||||||
|
override val runtimeDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
"runtimeClasspath"
|
||||||
|
)
|
||||||
|
|
||||||
|
override lateinit var runtimeDependencyFiles: FileCollection
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KotlinCompilation<*>.disambiguateName(simpleName: String): String {
|
||||||
|
return lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
simpleName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
open class KotlinJvmCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJvmOptions>(target, name), KotlinCompilationWithResources<KotlinJvmOptions> {
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
override val compileKotlinTask: org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
get() = super.compileKotlinTask as org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinWithJavaCompilation<KotlinOptionsType : KotlinCommonOptions>(
|
||||||
|
target: KotlinWithJavaTarget<KotlinOptionsType>,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinOptionsType>(target, name), KotlinCompilationWithResources<KotlinOptionsType> {
|
||||||
|
lateinit var javaSourceSet: SourceSet
|
||||||
|
|
||||||
|
override val output: KotlinCompilationOutput by lazy { KotlinWithJavaCompilationOutput(this) }
|
||||||
|
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = javaSourceSet.processResourcesTaskName
|
||||||
|
|
||||||
|
override var runtimeDependencyFiles: FileCollection
|
||||||
|
get() = javaSourceSet.runtimeClasspath
|
||||||
|
set(value) {
|
||||||
|
javaSourceSet.runtimeClasspath = value
|
||||||
|
}
|
||||||
|
|
||||||
|
override val runtimeDependencyConfigurationName: String
|
||||||
|
get() = javaSourceSet.runtimeClasspathConfigurationName
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = javaSourceSet.compileClasspathConfigurationName
|
||||||
|
|
||||||
|
override val runtimeOnlyConfigurationName: String
|
||||||
|
get() = javaSourceSet.runtimeOnlyConfigurationName
|
||||||
|
|
||||||
|
override val implementationConfigurationName: String
|
||||||
|
get() = javaSourceSet.implementationConfigurationName
|
||||||
|
|
||||||
|
override val apiConfigurationName: String
|
||||||
|
get() = javaSourceSet.apiConfigurationName
|
||||||
|
|
||||||
|
override val compileOnlyConfigurationName: String
|
||||||
|
get() = javaSourceSet.compileOnlyConfigurationName
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = javaSourceSet.classesTaskName
|
||||||
|
|
||||||
|
override var compileDependencyFiles: FileCollection
|
||||||
|
get() = javaSourceSet.compileClasspath
|
||||||
|
set(value) {
|
||||||
|
javaSourceSet.compileClasspath = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun source(javaSourceSet: SourceSet) {
|
||||||
|
with(target.project) {
|
||||||
|
afterEvaluate {
|
||||||
|
(tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>).source(javaSourceSet.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmAndroidCompilation(
|
||||||
|
target: KotlinAndroidTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJvmOptions>(target, name) {
|
||||||
|
override val compileKotlinTask: org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
get() = super.compileKotlinTask as org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
override val relatedConfigurationNames: List<String>
|
||||||
|
get() = super.relatedConfigurationNames + listOf("${name}ApiElements", "${name}RuntimeElements")
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJsOptions>(target, name), KotlinCompilationWithResources<KotlinJsOptions> {
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
override val compileKotlinTask: Kotlin2JsCompile
|
||||||
|
get() = super.compileKotlinTask as Kotlin2JsCompile
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinCommonCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<KotlinMultiplatformCommonOptions>(target, name) {
|
||||||
|
override val compileKotlinTask: KotlinCompileCommon
|
||||||
|
get() = super.compileKotlinTask as KotlinCompileCommon
|
||||||
|
|
||||||
|
// TODO once we properly compile metadata for each source set, the default source sets will likely become just the source sets
|
||||||
|
// which are transformed to metadata
|
||||||
|
private val commonSourceSetName = when (compilationName) {
|
||||||
|
KotlinCompilation.MAIN_COMPILATION_NAME -> KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME
|
||||||
|
else -> error("Custom metadata compilations are not supported yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
override val defaultSourceSet: KotlinSourceSet
|
||||||
|
get() = target.project.kotlinExtension.sourceSets.getByName(commonSourceSetName)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeCompilation(
|
||||||
|
override val target: KotlinNativeTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<KotlinCommonOptions>(target, name), KotlinCompilationWithResources<KotlinCommonOptions> {
|
||||||
|
|
||||||
|
override val kotlinOptions: KotlinCommonOptions
|
||||||
|
get() = compileKotlinTask.kotlinOptions
|
||||||
|
|
||||||
|
override val compileKotlinTask: KotlinNativeCompile
|
||||||
|
get() = super.compileKotlinTask as KotlinNativeCompile
|
||||||
|
|
||||||
|
private val project: Project
|
||||||
|
get() = target.project
|
||||||
|
|
||||||
|
// A collection containing all source sets used by this compilation
|
||||||
|
// (taking into account dependencies between source sets). Used by both compilation
|
||||||
|
// and linking tasks. Unlike kotlinSourceSets, includes dependency source sets.
|
||||||
|
// TODO: Move into the compilation task when the linking task does klib linking instead of compilation.
|
||||||
|
internal val allSources: MutableSet<SourceDirectorySet> = mutableSetOf()
|
||||||
|
|
||||||
|
// TODO: Move into the compilation task when the linking task does klib linking instead of compilation.
|
||||||
|
internal val commonSources: MutableSet<SourceDirectorySet> = mutableSetOf()
|
||||||
|
|
||||||
|
var isTestCompilation = false
|
||||||
|
|
||||||
|
var friendCompilationName: String? = null
|
||||||
|
|
||||||
|
internal val friendCompilation: KotlinNativeCompilation?
|
||||||
|
get() = friendCompilationName?.let {
|
||||||
|
target.compilations.getByName(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used only to support the old APIs. TODO: Remove when the old APIs are removed.
|
||||||
|
internal val binaries = mutableMapOf<Pair<NativeOutputKind, NativeBuildType>, NativeBinary>()
|
||||||
|
|
||||||
|
// Native-specific DSL.
|
||||||
|
var extraOpts = mutableListOf<String>()
|
||||||
|
|
||||||
|
fun extraOpts(vararg values: Any) = extraOpts(values.toList())
|
||||||
|
fun extraOpts(values: List<Any>) {
|
||||||
|
extraOpts.addAll(values.map { it.toString() })
|
||||||
|
}
|
||||||
|
|
||||||
|
var buildTypes = mutableListOf<NativeBuildType>()
|
||||||
|
var outputKinds = mutableListOf<NativeOutputKind>()
|
||||||
|
|
||||||
|
fun outputKind(kind: NativeOutputKind) = outputKinds.add(kind)
|
||||||
|
|
||||||
|
fun outputKinds(vararg kinds: NativeOutputKind) {
|
||||||
|
outputKinds = kinds.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun outputKinds(vararg kinds: String) {
|
||||||
|
outputKinds = kinds.map { NativeOutputKind.valueOf(it.toUpperCase()) }.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun outputKinds(kinds: List<Any>) {
|
||||||
|
outputKinds = kinds.map {
|
||||||
|
when (it) {
|
||||||
|
is NativeOutputKind -> it
|
||||||
|
is String -> NativeOutputKind.valueOf(it.toUpperCase())
|
||||||
|
else -> error("Cannot use $it as an output kind")
|
||||||
|
}
|
||||||
|
}.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
var entryPoint: String? = null
|
||||||
|
fun entryPoint(value: String) {
|
||||||
|
entryPoint = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interop DSL.
|
||||||
|
val cinterops = project.container(DefaultCInteropSettings::class.java) { cinteropName ->
|
||||||
|
DefaultCInteropSettings(project, cinteropName, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
var linkerOpts = mutableListOf<String>()
|
||||||
|
|
||||||
|
fun cinterops(action: NamedDomainObjectContainer<DefaultCInteropSettings>.() -> Unit) = cinterops.action()
|
||||||
|
fun cinterops(action: Closure<Unit>) = cinterops(ConfigureUtil.configureUsing(action))
|
||||||
|
fun cinterops(action: Action<NamedDomainObjectContainer<DefaultCInteropSettings>>) = action.execute(cinterops)
|
||||||
|
|
||||||
|
fun linkerOpts(vararg values: String) = linkerOpts(values.toList())
|
||||||
|
fun linkerOpts(values: List<String>) {
|
||||||
|
linkerOpts.addAll(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Task accessors.
|
||||||
|
fun findLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeLink? = binaries[kind to buildType]?.linkTask
|
||||||
|
|
||||||
|
fun getLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeLink =
|
||||||
|
findLinkTask(kind, buildType)
|
||||||
|
?: throw IllegalArgumentException("Cannot find a link task for the binary kind '$kind' and the build type '$buildType'")
|
||||||
|
|
||||||
|
fun findLinkTask(kind: String, buildType: String) =
|
||||||
|
findLinkTask(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun getLinkTask(kind: String, buildType: String) =
|
||||||
|
getLinkTask(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun findBinary(kind: NativeOutputKind, buildType: NativeBuildType): File? = findLinkTask(kind, buildType)?.outputFile?.get()
|
||||||
|
|
||||||
|
fun getBinary(kind: NativeOutputKind, buildType: NativeBuildType): File = getLinkTask(kind, buildType).outputFile.get()
|
||||||
|
|
||||||
|
fun findBinary(kind: String, buildType: String) =
|
||||||
|
findBinary(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun getBinary(kind: String, buildType: String) =
|
||||||
|
getBinary(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
// Naming
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
fun linkTaskName(kind: NativeOutputKind, buildType: NativeBuildType): String =
|
||||||
|
lowerCamelCaseName(
|
||||||
|
"link",
|
||||||
|
KotlinNativeBinaryContainer.generateBinaryName(compilationName, buildType, kind.taskNameClassifier),
|
||||||
|
target.targetName
|
||||||
|
)
|
||||||
|
|
||||||
|
fun linkTaskName(kind: String, buildType: String) =
|
||||||
|
linkTaskName(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }.orEmpty(),
|
||||||
|
"compileKlibraries"
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "klibrary")
|
||||||
|
|
||||||
|
val binariesTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "binaries")
|
||||||
|
|
||||||
|
override fun addSourcesToCompileTask(sourceSet: KotlinSourceSet, addAsCommonSources: Boolean) {
|
||||||
|
allSources.add(sourceSet.kotlin)
|
||||||
|
if (addAsCommonSources) {
|
||||||
|
commonSources.add(sourceSet.kotlin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private object CompilationSourceSetUtil {
|
||||||
|
// Cache the results per project
|
||||||
|
private val projectSourceSetsInMultipleCompilationsCache = WeakHashMap<Project, Set<KotlinSourceSet>>()
|
||||||
|
|
||||||
|
fun sourceSetsInMultipleCompilations(project: Project) =
|
||||||
|
projectSourceSetsInMultipleCompilationsCache.computeIfAbsent(project) { _ ->
|
||||||
|
check(project.state.executed) { "Should only be computed after the project is evaluated" }
|
||||||
|
|
||||||
|
val compilations = (project.kotlinExtension as? KotlinMultiplatformExtension)?.targets?.flatMap { it.compilations }
|
||||||
|
?: return@computeIfAbsent null
|
||||||
|
|
||||||
|
compilations
|
||||||
|
.flatMap { compilation -> compilation.allKotlinSourceSets.map { sourceSet -> compilation to sourceSet } }
|
||||||
|
.groupingBy { (_, sourceSet) -> sourceSet }
|
||||||
|
.eachCount()
|
||||||
|
.filterValues { it > 1 }
|
||||||
|
.keys
|
||||||
|
}
|
||||||
|
}
|
||||||
+471
@@ -0,0 +1,471 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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 groovy.lang.Closure
|
||||||
|
import org.gradle.api.Action
|
||||||
|
import org.gradle.api.NamedDomainObjectContainer
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.attributes.AttributeContainer
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.file.SourceDirectorySet
|
||||||
|
import org.gradle.api.tasks.SourceSet
|
||||||
|
import org.gradle.util.ConfigureUtil
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.*
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.defaultSourceSetLanguageSettingsChecker
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.getSourceSetHierarchy
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.*
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
|
internal fun KotlinCompilation<*>.composeName(prefix: String? = null, suffix: String? = null): String {
|
||||||
|
val compilationNamePart = compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }
|
||||||
|
val targetNamePart = target.disambiguationClassifier
|
||||||
|
|
||||||
|
return lowerCamelCaseName(prefix, targetNamePart, compilationNamePart, suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val KotlinCompilation<*>.defaultSourceSetName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName)
|
||||||
|
|
||||||
|
abstract class AbstractKotlinCompilation<T : KotlinCommonOptions>(
|
||||||
|
target: KotlinTarget,
|
||||||
|
override val compilationName: String
|
||||||
|
) : KotlinCompilation<T>, HasKotlinDependencies {
|
||||||
|
|
||||||
|
override val kotlinOptions: T
|
||||||
|
get() = compileKotlinTask.kotlinOptions
|
||||||
|
|
||||||
|
override fun kotlinOptions(configure: T.() -> Unit) =
|
||||||
|
configure(kotlinOptions)
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override val compileKotlinTask: KotlinCompile<T>
|
||||||
|
get() = (target.project.tasks.getByName(compileKotlinTaskName) as KotlinCompile<T>)
|
||||||
|
|
||||||
|
// Don't declare this property in the constructor to avoid NPE
|
||||||
|
// when an overriding property of a subclass is accessed instead.
|
||||||
|
override val target: KotlinTarget = target
|
||||||
|
|
||||||
|
private val attributeContainer = HierarchyAttributeContainer(target.attributes)
|
||||||
|
|
||||||
|
override fun getAttributes(): AttributeContainer = attributeContainer
|
||||||
|
|
||||||
|
override val kotlinSourceSets: MutableSet<KotlinSourceSet> = mutableSetOf()
|
||||||
|
|
||||||
|
override val allKotlinSourceSets: Set<KotlinSourceSet>
|
||||||
|
get() = kotlinSourceSets.flatMapTo(mutableSetOf()) { it.getSourceSetHierarchy() }
|
||||||
|
|
||||||
|
override val defaultSourceSet: KotlinSourceSet
|
||||||
|
get() = target.project.kotlinExtension.sourceSets.getByName(defaultSourceSetName)
|
||||||
|
|
||||||
|
override fun defaultSourceSet(configure: KotlinSourceSet.() -> Unit) =
|
||||||
|
configure(defaultSourceSet)
|
||||||
|
|
||||||
|
override val output: KotlinCompilationOutput by lazy {
|
||||||
|
DefaultKotlinCompilationOutput(
|
||||||
|
target.project,
|
||||||
|
Callable { target.project.buildDir.resolve("processedResources/${target.targetName}/$name") })
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun addSourcesToCompileTask(sourceSet: KotlinSourceSet, addAsCommonSources: Boolean) {
|
||||||
|
fun AbstractKotlinCompile<*>.configureAction() {
|
||||||
|
source(sourceSet.kotlin)
|
||||||
|
sourceFilesExtensions(sourceSet.customSourceFilesExtensions)
|
||||||
|
if (addAsCommonSources) {
|
||||||
|
commonSourceSet += sourceSet.kotlin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note! Invocation of withType-all results in preliminary task instantiation.
|
||||||
|
// After fix of this issue the following code should be uncommented:
|
||||||
|
// if (useLazyTaskConfiguration) {
|
||||||
|
// (target.project.tasks.named(compileKotlinTaskName) as TaskProvider<AbstractKotlinCompile<*>>).configure {
|
||||||
|
// it.configureAction()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
target.project.tasks
|
||||||
|
// To configure a task that may have not yet been created at this point, use 'withType-matching-all`:
|
||||||
|
.withType(AbstractKotlinCompile::class.java)
|
||||||
|
.matching { it.name == compileKotlinTaskName }
|
||||||
|
.all { compileKotlinTask ->
|
||||||
|
compileKotlinTask.configureAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun source(sourceSet: KotlinSourceSet) {
|
||||||
|
if (kotlinSourceSets.add(sourceSet)) {
|
||||||
|
//TODO possibly issue with forced instantiation
|
||||||
|
target.project.whenEvaluated {
|
||||||
|
sourceSet.getSourceSetHierarchy().forEach { sourceSet ->
|
||||||
|
val isCommonSource =
|
||||||
|
CompilationSourceSetUtil.sourceSetsInMultipleCompilations(project)?.contains(sourceSet) ?: false
|
||||||
|
|
||||||
|
addSourcesToCompileTask(sourceSet, addAsCommonSources = isCommonSource)
|
||||||
|
|
||||||
|
// Use `forced = false` since `api`, `implementation`, and `compileOnly` may be missing in some cases like
|
||||||
|
// old Java & Android projects:
|
||||||
|
addExtendsFromRelation(apiConfigurationName, sourceSet.apiConfigurationName, forced = false)
|
||||||
|
addExtendsFromRelation(implementationConfigurationName, sourceSet.implementationConfigurationName, forced = false)
|
||||||
|
addExtendsFromRelation(compileOnlyConfigurationName, sourceSet.compileOnlyConfigurationName, forced = false)
|
||||||
|
|
||||||
|
if (this@AbstractKotlinCompilation is KotlinCompilationToRunnableFiles<*>) {
|
||||||
|
addExtendsFromRelation(runtimeOnlyConfigurationName, sourceSet.runtimeOnlyConfigurationName, forced = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceSet.name != defaultSourceSetName) {
|
||||||
|
kotlinExtension.sourceSets.findByName(defaultSourceSetName)?.let { defaultSourceSet ->
|
||||||
|
// Temporary solution for checking consistency across source sets participating in a compilation that may
|
||||||
|
// not be interconnected with the dependsOn relation: check the settings as if the default source set of
|
||||||
|
// the compilation depends on the one added to the compilation:
|
||||||
|
defaultSourceSetLanguageSettingsChecker.runAllChecks(
|
||||||
|
defaultSourceSet,
|
||||||
|
sourceSet
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }.orEmpty(),
|
||||||
|
"compileClasspath"
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileKotlinTaskName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
"compile",
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
"Kotlin",
|
||||||
|
target.targetName
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "classes")
|
||||||
|
|
||||||
|
override lateinit var compileDependencyFiles: FileCollection
|
||||||
|
|
||||||
|
override val apiConfigurationName: String
|
||||||
|
get() = disambiguateName("api")
|
||||||
|
|
||||||
|
override val implementationConfigurationName: String
|
||||||
|
get() = disambiguateName("implementation")
|
||||||
|
|
||||||
|
override val compileOnlyConfigurationName: String
|
||||||
|
get() = disambiguateName("compileOnly")
|
||||||
|
|
||||||
|
override val runtimeOnlyConfigurationName: String
|
||||||
|
get() = disambiguateName("runtimeOnly")
|
||||||
|
|
||||||
|
override fun dependencies(configure: KotlinDependencyHandler.() -> Unit): Unit =
|
||||||
|
DefaultKotlinDependencyHandler(this, target.project).run(configure)
|
||||||
|
|
||||||
|
override fun dependencies(configureClosure: Closure<Any?>) =
|
||||||
|
dependencies f@{ ConfigureUtil.configure(configureClosure, this@f) }
|
||||||
|
|
||||||
|
override fun toString(): String = "compilation '$compilationName' ($target)"
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AbstractKotlinCompilationToRunnableFiles<T : KotlinCommonOptions>(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<T>(target, name), KotlinCompilationToRunnableFiles<T> {
|
||||||
|
override val runtimeDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
"runtimeClasspath"
|
||||||
|
)
|
||||||
|
|
||||||
|
override lateinit var runtimeDependencyFiles: FileCollection
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KotlinCompilation<*>.disambiguateName(simpleName: String): String {
|
||||||
|
return lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
simpleName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
open class KotlinJvmCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJvmOptions>(target, name), KotlinCompilationWithResources<KotlinJvmOptions> {
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
override val compileKotlinTask: org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
get() = super.compileKotlinTask as org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinWithJavaCompilation<KotlinOptionsType : KotlinCommonOptions>(
|
||||||
|
target: KotlinWithJavaTarget<KotlinOptionsType>,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinOptionsType>(target, name), KotlinCompilationWithResources<KotlinOptionsType> {
|
||||||
|
lateinit var javaSourceSet: SourceSet
|
||||||
|
|
||||||
|
override val output: KotlinCompilationOutput by lazy { KotlinWithJavaCompilationOutput(this) }
|
||||||
|
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = javaSourceSet.processResourcesTaskName
|
||||||
|
|
||||||
|
override var runtimeDependencyFiles: FileCollection
|
||||||
|
get() = javaSourceSet.runtimeClasspath
|
||||||
|
set(value) {
|
||||||
|
javaSourceSet.runtimeClasspath = value
|
||||||
|
}
|
||||||
|
|
||||||
|
override val runtimeDependencyConfigurationName: String
|
||||||
|
get() = javaSourceSet.runtimeClasspathConfigurationName
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = javaSourceSet.compileClasspathConfigurationName
|
||||||
|
|
||||||
|
override val runtimeOnlyConfigurationName: String
|
||||||
|
get() = javaSourceSet.runtimeOnlyConfigurationName
|
||||||
|
|
||||||
|
override val implementationConfigurationName: String
|
||||||
|
get() = javaSourceSet.implementationConfigurationName
|
||||||
|
|
||||||
|
override val apiConfigurationName: String
|
||||||
|
get() = javaSourceSet.apiConfigurationName
|
||||||
|
|
||||||
|
override val compileOnlyConfigurationName: String
|
||||||
|
get() = javaSourceSet.compileOnlyConfigurationName
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = javaSourceSet.classesTaskName
|
||||||
|
|
||||||
|
override var compileDependencyFiles: FileCollection
|
||||||
|
get() = javaSourceSet.compileClasspath
|
||||||
|
set(value) {
|
||||||
|
javaSourceSet.compileClasspath = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun source(javaSourceSet: SourceSet) {
|
||||||
|
with(target.project) {
|
||||||
|
afterEvaluate {
|
||||||
|
(tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>).source(javaSourceSet.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmAndroidCompilation(
|
||||||
|
target: KotlinAndroidTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJvmOptions>(target, name) {
|
||||||
|
override val compileKotlinTask: org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
get() = super.compileKotlinTask as org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
override val relatedConfigurationNames: List<String>
|
||||||
|
get() = super.relatedConfigurationNames + listOf("${name}ApiElements", "${name}RuntimeElements")
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJsOptions>(target, name), KotlinCompilationWithResources<KotlinJsOptions> {
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
override val compileKotlinTask: Kotlin2JsCompile
|
||||||
|
get() = super.compileKotlinTask as Kotlin2JsCompile
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinCommonCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<KotlinMultiplatformCommonOptions>(target, name) {
|
||||||
|
override val compileKotlinTask: KotlinCompileCommon
|
||||||
|
get() = super.compileKotlinTask as KotlinCompileCommon
|
||||||
|
|
||||||
|
// TODO once we properly compile metadata for each source set, the default source sets will likely become just the source sets
|
||||||
|
// which are transformed to metadata
|
||||||
|
private val commonSourceSetName = when (compilationName) {
|
||||||
|
KotlinCompilation.MAIN_COMPILATION_NAME -> KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME
|
||||||
|
else -> error("Custom metadata compilations are not supported yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
override val defaultSourceSet: KotlinSourceSet
|
||||||
|
get() = target.project.kotlinExtension.sourceSets.getByName(commonSourceSetName)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeCompilation(
|
||||||
|
override val target: KotlinNativeTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<KotlinCommonOptions>(target, name), KotlinCompilationWithResources<KotlinCommonOptions> {
|
||||||
|
|
||||||
|
override val kotlinOptions: KotlinCommonOptions
|
||||||
|
get() = compileKotlinTask.kotlinOptions
|
||||||
|
|
||||||
|
override val compileKotlinTask: KotlinNativeCompile
|
||||||
|
get() = super.compileKotlinTask as KotlinNativeCompile
|
||||||
|
|
||||||
|
private val project: Project
|
||||||
|
get() = target.project
|
||||||
|
|
||||||
|
// A collection containing all source sets used by this compilation
|
||||||
|
// (taking into account dependencies between source sets). Used by both compilation
|
||||||
|
// and linking tasks. Unlike kotlinSourceSets, includes dependency source sets.
|
||||||
|
// TODO: Move into the compilation task when the linking task does klib linking instead of compilation.
|
||||||
|
internal val allSources: MutableSet<SourceDirectorySet> = mutableSetOf()
|
||||||
|
|
||||||
|
// TODO: Move into the compilation task when the linking task does klib linking instead of compilation.
|
||||||
|
internal val commonSources: MutableSet<SourceDirectorySet> = mutableSetOf()
|
||||||
|
|
||||||
|
var isTestCompilation = false
|
||||||
|
|
||||||
|
var friendCompilationName: String? = null
|
||||||
|
|
||||||
|
internal val friendCompilation: KotlinNativeCompilation?
|
||||||
|
get() = friendCompilationName?.let {
|
||||||
|
target.compilations.getByName(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used only to support the old APIs. TODO: Remove when the old APIs are removed.
|
||||||
|
internal val binaries = mutableMapOf<Pair<NativeOutputKind, NativeBuildType>, NativeBinary>()
|
||||||
|
|
||||||
|
// Native-specific DSL.
|
||||||
|
var extraOpts = mutableListOf<String>()
|
||||||
|
|
||||||
|
fun extraOpts(vararg values: Any) = extraOpts(values.toList())
|
||||||
|
fun extraOpts(values: List<Any>) {
|
||||||
|
extraOpts.addAll(values.map { it.toString() })
|
||||||
|
}
|
||||||
|
|
||||||
|
var buildTypes = mutableListOf<NativeBuildType>()
|
||||||
|
var outputKinds = mutableListOf<NativeOutputKind>()
|
||||||
|
|
||||||
|
fun outputKind(kind: NativeOutputKind) = outputKinds.add(kind)
|
||||||
|
|
||||||
|
fun outputKinds(vararg kinds: NativeOutputKind) {
|
||||||
|
outputKinds = kinds.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun outputKinds(vararg kinds: String) {
|
||||||
|
outputKinds = kinds.map { NativeOutputKind.valueOf(it.toUpperCase()) }.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun outputKinds(kinds: List<Any>) {
|
||||||
|
outputKinds = kinds.map {
|
||||||
|
when (it) {
|
||||||
|
is NativeOutputKind -> it
|
||||||
|
is String -> NativeOutputKind.valueOf(it.toUpperCase())
|
||||||
|
else -> error("Cannot use $it as an output kind")
|
||||||
|
}
|
||||||
|
}.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
var entryPoint: String? = null
|
||||||
|
fun entryPoint(value: String) {
|
||||||
|
entryPoint = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interop DSL.
|
||||||
|
val cinterops = project.container(DefaultCInteropSettings::class.java) { cinteropName ->
|
||||||
|
DefaultCInteropSettings(project, cinteropName, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
var linkerOpts = mutableListOf<String>()
|
||||||
|
|
||||||
|
fun cinterops(action: NamedDomainObjectContainer<DefaultCInteropSettings>.() -> Unit) = cinterops.action()
|
||||||
|
fun cinterops(action: Closure<Unit>) = cinterops(ConfigureUtil.configureUsing(action))
|
||||||
|
fun cinterops(action: Action<NamedDomainObjectContainer<DefaultCInteropSettings>>) = action.execute(cinterops)
|
||||||
|
|
||||||
|
fun linkerOpts(vararg values: String) = linkerOpts(values.toList())
|
||||||
|
fun linkerOpts(values: List<String>) {
|
||||||
|
linkerOpts.addAll(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Task accessors.
|
||||||
|
fun findLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeLink? = binaries[kind to buildType]?.linkTask
|
||||||
|
|
||||||
|
fun getLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeLink =
|
||||||
|
findLinkTask(kind, buildType)
|
||||||
|
?: throw IllegalArgumentException("Cannot find a link task for the binary kind '$kind' and the build type '$buildType'")
|
||||||
|
|
||||||
|
fun findLinkTask(kind: String, buildType: String) =
|
||||||
|
findLinkTask(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun getLinkTask(kind: String, buildType: String) =
|
||||||
|
getLinkTask(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun findBinary(kind: NativeOutputKind, buildType: NativeBuildType): File? = findLinkTask(kind, buildType)?.outputFile?.get()
|
||||||
|
|
||||||
|
fun getBinary(kind: NativeOutputKind, buildType: NativeBuildType): File = getLinkTask(kind, buildType).outputFile.get()
|
||||||
|
|
||||||
|
fun findBinary(kind: String, buildType: String) =
|
||||||
|
findBinary(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun getBinary(kind: String, buildType: String) =
|
||||||
|
getBinary(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
// Naming
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
fun linkTaskName(kind: NativeOutputKind, buildType: NativeBuildType): String =
|
||||||
|
lowerCamelCaseName(
|
||||||
|
"link",
|
||||||
|
KotlinNativeBinaryContainer.generateBinaryName(compilationName, buildType, kind.taskNameClassifier),
|
||||||
|
target.targetName
|
||||||
|
)
|
||||||
|
|
||||||
|
fun linkTaskName(kind: String, buildType: String) =
|
||||||
|
linkTaskName(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }.orEmpty(),
|
||||||
|
"compileKlibraries"
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "klibrary")
|
||||||
|
|
||||||
|
val binariesTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "binaries")
|
||||||
|
|
||||||
|
override fun addSourcesToCompileTask(sourceSet: KotlinSourceSet, addAsCommonSources: Boolean) {
|
||||||
|
allSources.add(sourceSet.kotlin)
|
||||||
|
if (addAsCommonSources) {
|
||||||
|
commonSources.add(sourceSet.kotlin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private object CompilationSourceSetUtil {
|
||||||
|
// Cache the results per project
|
||||||
|
private val projectSourceSetsInMultipleCompilationsCache = WeakHashMap<Project, Set<KotlinSourceSet>>()
|
||||||
|
|
||||||
|
fun sourceSetsInMultipleCompilations(project: Project) =
|
||||||
|
projectSourceSetsInMultipleCompilationsCache.computeIfAbsent(project) { _ ->
|
||||||
|
check(project.state.executed) { "Should only be computed after the project is evaluated" }
|
||||||
|
|
||||||
|
val compilations = (project.kotlinExtension as? KotlinMultiplatformExtension)?.targets?.flatMap { it.compilations }
|
||||||
|
?: return@computeIfAbsent null
|
||||||
|
|
||||||
|
compilations
|
||||||
|
.flatMap { compilation -> compilation.allKotlinSourceSets.map { sourceSet -> compilation to sourceSet } }
|
||||||
|
.groupingBy { (_, sourceSet) -> sourceSet }
|
||||||
|
.eachCount()
|
||||||
|
.filterValues { it > 1 }
|
||||||
|
.keys
|
||||||
|
}
|
||||||
|
}
|
||||||
+93
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.NamedDomainObjectFactory
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
|
|
||||||
|
interface KotlinCompilationFactory<T : KotlinCompilation<*>> : NamedDomainObjectFactory<T> {
|
||||||
|
val itemClass: Class<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinCommonCompilationFactory(
|
||||||
|
val target: KotlinOnlyTarget<KotlinCommonCompilation>
|
||||||
|
) : KotlinCompilationFactory<KotlinCommonCompilation> {
|
||||||
|
override val itemClass: Class<KotlinCommonCompilation>
|
||||||
|
get() = KotlinCommonCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinCommonCompilation =
|
||||||
|
KotlinCommonCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmCompilationFactory(
|
||||||
|
val target: KotlinOnlyTarget<KotlinJvmCompilation>
|
||||||
|
) : KotlinCompilationFactory<KotlinJvmCompilation> {
|
||||||
|
override val itemClass: Class<KotlinJvmCompilation>
|
||||||
|
get() = KotlinJvmCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinJvmCompilation =
|
||||||
|
KotlinJvmCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinWithJavaCompilationFactory<KotlinOptionsType : KotlinCommonOptions>(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinWithJavaTarget<KotlinOptionsType>
|
||||||
|
) : KotlinCompilationFactory<KotlinWithJavaCompilation<KotlinOptionsType>> {
|
||||||
|
|
||||||
|
override val itemClass: Class<KotlinWithJavaCompilation<KotlinOptionsType>>
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
get() = KotlinWithJavaCompilation::class.java as Class<KotlinWithJavaCompilation<KotlinOptionsType>>
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinWithJavaCompilation<KotlinOptionsType> {
|
||||||
|
val result = KotlinWithJavaCompilation(target, name)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmAndroidCompilationFactory(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinAndroidTarget
|
||||||
|
) : KotlinCompilationFactory<KotlinJvmAndroidCompilation> {
|
||||||
|
|
||||||
|
override val itemClass: Class<KotlinJvmAndroidCompilation>
|
||||||
|
get() = KotlinJvmAndroidCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinJvmAndroidCompilation =
|
||||||
|
KotlinJvmAndroidCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsCompilationFactory(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinOnlyTarget<KotlinJsCompilation>
|
||||||
|
) : KotlinCompilationFactory<KotlinJsCompilation> {
|
||||||
|
override val itemClass: Class<KotlinJsCompilation>
|
||||||
|
get() = KotlinJsCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinJsCompilation =
|
||||||
|
KotlinJsCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeCompilationFactory(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinNativeTarget
|
||||||
|
) : KotlinCompilationFactory<KotlinNativeCompilation> {
|
||||||
|
|
||||||
|
override val itemClass: Class<KotlinNativeCompilation>
|
||||||
|
get() = KotlinNativeCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinNativeCompilation =
|
||||||
|
KotlinNativeCompilation(target, name).apply {
|
||||||
|
if (name == KotlinCompilation.TEST_COMPILATION_NAME) {
|
||||||
|
friendCompilationName = KotlinCompilation.MAIN_COMPILATION_NAME
|
||||||
|
isTestCompilation = true
|
||||||
|
}
|
||||||
|
buildTypes = mutableListOf(NativeBuildType.DEBUG, NativeBuildType.RELEASE)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+330
@@ -0,0 +1,330 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.artifacts.Dependency
|
||||||
|
import org.gradle.api.internal.file.FileResolver
|
||||||
|
import org.gradle.api.plugins.JavaPlugin
|
||||||
|
import org.gradle.internal.reflect.Instantiator
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.KotlinNativeProjectProperty
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.hasProperty
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.konanHome
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinTask
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
|
||||||
|
import org.jetbrains.kotlin.konan.KonanVersion
|
||||||
|
import org.jetbrains.kotlin.konan.target.HostManager
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
abstract class KotlinOnlyTargetPreset<T : KotlinCompilation<*>>(
|
||||||
|
protected val project: Project,
|
||||||
|
private val instantiator: Instantiator,
|
||||||
|
private val fileResolver: FileResolver,
|
||||||
|
protected val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinOnlyTarget<T>> {
|
||||||
|
|
||||||
|
protected open fun createKotlinTargetConfigurator(): KotlinTargetConfigurator<T> =
|
||||||
|
KotlinTargetConfigurator(createDefaultSourceSets = true, createTestCompilation = true)
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinOnlyTarget<T> {
|
||||||
|
val result = KotlinOnlyTarget<T>(project, platformType).apply {
|
||||||
|
targetName = name
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinOnlyTargetPreset
|
||||||
|
|
||||||
|
val compilationFactory = createCompilationFactory(this)
|
||||||
|
compilations = project.container(compilationFactory.itemClass, compilationFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
createKotlinTargetConfigurator().configureTarget(result)
|
||||||
|
|
||||||
|
result.compilations.all { compilation ->
|
||||||
|
buildCompilationProcessor(compilation).run()
|
||||||
|
if (compilation.name == KotlinCompilation.MAIN_COMPILATION_NAME) {
|
||||||
|
sourcesJarTask(compilation, result.targetName, result.targetName.toLowerCase())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun createCompilationFactory(forTarget: KotlinOnlyTarget<T>): KotlinCompilationFactory<T>
|
||||||
|
protected abstract val platformType: KotlinPlatformType
|
||||||
|
internal abstract fun buildCompilationProcessor(compilation: T): KotlinSourceSetProcessor<*>
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinMetadataTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinCommonCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(
|
||||||
|
forTarget: KotlinOnlyTarget<KotlinCommonCompilation>
|
||||||
|
): KotlinCompilationFactory<KotlinCommonCompilation> =
|
||||||
|
KotlinCommonCompilationFactory(forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.common
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinCommonCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return KotlinCommonSourceSetProcessor(project, compilation, tasksProvider, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "metadata"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createKotlinTargetConfigurator(): KotlinTargetConfigurator<KotlinCommonCompilation> =
|
||||||
|
KotlinTargetConfigurator(createDefaultSourceSets = false, createTestCompilation = false)
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinOnlyTarget<KotlinCommonCompilation> =
|
||||||
|
super.createTarget(name).apply {
|
||||||
|
val mainCompilation = compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
val commonMainSourceSet = project.kotlinExtension.sourceSets.getByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
||||||
|
|
||||||
|
mainCompilation.source(commonMainSourceSet)
|
||||||
|
|
||||||
|
project.afterEvaluate {
|
||||||
|
// Since there's no default source set, apply language settings from commonMain:
|
||||||
|
val compileKotlinMetadata = project.tasks.getByName(mainCompilation.compileKotlinTaskName) as KotlinCompile<*>
|
||||||
|
applyLanguageSettingsToKotlinTask(commonMainSourceSet.languageSettings, compileKotlinMetadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinJvmCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinJvmCompilation>): KotlinCompilationFactory<KotlinJvmCompilation> =
|
||||||
|
KotlinJvmCompilationFactory(forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.jvm
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinJvmCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return Kotlin2JvmSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "jvm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinJsCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinJsCompilation>) =
|
||||||
|
KotlinJsCompilationFactory(project, forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.js
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinJsCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return Kotlin2JsSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinAndroidTargetPreset(
|
||||||
|
private val project: Project,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinAndroidTarget> {
|
||||||
|
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinAndroidTarget {
|
||||||
|
val result = KotlinAndroidTarget(name, project).apply {
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinAndroidTargetPreset
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinAndroidPlugin.applyToTarget(kotlinPluginVersion, result)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "android"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmWithJavaTargetPreset(
|
||||||
|
private val project: Project,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinWithJavaTarget<KotlinJvmOptions>> {
|
||||||
|
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinWithJavaTarget<KotlinJvmOptions> {
|
||||||
|
project.plugins.apply(JavaPlugin::class.java)
|
||||||
|
|
||||||
|
val target = KotlinWithJavaTarget<KotlinJvmOptions>(project, KotlinPlatformType.jvm, name).apply {
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinJvmWithJavaTargetPreset
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractKotlinPlugin.configureTarget(target) { compilation ->
|
||||||
|
Kotlin2JvmSourceSetProcessor(project, KotlinTasksProvider(name), compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
target.compilations.getByName("test").run {
|
||||||
|
val main = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
|
||||||
|
compileDependencyFiles = project.files(
|
||||||
|
main.output.allOutputs,
|
||||||
|
project.configurations.maybeCreate(compileDependencyConfigurationName)
|
||||||
|
)
|
||||||
|
runtimeDependencyFiles = project.files(
|
||||||
|
output.allOutputs,
|
||||||
|
main.output.allOutputs,
|
||||||
|
project.configurations.maybeCreate(runtimeDependencyConfigurationName)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "jvmWithJava"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeTargetPreset(
|
||||||
|
private val name: String,
|
||||||
|
val project: Project,
|
||||||
|
val konanTarget: KonanTarget,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinNativeTarget> {
|
||||||
|
|
||||||
|
init {
|
||||||
|
// This is required to obtain Kotlin/Native home in CLion plugin:
|
||||||
|
setupNativeHomePrivateProperty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName(): String = name
|
||||||
|
|
||||||
|
private fun setupNativeHomePrivateProperty() = with(project) {
|
||||||
|
if (!hasProperty(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY))
|
||||||
|
extensions.extraProperties.set(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY, konanHome)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupNativeCompiler() = with(project) {
|
||||||
|
if (!hasProperty(KotlinNativeProjectProperty.KONAN_HOME_OVERRIDE)) {
|
||||||
|
NativeCompilerDownloader(this).downloadIfNeeded()
|
||||||
|
logger.info("Kotlin/Native distribution: $konanHome")
|
||||||
|
} else {
|
||||||
|
logger.info("User-provided Kotlin/Native distribution: $konanHome")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We declare default K/N dependencies as files to avoid searching them in remote repos (see KT-28128).
|
||||||
|
private fun defaultLibs(target: KonanTarget? = null): List<Dependency> = with(project) {
|
||||||
|
|
||||||
|
val relPath = if (target != null) "platform/${target.name}" else "common"
|
||||||
|
|
||||||
|
file("$konanHome/klib/$relPath")
|
||||||
|
.listFiles { file -> file.isDirectory }
|
||||||
|
?.sortedBy { dir -> dir.name.toLowerCase() }
|
||||||
|
?.map { dir -> dependencies.create(files(dir)) } ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinNativeTarget {
|
||||||
|
setupNativeCompiler()
|
||||||
|
|
||||||
|
val result = KotlinNativeTarget(project, konanTarget).apply {
|
||||||
|
targetName = name
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinNativeTargetPreset
|
||||||
|
|
||||||
|
val compilationFactory = KotlinNativeCompilationFactory(project, this)
|
||||||
|
compilations = project.container(compilationFactory.itemClass, compilationFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinNativeTargetConfigurator(kotlinPluginVersion).configureTarget(result)
|
||||||
|
|
||||||
|
// Allow IDE to resolve the libraries provided by the compiler by adding them into dependencies.
|
||||||
|
result.compilations.all { compilation ->
|
||||||
|
val target = compilation.target.konanTarget
|
||||||
|
// First, put common libs:
|
||||||
|
defaultLibs().forEach {
|
||||||
|
project.dependencies.add(compilation.compileDependencyConfigurationName, it)
|
||||||
|
}
|
||||||
|
// Then, platform-specific libs:
|
||||||
|
defaultLibs(target).forEach {
|
||||||
|
project.dependencies.add(compilation.compileDependencyConfigurationName, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!konanTarget.enabledOnCurrentHost) {
|
||||||
|
with(HostManager()) {
|
||||||
|
val supportedHosts = enabledTargetsByHost.filterValues { konanTarget in it }.keys
|
||||||
|
val supportedHostsString =
|
||||||
|
if (supportedHosts.size == 1)
|
||||||
|
"a ${supportedHosts.single()} host" else
|
||||||
|
"one of the host platforms: ${supportedHosts.joinToString(", ")}"
|
||||||
|
project.logger.warn(
|
||||||
|
"Target '$name' for platform ${konanTarget} is ignored during build on this ${HostManager.host} machine. " +
|
||||||
|
"You can build it with $supportedHostsString."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY = "konanHome"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val KonanTarget.isCurrentHost: Boolean
|
||||||
|
get() = this == HostManager.host
|
||||||
|
|
||||||
|
internal val KonanTarget.enabledOnCurrentHost
|
||||||
|
get() = HostManager().isEnabled(this)
|
||||||
|
|
||||||
|
internal val KotlinNativeCompilation.isMainCompilation: Boolean
|
||||||
|
get() = name == KotlinCompilation.MAIN_COMPILATION_NAME
|
||||||
+471
@@ -0,0 +1,471 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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 groovy.lang.Closure
|
||||||
|
import org.gradle.api.Action
|
||||||
|
import org.gradle.api.NamedDomainObjectContainer
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.attributes.AttributeContainer
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.file.SourceDirectorySet
|
||||||
|
import org.gradle.api.tasks.SourceSet
|
||||||
|
import org.gradle.util.ConfigureUtil
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.*
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.defaultSourceSetLanguageSettingsChecker
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.getSourceSetHierarchy
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.*
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
|
internal fun KotlinCompilation<*>.composeName(prefix: String? = null, suffix: String? = null): String {
|
||||||
|
val compilationNamePart = compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }
|
||||||
|
val targetNamePart = target.disambiguationClassifier
|
||||||
|
|
||||||
|
return lowerCamelCaseName(prefix, targetNamePart, compilationNamePart, suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val KotlinCompilation<*>.defaultSourceSetName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName)
|
||||||
|
|
||||||
|
abstract class AbstractKotlinCompilation<T : KotlinCommonOptions>(
|
||||||
|
target: KotlinTarget,
|
||||||
|
override val compilationName: String
|
||||||
|
) : KotlinCompilation<T>, HasKotlinDependencies {
|
||||||
|
|
||||||
|
override val kotlinOptions: T
|
||||||
|
get() = compileKotlinTask.kotlinOptions
|
||||||
|
|
||||||
|
override fun kotlinOptions(configure: T.() -> Unit) =
|
||||||
|
configure(kotlinOptions)
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override val compileKotlinTask: KotlinCompile<T>
|
||||||
|
get() = (target.project.tasks.getByName(compileKotlinTaskName) as KotlinCompile<T>)
|
||||||
|
|
||||||
|
// Don't declare this property in the constructor to avoid NPE
|
||||||
|
// when an overriding property of a subclass is accessed instead.
|
||||||
|
override val target: KotlinTarget = target
|
||||||
|
|
||||||
|
private val attributeContainer = HierarchyAttributeContainer(target.attributes)
|
||||||
|
|
||||||
|
override fun getAttributes(): AttributeContainer = attributeContainer
|
||||||
|
|
||||||
|
override val kotlinSourceSets: MutableSet<KotlinSourceSet> = mutableSetOf()
|
||||||
|
|
||||||
|
override val allKotlinSourceSets: Set<KotlinSourceSet>
|
||||||
|
get() = kotlinSourceSets.flatMapTo(mutableSetOf()) { it.getSourceSetHierarchy() }
|
||||||
|
|
||||||
|
override val defaultSourceSet: KotlinSourceSet
|
||||||
|
get() = target.project.kotlinExtension.sourceSets.getByName(defaultSourceSetName)
|
||||||
|
|
||||||
|
override fun defaultSourceSet(configure: KotlinSourceSet.() -> Unit) =
|
||||||
|
configure(defaultSourceSet)
|
||||||
|
|
||||||
|
override val output: KotlinCompilationOutput by lazy {
|
||||||
|
DefaultKotlinCompilationOutput(
|
||||||
|
target.project,
|
||||||
|
Callable { target.project.buildDir.resolve("processedResources/${target.targetName}/$name") })
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun addSourcesToCompileTask(sourceSet: KotlinSourceSet, addAsCommonSources: Boolean) {
|
||||||
|
fun AbstractKotlinCompile<*>.configureAction() {
|
||||||
|
source(sourceSet.kotlin)
|
||||||
|
sourceFilesExtensions(sourceSet.customSourceFilesExtensions)
|
||||||
|
if (addAsCommonSources) {
|
||||||
|
commonSourceSet += sourceSet.kotlin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note! Invocation of withType-all results in preliminary task instantiation.
|
||||||
|
// After fix of this issue the following code should be uncommented:
|
||||||
|
// if (useLazyTaskConfiguration) {
|
||||||
|
// (target.project.tasks.named(compileKotlinTaskName) as TaskProvider<AbstractKotlinCompile<*>>).configure {
|
||||||
|
// it.configureAction()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
target.project.tasks
|
||||||
|
// To configure a task that may have not yet been created at this point, use 'withType-matching-all`:
|
||||||
|
.withType(AbstractKotlinCompile::class.java)
|
||||||
|
.matching { it.name == compileKotlinTaskName }
|
||||||
|
.all { compileKotlinTask ->
|
||||||
|
compileKotlinTask.configureAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun source(sourceSet: KotlinSourceSet) {
|
||||||
|
if (kotlinSourceSets.add(sourceSet)) {
|
||||||
|
//TODO possibly issue with forced instantiation
|
||||||
|
target.project.whenEvaluated {
|
||||||
|
sourceSet.getSourceSetHierarchy().forEach { sourceSet ->
|
||||||
|
val isCommonSource =
|
||||||
|
CompilationSourceSetUtil.sourceSetsInMultipleCompilations(project)?.contains(sourceSet) ?: false
|
||||||
|
|
||||||
|
addSourcesToCompileTask(sourceSet, addAsCommonSources = isCommonSource)
|
||||||
|
|
||||||
|
// Use `forced = false` since `api`, `implementation`, and `compileOnly` may be missing in some cases like
|
||||||
|
// old Java & Android projects:
|
||||||
|
addExtendsFromRelation(apiConfigurationName, sourceSet.apiConfigurationName, forced = false)
|
||||||
|
addExtendsFromRelation(implementationConfigurationName, sourceSet.implementationConfigurationName, forced = false)
|
||||||
|
addExtendsFromRelation(compileOnlyConfigurationName, sourceSet.compileOnlyConfigurationName, forced = false)
|
||||||
|
|
||||||
|
if (this@AbstractKotlinCompilation is KotlinCompilationToRunnableFiles<*>) {
|
||||||
|
addExtendsFromRelation(runtimeOnlyConfigurationName, sourceSet.runtimeOnlyConfigurationName, forced = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceSet.name != defaultSourceSetName) {
|
||||||
|
kotlinExtension.sourceSets.findByName(defaultSourceSetName)?.let { defaultSourceSet ->
|
||||||
|
// Temporary solution for checking consistency across source sets participating in a compilation that may
|
||||||
|
// not be interconnected with the dependsOn relation: check the settings as if the default source set of
|
||||||
|
// the compilation depends on the one added to the compilation:
|
||||||
|
defaultSourceSetLanguageSettingsChecker.runAllChecks(
|
||||||
|
defaultSourceSet,
|
||||||
|
sourceSet
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }.orEmpty(),
|
||||||
|
"compileClasspath"
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileKotlinTaskName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
"compile",
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
"Kotlin",
|
||||||
|
target.targetName
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "classes")
|
||||||
|
|
||||||
|
override lateinit var compileDependencyFiles: FileCollection
|
||||||
|
|
||||||
|
override val apiConfigurationName: String
|
||||||
|
get() = disambiguateName("api")
|
||||||
|
|
||||||
|
override val implementationConfigurationName: String
|
||||||
|
get() = disambiguateName("implementation")
|
||||||
|
|
||||||
|
override val compileOnlyConfigurationName: String
|
||||||
|
get() = disambiguateName("compileOnly")
|
||||||
|
|
||||||
|
override val runtimeOnlyConfigurationName: String
|
||||||
|
get() = disambiguateName("runtimeOnly")
|
||||||
|
|
||||||
|
override fun dependencies(configure: KotlinDependencyHandler.() -> Unit): Unit =
|
||||||
|
DefaultKotlinDependencyHandler(this, target.project).run(configure)
|
||||||
|
|
||||||
|
override fun dependencies(configureClosure: Closure<Any?>) =
|
||||||
|
dependencies f@{ ConfigureUtil.configure(configureClosure, this@f) }
|
||||||
|
|
||||||
|
override fun toString(): String = "compilation '$compilationName' ($target)"
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AbstractKotlinCompilationToRunnableFiles<T : KotlinCommonOptions>(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<T>(target, name), KotlinCompilationToRunnableFiles<T> {
|
||||||
|
override val runtimeDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
"runtimeClasspath"
|
||||||
|
)
|
||||||
|
|
||||||
|
override lateinit var runtimeDependencyFiles: FileCollection
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KotlinCompilation<*>.disambiguateName(simpleName: String): String {
|
||||||
|
return lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
simpleName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
open class KotlinJvmCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJvmOptions>(target, name), KotlinCompilationWithResources<KotlinJvmOptions> {
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
override val compileKotlinTask: org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
get() = super.compileKotlinTask as org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinWithJavaCompilation<KotlinOptionsType : KotlinCommonOptions>(
|
||||||
|
target: KotlinWithJavaTarget<KotlinOptionsType>,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinOptionsType>(target, name), KotlinCompilationWithResources<KotlinOptionsType> {
|
||||||
|
lateinit var javaSourceSet: SourceSet
|
||||||
|
|
||||||
|
override val output: KotlinCompilationOutput by lazy { KotlinWithJavaCompilationOutput(this) }
|
||||||
|
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = javaSourceSet.processResourcesTaskName
|
||||||
|
|
||||||
|
override var runtimeDependencyFiles: FileCollection
|
||||||
|
get() = javaSourceSet.runtimeClasspath
|
||||||
|
set(value) {
|
||||||
|
javaSourceSet.runtimeClasspath = value
|
||||||
|
}
|
||||||
|
|
||||||
|
override val runtimeDependencyConfigurationName: String
|
||||||
|
get() = javaSourceSet.runtimeClasspathConfigurationName
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = javaSourceSet.compileClasspathConfigurationName
|
||||||
|
|
||||||
|
override val runtimeOnlyConfigurationName: String
|
||||||
|
get() = javaSourceSet.runtimeOnlyConfigurationName
|
||||||
|
|
||||||
|
override val implementationConfigurationName: String
|
||||||
|
get() = javaSourceSet.implementationConfigurationName
|
||||||
|
|
||||||
|
override val apiConfigurationName: String
|
||||||
|
get() = javaSourceSet.apiConfigurationName
|
||||||
|
|
||||||
|
override val compileOnlyConfigurationName: String
|
||||||
|
get() = javaSourceSet.compileOnlyConfigurationName
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = javaSourceSet.classesTaskName
|
||||||
|
|
||||||
|
override var compileDependencyFiles: FileCollection
|
||||||
|
get() = javaSourceSet.compileClasspath
|
||||||
|
set(value) {
|
||||||
|
javaSourceSet.compileClasspath = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun source(javaSourceSet: SourceSet) {
|
||||||
|
with(target.project) {
|
||||||
|
afterEvaluate {
|
||||||
|
(tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>).source(javaSourceSet.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmAndroidCompilation(
|
||||||
|
target: KotlinAndroidTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJvmOptions>(target, name) {
|
||||||
|
override val compileKotlinTask: org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
get() = super.compileKotlinTask as org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
override val relatedConfigurationNames: List<String>
|
||||||
|
get() = super.relatedConfigurationNames + listOf("${name}ApiElements", "${name}RuntimeElements")
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJsOptions>(target, name), KotlinCompilationWithResources<KotlinJsOptions> {
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
override val compileKotlinTask: Kotlin2JsCompile
|
||||||
|
get() = super.compileKotlinTask as Kotlin2JsCompile
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinCommonCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<KotlinMultiplatformCommonOptions>(target, name) {
|
||||||
|
override val compileKotlinTask: KotlinCompileCommon
|
||||||
|
get() = super.compileKotlinTask as KotlinCompileCommon
|
||||||
|
|
||||||
|
// TODO once we properly compile metadata for each source set, the default source sets will likely become just the source sets
|
||||||
|
// which are transformed to metadata
|
||||||
|
private val commonSourceSetName = when (compilationName) {
|
||||||
|
KotlinCompilation.MAIN_COMPILATION_NAME -> KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME
|
||||||
|
else -> error("Custom metadata compilations are not supported yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
override val defaultSourceSet: KotlinSourceSet
|
||||||
|
get() = target.project.kotlinExtension.sourceSets.getByName(commonSourceSetName)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeCompilation(
|
||||||
|
override val target: KotlinNativeTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<KotlinCommonOptions>(target, name), KotlinCompilationWithResources<KotlinCommonOptions> {
|
||||||
|
|
||||||
|
override val kotlinOptions: KotlinCommonOptions
|
||||||
|
get() = compileKotlinTask.kotlinOptions
|
||||||
|
|
||||||
|
override val compileKotlinTask: KotlinNativeCompile
|
||||||
|
get() = super.compileKotlinTask as KotlinNativeCompile
|
||||||
|
|
||||||
|
private val project: Project
|
||||||
|
get() = target.project
|
||||||
|
|
||||||
|
// A collection containing all source sets used by this compilation
|
||||||
|
// (taking into account dependencies between source sets). Used by both compilation
|
||||||
|
// and linking tasks. Unlike kotlinSourceSets, includes dependency source sets.
|
||||||
|
// TODO: Move into the compilation task when the linking task does klib linking instead of compilation.
|
||||||
|
internal val allSources: MutableSet<SourceDirectorySet> = mutableSetOf()
|
||||||
|
|
||||||
|
// TODO: Move into the compilation task when the linking task does klib linking instead of compilation.
|
||||||
|
internal val commonSources: MutableSet<SourceDirectorySet> = mutableSetOf()
|
||||||
|
|
||||||
|
var isTestCompilation = false
|
||||||
|
|
||||||
|
var friendCompilationName: String? = null
|
||||||
|
|
||||||
|
internal val friendCompilation: KotlinNativeCompilation?
|
||||||
|
get() = friendCompilationName?.let {
|
||||||
|
target.compilations.getByName(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used only to support the old APIs. TODO: Remove when the old APIs are removed.
|
||||||
|
internal val binaries = mutableMapOf<Pair<NativeOutputKind, NativeBuildType>, NativeBinary>()
|
||||||
|
|
||||||
|
// Native-specific DSL.
|
||||||
|
var extraOpts = mutableListOf<String>()
|
||||||
|
|
||||||
|
fun extraOpts(vararg values: Any) = extraOpts(values.toList())
|
||||||
|
fun extraOpts(values: List<Any>) {
|
||||||
|
extraOpts.addAll(values.map { it.toString() })
|
||||||
|
}
|
||||||
|
|
||||||
|
var buildTypes = mutableListOf<NativeBuildType>()
|
||||||
|
var outputKinds = mutableListOf<NativeOutputKind>()
|
||||||
|
|
||||||
|
fun outputKind(kind: NativeOutputKind) = outputKinds.add(kind)
|
||||||
|
|
||||||
|
fun outputKinds(vararg kinds: NativeOutputKind) {
|
||||||
|
outputKinds = kinds.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun outputKinds(vararg kinds: String) {
|
||||||
|
outputKinds = kinds.map { NativeOutputKind.valueOf(it.toUpperCase()) }.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun outputKinds(kinds: List<Any>) {
|
||||||
|
outputKinds = kinds.map {
|
||||||
|
when (it) {
|
||||||
|
is NativeOutputKind -> it
|
||||||
|
is String -> NativeOutputKind.valueOf(it.toUpperCase())
|
||||||
|
else -> error("Cannot use $it as an output kind")
|
||||||
|
}
|
||||||
|
}.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
var entryPoint: String? = null
|
||||||
|
fun entryPoint(value: String) {
|
||||||
|
entryPoint = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interop DSL.
|
||||||
|
val cinterops = project.container(DefaultCInteropSettings::class.java) { cinteropName ->
|
||||||
|
DefaultCInteropSettings(project, cinteropName, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
var linkerOpts = mutableListOf<String>()
|
||||||
|
|
||||||
|
fun cinterops(action: NamedDomainObjectContainer<DefaultCInteropSettings>.() -> Unit) = cinterops.action()
|
||||||
|
fun cinterops(action: Closure<Unit>) = cinterops(ConfigureUtil.configureUsing(action))
|
||||||
|
fun cinterops(action: Action<NamedDomainObjectContainer<DefaultCInteropSettings>>) = action.execute(cinterops)
|
||||||
|
|
||||||
|
fun linkerOpts(vararg values: String) = linkerOpts(values.toList())
|
||||||
|
fun linkerOpts(values: List<String>) {
|
||||||
|
linkerOpts.addAll(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Task accessors.
|
||||||
|
fun findLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeLink? = binaries[kind to buildType]?.linkTask
|
||||||
|
|
||||||
|
fun getLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeLink =
|
||||||
|
findLinkTask(kind, buildType)
|
||||||
|
?: throw IllegalArgumentException("Cannot find a link task for the binary kind '$kind' and the build type '$buildType'")
|
||||||
|
|
||||||
|
fun findLinkTask(kind: String, buildType: String) =
|
||||||
|
findLinkTask(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun getLinkTask(kind: String, buildType: String) =
|
||||||
|
getLinkTask(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun findBinary(kind: NativeOutputKind, buildType: NativeBuildType): File? = findLinkTask(kind, buildType)?.outputFile?.get()
|
||||||
|
|
||||||
|
fun getBinary(kind: NativeOutputKind, buildType: NativeBuildType): File = getLinkTask(kind, buildType).outputFile.get()
|
||||||
|
|
||||||
|
fun findBinary(kind: String, buildType: String) =
|
||||||
|
findBinary(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun getBinary(kind: String, buildType: String) =
|
||||||
|
getBinary(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
// Naming
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
fun linkTaskName(kind: NativeOutputKind, buildType: NativeBuildType): String =
|
||||||
|
lowerCamelCaseName(
|
||||||
|
"link",
|
||||||
|
KotlinNativeBinaryContainer.generateBinaryName(compilationName, buildType, kind.taskNameClassifier),
|
||||||
|
target.targetName
|
||||||
|
)
|
||||||
|
|
||||||
|
fun linkTaskName(kind: String, buildType: String) =
|
||||||
|
linkTaskName(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }.orEmpty(),
|
||||||
|
"compileKlibraries"
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "klibrary")
|
||||||
|
|
||||||
|
val binariesTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "binaries")
|
||||||
|
|
||||||
|
override fun addSourcesToCompileTask(sourceSet: KotlinSourceSet, addAsCommonSources: Boolean) {
|
||||||
|
allSources.add(sourceSet.kotlin)
|
||||||
|
if (addAsCommonSources) {
|
||||||
|
commonSources.add(sourceSet.kotlin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private object CompilationSourceSetUtil {
|
||||||
|
// Cache the results per project
|
||||||
|
private val projectSourceSetsInMultipleCompilationsCache = WeakHashMap<Project, Set<KotlinSourceSet>>()
|
||||||
|
|
||||||
|
fun sourceSetsInMultipleCompilations(project: Project) =
|
||||||
|
projectSourceSetsInMultipleCompilationsCache.computeIfAbsent(project) { _ ->
|
||||||
|
check(project.state.executed) { "Should only be computed after the project is evaluated" }
|
||||||
|
|
||||||
|
val compilations = (project.kotlinExtension as? KotlinMultiplatformExtension)?.targets?.flatMap { it.compilations }
|
||||||
|
?: return@computeIfAbsent null
|
||||||
|
|
||||||
|
compilations
|
||||||
|
.flatMap { compilation -> compilation.allKotlinSourceSets.map { sourceSet -> compilation to sourceSet } }
|
||||||
|
.groupingBy { (_, sourceSet) -> sourceSet }
|
||||||
|
.eachCount()
|
||||||
|
.filterValues { it > 1 }
|
||||||
|
.keys
|
||||||
|
}
|
||||||
|
}
|
||||||
+93
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.NamedDomainObjectFactory
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
|
|
||||||
|
interface KotlinCompilationFactory<T : KotlinCompilation<*>> : NamedDomainObjectFactory<T> {
|
||||||
|
val itemClass: Class<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinCommonCompilationFactory(
|
||||||
|
val target: KotlinOnlyTarget<KotlinCommonCompilation>
|
||||||
|
) : KotlinCompilationFactory<KotlinCommonCompilation> {
|
||||||
|
override val itemClass: Class<KotlinCommonCompilation>
|
||||||
|
get() = KotlinCommonCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinCommonCompilation =
|
||||||
|
KotlinCommonCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmCompilationFactory(
|
||||||
|
val target: KotlinOnlyTarget<KotlinJvmCompilation>
|
||||||
|
) : KotlinCompilationFactory<KotlinJvmCompilation> {
|
||||||
|
override val itemClass: Class<KotlinJvmCompilation>
|
||||||
|
get() = KotlinJvmCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinJvmCompilation =
|
||||||
|
KotlinJvmCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinWithJavaCompilationFactory<KotlinOptionsType : KotlinCommonOptions>(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinWithJavaTarget<KotlinOptionsType>
|
||||||
|
) : KotlinCompilationFactory<KotlinWithJavaCompilation<KotlinOptionsType>> {
|
||||||
|
|
||||||
|
override val itemClass: Class<KotlinWithJavaCompilation<KotlinOptionsType>>
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
get() = KotlinWithJavaCompilation::class.java as Class<KotlinWithJavaCompilation<KotlinOptionsType>>
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinWithJavaCompilation<KotlinOptionsType> {
|
||||||
|
val result = KotlinWithJavaCompilation(target, name)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmAndroidCompilationFactory(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinAndroidTarget
|
||||||
|
) : KotlinCompilationFactory<KotlinJvmAndroidCompilation> {
|
||||||
|
|
||||||
|
override val itemClass: Class<KotlinJvmAndroidCompilation>
|
||||||
|
get() = KotlinJvmAndroidCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinJvmAndroidCompilation =
|
||||||
|
KotlinJvmAndroidCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsCompilationFactory(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinOnlyTarget<KotlinJsCompilation>
|
||||||
|
) : KotlinCompilationFactory<KotlinJsCompilation> {
|
||||||
|
override val itemClass: Class<KotlinJsCompilation>
|
||||||
|
get() = KotlinJsCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinJsCompilation =
|
||||||
|
KotlinJsCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeCompilationFactory(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinNativeTarget
|
||||||
|
) : KotlinCompilationFactory<KotlinNativeCompilation> {
|
||||||
|
|
||||||
|
override val itemClass: Class<KotlinNativeCompilation>
|
||||||
|
get() = KotlinNativeCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinNativeCompilation =
|
||||||
|
KotlinNativeCompilation(target, name).apply {
|
||||||
|
if (name == KotlinCompilation.TEST_COMPILATION_NAME) {
|
||||||
|
friendCompilationName = KotlinCompilation.MAIN_COMPILATION_NAME
|
||||||
|
isTestCompilation = true
|
||||||
|
}
|
||||||
|
buildTypes = mutableListOf(NativeBuildType.DEBUG, NativeBuildType.RELEASE)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+471
@@ -0,0 +1,471 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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 groovy.lang.Closure
|
||||||
|
import org.gradle.api.Action
|
||||||
|
import org.gradle.api.NamedDomainObjectContainer
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.attributes.AttributeContainer
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.file.SourceDirectorySet
|
||||||
|
import org.gradle.api.tasks.SourceSet
|
||||||
|
import org.gradle.util.ConfigureUtil
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.*
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.defaultSourceSetLanguageSettingsChecker
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.getSourceSetHierarchy
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.*
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
|
internal fun KotlinCompilation<*>.composeName(prefix: String? = null, suffix: String? = null): String {
|
||||||
|
val compilationNamePart = compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }
|
||||||
|
val targetNamePart = target.disambiguationClassifier
|
||||||
|
|
||||||
|
return lowerCamelCaseName(prefix, targetNamePart, compilationNamePart, suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val KotlinCompilation<*>.defaultSourceSetName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName)
|
||||||
|
|
||||||
|
abstract class AbstractKotlinCompilation<T : KotlinCommonOptions>(
|
||||||
|
target: KotlinTarget,
|
||||||
|
override val compilationName: String
|
||||||
|
) : KotlinCompilation<T>, HasKotlinDependencies {
|
||||||
|
|
||||||
|
override val kotlinOptions: T
|
||||||
|
get() = compileKotlinTask.kotlinOptions
|
||||||
|
|
||||||
|
override fun kotlinOptions(configure: T.() -> Unit) =
|
||||||
|
configure(kotlinOptions)
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override val compileKotlinTask: KotlinCompile<T>
|
||||||
|
get() = (target.project.tasks.getByName(compileKotlinTaskName) as KotlinCompile<T>)
|
||||||
|
|
||||||
|
// Don't declare this property in the constructor to avoid NPE
|
||||||
|
// when an overriding property of a subclass is accessed instead.
|
||||||
|
override val target: KotlinTarget = target
|
||||||
|
|
||||||
|
private val attributeContainer = HierarchyAttributeContainer(target.attributes)
|
||||||
|
|
||||||
|
override fun getAttributes(): AttributeContainer = attributeContainer
|
||||||
|
|
||||||
|
override val kotlinSourceSets: MutableSet<KotlinSourceSet> = mutableSetOf()
|
||||||
|
|
||||||
|
override val allKotlinSourceSets: Set<KotlinSourceSet>
|
||||||
|
get() = kotlinSourceSets.flatMapTo(mutableSetOf()) { it.getSourceSetHierarchy() }
|
||||||
|
|
||||||
|
override val defaultSourceSet: KotlinSourceSet
|
||||||
|
get() = target.project.kotlinExtension.sourceSets.getByName(defaultSourceSetName)
|
||||||
|
|
||||||
|
override fun defaultSourceSet(configure: KotlinSourceSet.() -> Unit) =
|
||||||
|
configure(defaultSourceSet)
|
||||||
|
|
||||||
|
override val output: KotlinCompilationOutput by lazy {
|
||||||
|
DefaultKotlinCompilationOutput(
|
||||||
|
target.project,
|
||||||
|
Callable { target.project.buildDir.resolve("processedResources/${target.targetName}/$name") })
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun addSourcesToCompileTask(sourceSet: KotlinSourceSet, addAsCommonSources: Boolean) {
|
||||||
|
fun AbstractKotlinCompile<*>.configureAction() {
|
||||||
|
source(sourceSet.kotlin)
|
||||||
|
sourceFilesExtensions(sourceSet.customSourceFilesExtensions)
|
||||||
|
if (addAsCommonSources) {
|
||||||
|
commonSourceSet += sourceSet.kotlin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note! Invocation of withType-all results in preliminary task instantiation.
|
||||||
|
// After fix of this issue the following code should be uncommented:
|
||||||
|
// if (useLazyTaskConfiguration) {
|
||||||
|
// (target.project.tasks.named(compileKotlinTaskName) as TaskProvider<AbstractKotlinCompile<*>>).configure {
|
||||||
|
// it.configureAction()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
target.project.tasks
|
||||||
|
// To configure a task that may have not yet been created at this point, use 'withType-matching-all`:
|
||||||
|
.withType(AbstractKotlinCompile::class.java)
|
||||||
|
.matching { it.name == compileKotlinTaskName }
|
||||||
|
.all { compileKotlinTask ->
|
||||||
|
compileKotlinTask.configureAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun source(sourceSet: KotlinSourceSet) {
|
||||||
|
if (kotlinSourceSets.add(sourceSet)) {
|
||||||
|
//TODO possibly issue with forced instantiation
|
||||||
|
target.project.whenEvaluated {
|
||||||
|
sourceSet.getSourceSetHierarchy().forEach { sourceSet ->
|
||||||
|
val isCommonSource =
|
||||||
|
CompilationSourceSetUtil.sourceSetsInMultipleCompilations(project)?.contains(sourceSet) ?: false
|
||||||
|
|
||||||
|
addSourcesToCompileTask(sourceSet, addAsCommonSources = isCommonSource)
|
||||||
|
|
||||||
|
// Use `forced = false` since `api`, `implementation`, and `compileOnly` may be missing in some cases like
|
||||||
|
// old Java & Android projects:
|
||||||
|
addExtendsFromRelation(apiConfigurationName, sourceSet.apiConfigurationName, forced = false)
|
||||||
|
addExtendsFromRelation(implementationConfigurationName, sourceSet.implementationConfigurationName, forced = false)
|
||||||
|
addExtendsFromRelation(compileOnlyConfigurationName, sourceSet.compileOnlyConfigurationName, forced = false)
|
||||||
|
|
||||||
|
if (this@AbstractKotlinCompilation is KotlinCompilationToRunnableFiles<*>) {
|
||||||
|
addExtendsFromRelation(runtimeOnlyConfigurationName, sourceSet.runtimeOnlyConfigurationName, forced = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceSet.name != defaultSourceSetName) {
|
||||||
|
kotlinExtension.sourceSets.findByName(defaultSourceSetName)?.let { defaultSourceSet ->
|
||||||
|
// Temporary solution for checking consistency across source sets participating in a compilation that may
|
||||||
|
// not be interconnected with the dependsOn relation: check the settings as if the default source set of
|
||||||
|
// the compilation depends on the one added to the compilation:
|
||||||
|
defaultSourceSetLanguageSettingsChecker.runAllChecks(
|
||||||
|
defaultSourceSet,
|
||||||
|
sourceSet
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }.orEmpty(),
|
||||||
|
"compileClasspath"
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileKotlinTaskName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
"compile",
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
"Kotlin",
|
||||||
|
target.targetName
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "classes")
|
||||||
|
|
||||||
|
override lateinit var compileDependencyFiles: FileCollection
|
||||||
|
|
||||||
|
override val apiConfigurationName: String
|
||||||
|
get() = disambiguateName("api")
|
||||||
|
|
||||||
|
override val implementationConfigurationName: String
|
||||||
|
get() = disambiguateName("implementation")
|
||||||
|
|
||||||
|
override val compileOnlyConfigurationName: String
|
||||||
|
get() = disambiguateName("compileOnly")
|
||||||
|
|
||||||
|
override val runtimeOnlyConfigurationName: String
|
||||||
|
get() = disambiguateName("runtimeOnly")
|
||||||
|
|
||||||
|
override fun dependencies(configure: KotlinDependencyHandler.() -> Unit): Unit =
|
||||||
|
DefaultKotlinDependencyHandler(this, target.project).run(configure)
|
||||||
|
|
||||||
|
override fun dependencies(configureClosure: Closure<Any?>) =
|
||||||
|
dependencies f@{ ConfigureUtil.configure(configureClosure, this@f) }
|
||||||
|
|
||||||
|
override fun toString(): String = "compilation '$compilationName' ($target)"
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AbstractKotlinCompilationToRunnableFiles<T : KotlinCommonOptions>(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<T>(target, name), KotlinCompilationToRunnableFiles<T> {
|
||||||
|
override val runtimeDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
"runtimeClasspath"
|
||||||
|
)
|
||||||
|
|
||||||
|
override lateinit var runtimeDependencyFiles: FileCollection
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KotlinCompilation<*>.disambiguateName(simpleName: String): String {
|
||||||
|
return lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
simpleName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
open class KotlinJvmCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJvmOptions>(target, name), KotlinCompilationWithResources<KotlinJvmOptions> {
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
override val compileKotlinTask: org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
get() = super.compileKotlinTask as org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinWithJavaCompilation<KotlinOptionsType : KotlinCommonOptions>(
|
||||||
|
target: KotlinWithJavaTarget<KotlinOptionsType>,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinOptionsType>(target, name), KotlinCompilationWithResources<KotlinOptionsType> {
|
||||||
|
lateinit var javaSourceSet: SourceSet
|
||||||
|
|
||||||
|
override val output: KotlinCompilationOutput by lazy { KotlinWithJavaCompilationOutput(this) }
|
||||||
|
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = javaSourceSet.processResourcesTaskName
|
||||||
|
|
||||||
|
override var runtimeDependencyFiles: FileCollection
|
||||||
|
get() = javaSourceSet.runtimeClasspath
|
||||||
|
set(value) {
|
||||||
|
javaSourceSet.runtimeClasspath = value
|
||||||
|
}
|
||||||
|
|
||||||
|
override val runtimeDependencyConfigurationName: String
|
||||||
|
get() = javaSourceSet.runtimeClasspathConfigurationName
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = javaSourceSet.compileClasspathConfigurationName
|
||||||
|
|
||||||
|
override val runtimeOnlyConfigurationName: String
|
||||||
|
get() = javaSourceSet.runtimeOnlyConfigurationName
|
||||||
|
|
||||||
|
override val implementationConfigurationName: String
|
||||||
|
get() = javaSourceSet.implementationConfigurationName
|
||||||
|
|
||||||
|
override val apiConfigurationName: String
|
||||||
|
get() = javaSourceSet.apiConfigurationName
|
||||||
|
|
||||||
|
override val compileOnlyConfigurationName: String
|
||||||
|
get() = javaSourceSet.compileOnlyConfigurationName
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = javaSourceSet.classesTaskName
|
||||||
|
|
||||||
|
override var compileDependencyFiles: FileCollection
|
||||||
|
get() = javaSourceSet.compileClasspath
|
||||||
|
set(value) {
|
||||||
|
javaSourceSet.compileClasspath = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun source(javaSourceSet: SourceSet) {
|
||||||
|
with(target.project) {
|
||||||
|
afterEvaluate {
|
||||||
|
(tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>).source(javaSourceSet.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmAndroidCompilation(
|
||||||
|
target: KotlinAndroidTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJvmOptions>(target, name) {
|
||||||
|
override val compileKotlinTask: org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
get() = super.compileKotlinTask as org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
override val relatedConfigurationNames: List<String>
|
||||||
|
get() = super.relatedConfigurationNames + listOf("${name}ApiElements", "${name}RuntimeElements")
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJsOptions>(target, name), KotlinCompilationWithResources<KotlinJsOptions> {
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
override val compileKotlinTask: Kotlin2JsCompile
|
||||||
|
get() = super.compileKotlinTask as Kotlin2JsCompile
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinCommonCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<KotlinMultiplatformCommonOptions>(target, name) {
|
||||||
|
override val compileKotlinTask: KotlinCompileCommon
|
||||||
|
get() = super.compileKotlinTask as KotlinCompileCommon
|
||||||
|
|
||||||
|
// TODO once we properly compile metadata for each source set, the default source sets will likely become just the source sets
|
||||||
|
// which are transformed to metadata
|
||||||
|
private val commonSourceSetName = when (compilationName) {
|
||||||
|
KotlinCompilation.MAIN_COMPILATION_NAME -> KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME
|
||||||
|
else -> error("Custom metadata compilations are not supported yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
override val defaultSourceSet: KotlinSourceSet
|
||||||
|
get() = target.project.kotlinExtension.sourceSets.getByName(commonSourceSetName)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeCompilation(
|
||||||
|
override val target: KotlinNativeTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<KotlinCommonOptions>(target, name), KotlinCompilationWithResources<KotlinCommonOptions> {
|
||||||
|
|
||||||
|
override val kotlinOptions: KotlinCommonOptions
|
||||||
|
get() = compileKotlinTask.kotlinOptions
|
||||||
|
|
||||||
|
override val compileKotlinTask: KotlinNativeCompile
|
||||||
|
get() = super.compileKotlinTask as KotlinNativeCompile
|
||||||
|
|
||||||
|
private val project: Project
|
||||||
|
get() = target.project
|
||||||
|
|
||||||
|
// A collection containing all source sets used by this compilation
|
||||||
|
// (taking into account dependencies between source sets). Used by both compilation
|
||||||
|
// and linking tasks. Unlike kotlinSourceSets, includes dependency source sets.
|
||||||
|
// TODO: Move into the compilation task when the linking task does klib linking instead of compilation.
|
||||||
|
internal val allSources: MutableSet<SourceDirectorySet> = mutableSetOf()
|
||||||
|
|
||||||
|
// TODO: Move into the compilation task when the linking task does klib linking instead of compilation.
|
||||||
|
internal val commonSources: MutableSet<SourceDirectorySet> = mutableSetOf()
|
||||||
|
|
||||||
|
var isTestCompilation = false
|
||||||
|
|
||||||
|
var friendCompilationName: String? = null
|
||||||
|
|
||||||
|
internal val friendCompilation: KotlinNativeCompilation?
|
||||||
|
get() = friendCompilationName?.let {
|
||||||
|
target.compilations.getByName(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used only to support the old APIs. TODO: Remove when the old APIs are removed.
|
||||||
|
internal val binaries = mutableMapOf<Pair<NativeOutputKind, NativeBuildType>, NativeBinary>()
|
||||||
|
|
||||||
|
// Native-specific DSL.
|
||||||
|
var extraOpts = mutableListOf<String>()
|
||||||
|
|
||||||
|
fun extraOpts(vararg values: Any) = extraOpts(values.toList())
|
||||||
|
fun extraOpts(values: List<Any>) {
|
||||||
|
extraOpts.addAll(values.map { it.toString() })
|
||||||
|
}
|
||||||
|
|
||||||
|
var buildTypes = mutableListOf<NativeBuildType>()
|
||||||
|
var outputKinds = mutableListOf<NativeOutputKind>()
|
||||||
|
|
||||||
|
fun outputKind(kind: NativeOutputKind) = outputKinds.add(kind)
|
||||||
|
|
||||||
|
fun outputKinds(vararg kinds: NativeOutputKind) {
|
||||||
|
outputKinds = kinds.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun outputKinds(vararg kinds: String) {
|
||||||
|
outputKinds = kinds.map { NativeOutputKind.valueOf(it.toUpperCase()) }.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun outputKinds(kinds: List<Any>) {
|
||||||
|
outputKinds = kinds.map {
|
||||||
|
when (it) {
|
||||||
|
is NativeOutputKind -> it
|
||||||
|
is String -> NativeOutputKind.valueOf(it.toUpperCase())
|
||||||
|
else -> error("Cannot use $it as an output kind")
|
||||||
|
}
|
||||||
|
}.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
var entryPoint: String? = null
|
||||||
|
fun entryPoint(value: String) {
|
||||||
|
entryPoint = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interop DSL.
|
||||||
|
val cinterops = project.container(DefaultCInteropSettings::class.java) { cinteropName ->
|
||||||
|
DefaultCInteropSettings(project, cinteropName, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
var linkerOpts = mutableListOf<String>()
|
||||||
|
|
||||||
|
fun cinterops(action: NamedDomainObjectContainer<DefaultCInteropSettings>.() -> Unit) = cinterops.action()
|
||||||
|
fun cinterops(action: Closure<Unit>) = cinterops(ConfigureUtil.configureUsing(action))
|
||||||
|
fun cinterops(action: Action<NamedDomainObjectContainer<DefaultCInteropSettings>>) = action.execute(cinterops)
|
||||||
|
|
||||||
|
fun linkerOpts(vararg values: String) = linkerOpts(values.toList())
|
||||||
|
fun linkerOpts(values: List<String>) {
|
||||||
|
linkerOpts.addAll(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Task accessors.
|
||||||
|
fun findLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeLink? = binaries[kind to buildType]?.linkTask
|
||||||
|
|
||||||
|
fun getLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeLink =
|
||||||
|
findLinkTask(kind, buildType)
|
||||||
|
?: throw IllegalArgumentException("Cannot find a link task for the binary kind '$kind' and the build type '$buildType'")
|
||||||
|
|
||||||
|
fun findLinkTask(kind: String, buildType: String) =
|
||||||
|
findLinkTask(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun getLinkTask(kind: String, buildType: String) =
|
||||||
|
getLinkTask(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun findBinary(kind: NativeOutputKind, buildType: NativeBuildType): File? = findLinkTask(kind, buildType)?.outputFile?.get()
|
||||||
|
|
||||||
|
fun getBinary(kind: NativeOutputKind, buildType: NativeBuildType): File = getLinkTask(kind, buildType).outputFile.get()
|
||||||
|
|
||||||
|
fun findBinary(kind: String, buildType: String) =
|
||||||
|
findBinary(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun getBinary(kind: String, buildType: String) =
|
||||||
|
getBinary(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
// Naming
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
fun linkTaskName(kind: NativeOutputKind, buildType: NativeBuildType): String =
|
||||||
|
lowerCamelCaseName(
|
||||||
|
"link",
|
||||||
|
KotlinNativeBinaryContainer.generateBinaryName(compilationName, buildType, kind.taskNameClassifier),
|
||||||
|
target.targetName
|
||||||
|
)
|
||||||
|
|
||||||
|
fun linkTaskName(kind: String, buildType: String) =
|
||||||
|
linkTaskName(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }.orEmpty(),
|
||||||
|
"compileKlibraries"
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "klibrary")
|
||||||
|
|
||||||
|
val binariesTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "binaries")
|
||||||
|
|
||||||
|
override fun addSourcesToCompileTask(sourceSet: KotlinSourceSet, addAsCommonSources: Boolean) {
|
||||||
|
allSources.add(sourceSet.kotlin)
|
||||||
|
if (addAsCommonSources) {
|
||||||
|
commonSources.add(sourceSet.kotlin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private object CompilationSourceSetUtil {
|
||||||
|
// Cache the results per project
|
||||||
|
private val projectSourceSetsInMultipleCompilationsCache = WeakHashMap<Project, Set<KotlinSourceSet>>()
|
||||||
|
|
||||||
|
fun sourceSetsInMultipleCompilations(project: Project) =
|
||||||
|
projectSourceSetsInMultipleCompilationsCache.computeIfAbsent(project) { _ ->
|
||||||
|
check(project.state.executed) { "Should only be computed after the project is evaluated" }
|
||||||
|
|
||||||
|
val compilations = (project.kotlinExtension as? KotlinMultiplatformExtension)?.targets?.flatMap { it.compilations }
|
||||||
|
?: return@computeIfAbsent null
|
||||||
|
|
||||||
|
compilations
|
||||||
|
.flatMap { compilation -> compilation.allKotlinSourceSets.map { sourceSet -> compilation to sourceSet } }
|
||||||
|
.groupingBy { (_, sourceSet) -> sourceSet }
|
||||||
|
.eachCount()
|
||||||
|
.filterValues { it > 1 }
|
||||||
|
.keys
|
||||||
|
}
|
||||||
|
}
|
||||||
+93
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.NamedDomainObjectFactory
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
|
|
||||||
|
interface KotlinCompilationFactory<T : KotlinCompilation<*>> : NamedDomainObjectFactory<T> {
|
||||||
|
val itemClass: Class<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinCommonCompilationFactory(
|
||||||
|
val target: KotlinOnlyTarget<KotlinCommonCompilation>
|
||||||
|
) : KotlinCompilationFactory<KotlinCommonCompilation> {
|
||||||
|
override val itemClass: Class<KotlinCommonCompilation>
|
||||||
|
get() = KotlinCommonCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinCommonCompilation =
|
||||||
|
KotlinCommonCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmCompilationFactory(
|
||||||
|
val target: KotlinOnlyTarget<KotlinJvmCompilation>
|
||||||
|
) : KotlinCompilationFactory<KotlinJvmCompilation> {
|
||||||
|
override val itemClass: Class<KotlinJvmCompilation>
|
||||||
|
get() = KotlinJvmCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinJvmCompilation =
|
||||||
|
KotlinJvmCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinWithJavaCompilationFactory<KotlinOptionsType : KotlinCommonOptions>(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinWithJavaTarget<KotlinOptionsType>
|
||||||
|
) : KotlinCompilationFactory<KotlinWithJavaCompilation<KotlinOptionsType>> {
|
||||||
|
|
||||||
|
override val itemClass: Class<KotlinWithJavaCompilation<KotlinOptionsType>>
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
get() = KotlinWithJavaCompilation::class.java as Class<KotlinWithJavaCompilation<KotlinOptionsType>>
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinWithJavaCompilation<KotlinOptionsType> {
|
||||||
|
val result = KotlinWithJavaCompilation(target, name)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmAndroidCompilationFactory(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinAndroidTarget
|
||||||
|
) : KotlinCompilationFactory<KotlinJvmAndroidCompilation> {
|
||||||
|
|
||||||
|
override val itemClass: Class<KotlinJvmAndroidCompilation>
|
||||||
|
get() = KotlinJvmAndroidCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinJvmAndroidCompilation =
|
||||||
|
KotlinJvmAndroidCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsCompilationFactory(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinOnlyTarget<KotlinJsCompilation>
|
||||||
|
) : KotlinCompilationFactory<KotlinJsCompilation> {
|
||||||
|
override val itemClass: Class<KotlinJsCompilation>
|
||||||
|
get() = KotlinJsCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinJsCompilation =
|
||||||
|
KotlinJsCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeCompilationFactory(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinNativeTarget
|
||||||
|
) : KotlinCompilationFactory<KotlinNativeCompilation> {
|
||||||
|
|
||||||
|
override val itemClass: Class<KotlinNativeCompilation>
|
||||||
|
get() = KotlinNativeCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinNativeCompilation =
|
||||||
|
KotlinNativeCompilation(target, name).apply {
|
||||||
|
if (name == KotlinCompilation.TEST_COMPILATION_NAME) {
|
||||||
|
friendCompilationName = KotlinCompilation.MAIN_COMPILATION_NAME
|
||||||
|
isTestCompilation = true
|
||||||
|
}
|
||||||
|
buildTypes = mutableListOf(NativeBuildType.DEBUG, NativeBuildType.RELEASE)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+330
@@ -0,0 +1,330 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.artifacts.Dependency
|
||||||
|
import org.gradle.api.internal.file.FileResolver
|
||||||
|
import org.gradle.api.plugins.JavaPlugin
|
||||||
|
import org.gradle.internal.reflect.Instantiator
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.KotlinNativeProjectProperty
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.hasProperty
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.konanHome
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinTask
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
|
||||||
|
import org.jetbrains.kotlin.konan.KonanVersion
|
||||||
|
import org.jetbrains.kotlin.konan.target.HostManager
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
abstract class KotlinOnlyTargetPreset<T : KotlinCompilation<*>>(
|
||||||
|
protected val project: Project,
|
||||||
|
private val instantiator: Instantiator,
|
||||||
|
private val fileResolver: FileResolver,
|
||||||
|
protected val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinOnlyTarget<T>> {
|
||||||
|
|
||||||
|
protected open fun createKotlinTargetConfigurator(): KotlinTargetConfigurator<T> =
|
||||||
|
KotlinTargetConfigurator(createDefaultSourceSets = true, createTestCompilation = true)
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinOnlyTarget<T> {
|
||||||
|
val result = KotlinOnlyTarget<T>(project, platformType).apply {
|
||||||
|
targetName = name
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinOnlyTargetPreset
|
||||||
|
|
||||||
|
val compilationFactory = createCompilationFactory(this)
|
||||||
|
compilations = project.container(compilationFactory.itemClass, compilationFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
createKotlinTargetConfigurator().configureTarget(result)
|
||||||
|
|
||||||
|
result.compilations.all { compilation ->
|
||||||
|
buildCompilationProcessor(compilation).run()
|
||||||
|
if (compilation.name == KotlinCompilation.MAIN_COMPILATION_NAME) {
|
||||||
|
sourcesJarTask(compilation, result.targetName, result.targetName.toLowerCase())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun createCompilationFactory(forTarget: KotlinOnlyTarget<T>): KotlinCompilationFactory<T>
|
||||||
|
protected abstract val platformType: KotlinPlatformType
|
||||||
|
internal abstract fun buildCompilationProcessor(compilation: T): KotlinSourceSetProcessor<*>
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinMetadataTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinCommonCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(
|
||||||
|
forTarget: KotlinOnlyTarget<KotlinCommonCompilation>
|
||||||
|
): KotlinCompilationFactory<KotlinCommonCompilation> =
|
||||||
|
KotlinCommonCompilationFactory(forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.common
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinCommonCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return KotlinCommonSourceSetProcessor(project, compilation, tasksProvider, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "metadata"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createKotlinTargetConfigurator(): KotlinTargetConfigurator<KotlinCommonCompilation> =
|
||||||
|
KotlinTargetConfigurator(createDefaultSourceSets = false, createTestCompilation = false)
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinOnlyTarget<KotlinCommonCompilation> =
|
||||||
|
super.createTarget(name).apply {
|
||||||
|
val mainCompilation = compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
val commonMainSourceSet = project.kotlinExtension.sourceSets.getByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
||||||
|
|
||||||
|
mainCompilation.source(commonMainSourceSet)
|
||||||
|
|
||||||
|
project.afterEvaluate {
|
||||||
|
// Since there's no default source set, apply language settings from commonMain:
|
||||||
|
val compileKotlinMetadata = project.tasks.getByName(mainCompilation.compileKotlinTaskName) as KotlinCompile<*>
|
||||||
|
applyLanguageSettingsToKotlinTask(commonMainSourceSet.languageSettings, compileKotlinMetadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinJvmCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinJvmCompilation>): KotlinCompilationFactory<KotlinJvmCompilation> =
|
||||||
|
KotlinJvmCompilationFactory(forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.jvm
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinJvmCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return Kotlin2JvmSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "jvm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinJsCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinJsCompilation>) =
|
||||||
|
KotlinJsCompilationFactory(project, forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.js
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinJsCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return Kotlin2JsSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinAndroidTargetPreset(
|
||||||
|
private val project: Project,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinAndroidTarget> {
|
||||||
|
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinAndroidTarget {
|
||||||
|
val result = KotlinAndroidTarget(name, project).apply {
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinAndroidTargetPreset
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinAndroidPlugin.applyToTarget(kotlinPluginVersion, result)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "android"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmWithJavaTargetPreset(
|
||||||
|
private val project: Project,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinWithJavaTarget<KotlinJvmOptions>> {
|
||||||
|
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinWithJavaTarget<KotlinJvmOptions> {
|
||||||
|
project.plugins.apply(JavaPlugin::class.java)
|
||||||
|
|
||||||
|
val target = KotlinWithJavaTarget<KotlinJvmOptions>(project, KotlinPlatformType.jvm, name).apply {
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinJvmWithJavaTargetPreset
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractKotlinPlugin.configureTarget(target) { compilation ->
|
||||||
|
Kotlin2JvmSourceSetProcessor(project, KotlinTasksProvider(name), compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
target.compilations.getByName("test").run {
|
||||||
|
val main = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
|
||||||
|
compileDependencyFiles = project.files(
|
||||||
|
main.output.allOutputs,
|
||||||
|
project.configurations.maybeCreate(compileDependencyConfigurationName)
|
||||||
|
)
|
||||||
|
runtimeDependencyFiles = project.files(
|
||||||
|
output.allOutputs,
|
||||||
|
main.output.allOutputs,
|
||||||
|
project.configurations.maybeCreate(runtimeDependencyConfigurationName)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "jvmWithJava"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeTargetPreset(
|
||||||
|
private val name: String,
|
||||||
|
val project: Project,
|
||||||
|
val konanTarget: KonanTarget,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinNativeTarget> {
|
||||||
|
|
||||||
|
init {
|
||||||
|
// This is required to obtain Kotlin/Native home in CLion plugin:
|
||||||
|
setupNativeHomePrivateProperty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName(): String = name
|
||||||
|
|
||||||
|
private fun setupNativeHomePrivateProperty() = with(project) {
|
||||||
|
if (!hasProperty(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY))
|
||||||
|
extensions.extraProperties.set(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY, konanHome)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupNativeCompiler() = with(project) {
|
||||||
|
if (!hasProperty(KotlinNativeProjectProperty.KONAN_HOME_OVERRIDE)) {
|
||||||
|
NativeCompilerDownloader(this).downloadIfNeeded()
|
||||||
|
logger.info("Kotlin/Native distribution: $konanHome")
|
||||||
|
} else {
|
||||||
|
logger.info("User-provided Kotlin/Native distribution: $konanHome")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We declare default K/N dependencies as files to avoid searching them in remote repos (see KT-28128).
|
||||||
|
private fun defaultLibs(target: KonanTarget? = null): List<Dependency> = with(project) {
|
||||||
|
|
||||||
|
val relPath = if (target != null) "platform/${target.name}" else "common"
|
||||||
|
|
||||||
|
file("$konanHome/klib/$relPath")
|
||||||
|
.listFiles { file -> file.isDirectory }
|
||||||
|
?.sortedBy { dir -> dir.name.toLowerCase() }
|
||||||
|
?.map { dir -> dependencies.create(files(dir)) } ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinNativeTarget {
|
||||||
|
setupNativeCompiler()
|
||||||
|
|
||||||
|
val result = KotlinNativeTarget(project, konanTarget).apply {
|
||||||
|
targetName = name
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinNativeTargetPreset
|
||||||
|
|
||||||
|
val compilationFactory = KotlinNativeCompilationFactory(project, this)
|
||||||
|
compilations = project.container(compilationFactory.itemClass, compilationFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinNativeTargetConfigurator(kotlinPluginVersion).configureTarget(result)
|
||||||
|
|
||||||
|
// Allow IDE to resolve the libraries provided by the compiler by adding them into dependencies.
|
||||||
|
result.compilations.all { compilation ->
|
||||||
|
val target = compilation.target.konanTarget
|
||||||
|
// First, put common libs:
|
||||||
|
defaultLibs().forEach {
|
||||||
|
project.dependencies.add(compilation.compileDependencyConfigurationName, it)
|
||||||
|
}
|
||||||
|
// Then, platform-specific libs:
|
||||||
|
defaultLibs(target).forEach {
|
||||||
|
project.dependencies.add(compilation.compileDependencyConfigurationName, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!konanTarget.enabledOnCurrentHost) {
|
||||||
|
with(HostManager()) {
|
||||||
|
val supportedHosts = enabledTargetsByHost.filterValues { konanTarget in it }.keys
|
||||||
|
val supportedHostsString =
|
||||||
|
if (supportedHosts.size == 1)
|
||||||
|
"a ${supportedHosts.single()} host" else
|
||||||
|
"one of the host platforms: ${supportedHosts.joinToString(", ")}"
|
||||||
|
project.logger.warn(
|
||||||
|
"Target '$name' for platform ${konanTarget} is ignored during build on this ${HostManager.host} machine. " +
|
||||||
|
"You can build it with $supportedHostsString."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY = "konanHome"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val KonanTarget.isCurrentHost: Boolean
|
||||||
|
get() = this == HostManager.host
|
||||||
|
|
||||||
|
internal val KonanTarget.enabledOnCurrentHost
|
||||||
|
get() = HostManager().isEnabled(this)
|
||||||
|
|
||||||
|
internal val KotlinNativeCompilation.isMainCompilation: Boolean
|
||||||
|
get() = name == KotlinCompilation.MAIN_COMPILATION_NAME
|
||||||
+330
@@ -0,0 +1,330 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.artifacts.Dependency
|
||||||
|
import org.gradle.api.internal.file.FileResolver
|
||||||
|
import org.gradle.api.plugins.JavaPlugin
|
||||||
|
import org.gradle.internal.reflect.Instantiator
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.KotlinNativeProjectProperty
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.hasProperty
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.konanHome
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinTask
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
|
||||||
|
import org.jetbrains.kotlin.konan.KonanVersion
|
||||||
|
import org.jetbrains.kotlin.konan.target.HostManager
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
abstract class KotlinOnlyTargetPreset<T : KotlinCompilation<*>>(
|
||||||
|
protected val project: Project,
|
||||||
|
private val instantiator: Instantiator,
|
||||||
|
private val fileResolver: FileResolver,
|
||||||
|
protected val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinOnlyTarget<T>> {
|
||||||
|
|
||||||
|
protected open fun createKotlinTargetConfigurator(): KotlinTargetConfigurator<T> =
|
||||||
|
KotlinTargetConfigurator(createDefaultSourceSets = true, createTestCompilation = true)
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinOnlyTarget<T> {
|
||||||
|
val result = KotlinOnlyTarget<T>(project, platformType).apply {
|
||||||
|
targetName = name
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinOnlyTargetPreset
|
||||||
|
|
||||||
|
val compilationFactory = createCompilationFactory(this)
|
||||||
|
compilations = project.container(compilationFactory.itemClass, compilationFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
createKotlinTargetConfigurator().configureTarget(result)
|
||||||
|
|
||||||
|
result.compilations.all { compilation ->
|
||||||
|
buildCompilationProcessor(compilation).run()
|
||||||
|
if (compilation.name == KotlinCompilation.MAIN_COMPILATION_NAME) {
|
||||||
|
sourcesJarTask(compilation, result.targetName, result.targetName.toLowerCase())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun createCompilationFactory(forTarget: KotlinOnlyTarget<T>): KotlinCompilationFactory<T>
|
||||||
|
protected abstract val platformType: KotlinPlatformType
|
||||||
|
internal abstract fun buildCompilationProcessor(compilation: T): KotlinSourceSetProcessor<*>
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinMetadataTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinCommonCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(
|
||||||
|
forTarget: KotlinOnlyTarget<KotlinCommonCompilation>
|
||||||
|
): KotlinCompilationFactory<KotlinCommonCompilation> =
|
||||||
|
KotlinCommonCompilationFactory(forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.common
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinCommonCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return KotlinCommonSourceSetProcessor(project, compilation, tasksProvider, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "metadata"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createKotlinTargetConfigurator(): KotlinTargetConfigurator<KotlinCommonCompilation> =
|
||||||
|
KotlinTargetConfigurator(createDefaultSourceSets = false, createTestCompilation = false)
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinOnlyTarget<KotlinCommonCompilation> =
|
||||||
|
super.createTarget(name).apply {
|
||||||
|
val mainCompilation = compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
val commonMainSourceSet = project.kotlinExtension.sourceSets.getByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
||||||
|
|
||||||
|
mainCompilation.source(commonMainSourceSet)
|
||||||
|
|
||||||
|
project.afterEvaluate {
|
||||||
|
// Since there's no default source set, apply language settings from commonMain:
|
||||||
|
val compileKotlinMetadata = project.tasks.getByName(mainCompilation.compileKotlinTaskName) as KotlinCompile<*>
|
||||||
|
applyLanguageSettingsToKotlinTask(commonMainSourceSet.languageSettings, compileKotlinMetadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinJvmCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinJvmCompilation>): KotlinCompilationFactory<KotlinJvmCompilation> =
|
||||||
|
KotlinJvmCompilationFactory(forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.jvm
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinJvmCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return Kotlin2JvmSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "jvm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinJsCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinJsCompilation>) =
|
||||||
|
KotlinJsCompilationFactory(project, forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.js
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinJsCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return Kotlin2JsSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinAndroidTargetPreset(
|
||||||
|
private val project: Project,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinAndroidTarget> {
|
||||||
|
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinAndroidTarget {
|
||||||
|
val result = KotlinAndroidTarget(name, project).apply {
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinAndroidTargetPreset
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinAndroidPlugin.applyToTarget(kotlinPluginVersion, result)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "android"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmWithJavaTargetPreset(
|
||||||
|
private val project: Project,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinWithJavaTarget<KotlinJvmOptions>> {
|
||||||
|
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinWithJavaTarget<KotlinJvmOptions> {
|
||||||
|
project.plugins.apply(JavaPlugin::class.java)
|
||||||
|
|
||||||
|
val target = KotlinWithJavaTarget<KotlinJvmOptions>(project, KotlinPlatformType.jvm, name).apply {
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinJvmWithJavaTargetPreset
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractKotlinPlugin.configureTarget(target) { compilation ->
|
||||||
|
Kotlin2JvmSourceSetProcessor(project, KotlinTasksProvider(name), compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
target.compilations.getByName("test").run {
|
||||||
|
val main = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
|
||||||
|
compileDependencyFiles = project.files(
|
||||||
|
main.output.allOutputs,
|
||||||
|
project.configurations.maybeCreate(compileDependencyConfigurationName)
|
||||||
|
)
|
||||||
|
runtimeDependencyFiles = project.files(
|
||||||
|
output.allOutputs,
|
||||||
|
main.output.allOutputs,
|
||||||
|
project.configurations.maybeCreate(runtimeDependencyConfigurationName)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "jvmWithJava"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeTargetPreset(
|
||||||
|
private val name: String,
|
||||||
|
val project: Project,
|
||||||
|
val konanTarget: KonanTarget,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinNativeTarget> {
|
||||||
|
|
||||||
|
init {
|
||||||
|
// This is required to obtain Kotlin/Native home in CLion plugin:
|
||||||
|
setupNativeHomePrivateProperty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName(): String = name
|
||||||
|
|
||||||
|
private fun setupNativeHomePrivateProperty() = with(project) {
|
||||||
|
if (!hasProperty(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY))
|
||||||
|
extensions.extraProperties.set(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY, konanHome)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupNativeCompiler() = with(project) {
|
||||||
|
if (!hasProperty(KotlinNativeProjectProperty.KONAN_HOME_OVERRIDE)) {
|
||||||
|
NativeCompilerDownloader(this).downloadIfNeeded()
|
||||||
|
logger.info("Kotlin/Native distribution: $konanHome")
|
||||||
|
} else {
|
||||||
|
logger.info("User-provided Kotlin/Native distribution: $konanHome")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We declare default K/N dependencies as files to avoid searching them in remote repos (see KT-28128).
|
||||||
|
private fun defaultLibs(target: KonanTarget? = null): List<Dependency> = with(project) {
|
||||||
|
|
||||||
|
val relPath = if (target != null) "platform/${target.name}" else "common"
|
||||||
|
|
||||||
|
file("$konanHome/klib/$relPath")
|
||||||
|
.listFiles { file -> file.isDirectory }
|
||||||
|
?.sortedBy { dir -> dir.name.toLowerCase() }
|
||||||
|
?.map { dir -> dependencies.create(files(dir)) } ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinNativeTarget {
|
||||||
|
setupNativeCompiler()
|
||||||
|
|
||||||
|
val result = KotlinNativeTarget(project, konanTarget).apply {
|
||||||
|
targetName = name
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinNativeTargetPreset
|
||||||
|
|
||||||
|
val compilationFactory = KotlinNativeCompilationFactory(project, this)
|
||||||
|
compilations = project.container(compilationFactory.itemClass, compilationFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinNativeTargetConfigurator(kotlinPluginVersion).configureTarget(result)
|
||||||
|
|
||||||
|
// Allow IDE to resolve the libraries provided by the compiler by adding them into dependencies.
|
||||||
|
result.compilations.all { compilation ->
|
||||||
|
val target = compilation.target.konanTarget
|
||||||
|
// First, put common libs:
|
||||||
|
defaultLibs().forEach {
|
||||||
|
project.dependencies.add(compilation.compileDependencyConfigurationName, it)
|
||||||
|
}
|
||||||
|
// Then, platform-specific libs:
|
||||||
|
defaultLibs(target).forEach {
|
||||||
|
project.dependencies.add(compilation.compileDependencyConfigurationName, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!konanTarget.enabledOnCurrentHost) {
|
||||||
|
with(HostManager()) {
|
||||||
|
val supportedHosts = enabledTargetsByHost.filterValues { konanTarget in it }.keys
|
||||||
|
val supportedHostsString =
|
||||||
|
if (supportedHosts.size == 1)
|
||||||
|
"a ${supportedHosts.single()} host" else
|
||||||
|
"one of the host platforms: ${supportedHosts.joinToString(", ")}"
|
||||||
|
project.logger.warn(
|
||||||
|
"Target '$name' for platform ${konanTarget} is ignored during build on this ${HostManager.host} machine. " +
|
||||||
|
"You can build it with $supportedHostsString."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY = "konanHome"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val KonanTarget.isCurrentHost: Boolean
|
||||||
|
get() = this == HostManager.host
|
||||||
|
|
||||||
|
internal val KonanTarget.enabledOnCurrentHost
|
||||||
|
get() = HostManager().isEnabled(this)
|
||||||
|
|
||||||
|
internal val KotlinNativeCompilation.isMainCompilation: Boolean
|
||||||
|
get() = name == KotlinCompilation.MAIN_COMPILATION_NAME
|
||||||
+330
@@ -0,0 +1,330 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.artifacts.Dependency
|
||||||
|
import org.gradle.api.internal.file.FileResolver
|
||||||
|
import org.gradle.api.plugins.JavaPlugin
|
||||||
|
import org.gradle.internal.reflect.Instantiator
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.KotlinNativeProjectProperty
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.hasProperty
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.konanHome
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinTask
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
|
||||||
|
import org.jetbrains.kotlin.konan.KonanVersion
|
||||||
|
import org.jetbrains.kotlin.konan.target.HostManager
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
abstract class KotlinOnlyTargetPreset<T : KotlinCompilation<*>>(
|
||||||
|
protected val project: Project,
|
||||||
|
private val instantiator: Instantiator,
|
||||||
|
private val fileResolver: FileResolver,
|
||||||
|
protected val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinOnlyTarget<T>> {
|
||||||
|
|
||||||
|
protected open fun createKotlinTargetConfigurator(): KotlinTargetConfigurator<T> =
|
||||||
|
KotlinTargetConfigurator(createDefaultSourceSets = true, createTestCompilation = true)
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinOnlyTarget<T> {
|
||||||
|
val result = KotlinOnlyTarget<T>(project, platformType).apply {
|
||||||
|
targetName = name
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinOnlyTargetPreset
|
||||||
|
|
||||||
|
val compilationFactory = createCompilationFactory(this)
|
||||||
|
compilations = project.container(compilationFactory.itemClass, compilationFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
createKotlinTargetConfigurator().configureTarget(result)
|
||||||
|
|
||||||
|
result.compilations.all { compilation ->
|
||||||
|
buildCompilationProcessor(compilation).run()
|
||||||
|
if (compilation.name == KotlinCompilation.MAIN_COMPILATION_NAME) {
|
||||||
|
sourcesJarTask(compilation, result.targetName, result.targetName.toLowerCase())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun createCompilationFactory(forTarget: KotlinOnlyTarget<T>): KotlinCompilationFactory<T>
|
||||||
|
protected abstract val platformType: KotlinPlatformType
|
||||||
|
internal abstract fun buildCompilationProcessor(compilation: T): KotlinSourceSetProcessor<*>
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinMetadataTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinCommonCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(
|
||||||
|
forTarget: KotlinOnlyTarget<KotlinCommonCompilation>
|
||||||
|
): KotlinCompilationFactory<KotlinCommonCompilation> =
|
||||||
|
KotlinCommonCompilationFactory(forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.common
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinCommonCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return KotlinCommonSourceSetProcessor(project, compilation, tasksProvider, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "metadata"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createKotlinTargetConfigurator(): KotlinTargetConfigurator<KotlinCommonCompilation> =
|
||||||
|
KotlinTargetConfigurator(createDefaultSourceSets = false, createTestCompilation = false)
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinOnlyTarget<KotlinCommonCompilation> =
|
||||||
|
super.createTarget(name).apply {
|
||||||
|
val mainCompilation = compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
val commonMainSourceSet = project.kotlinExtension.sourceSets.getByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
||||||
|
|
||||||
|
mainCompilation.source(commonMainSourceSet)
|
||||||
|
|
||||||
|
project.afterEvaluate {
|
||||||
|
// Since there's no default source set, apply language settings from commonMain:
|
||||||
|
val compileKotlinMetadata = project.tasks.getByName(mainCompilation.compileKotlinTaskName) as KotlinCompile<*>
|
||||||
|
applyLanguageSettingsToKotlinTask(commonMainSourceSet.languageSettings, compileKotlinMetadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinJvmCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinJvmCompilation>): KotlinCompilationFactory<KotlinJvmCompilation> =
|
||||||
|
KotlinJvmCompilationFactory(forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.jvm
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinJvmCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return Kotlin2JvmSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "jvm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinJsCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinJsCompilation>) =
|
||||||
|
KotlinJsCompilationFactory(project, forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.js
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinJsCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return Kotlin2JsSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinAndroidTargetPreset(
|
||||||
|
private val project: Project,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinAndroidTarget> {
|
||||||
|
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinAndroidTarget {
|
||||||
|
val result = KotlinAndroidTarget(name, project).apply {
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinAndroidTargetPreset
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinAndroidPlugin.applyToTarget(kotlinPluginVersion, result)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "android"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmWithJavaTargetPreset(
|
||||||
|
private val project: Project,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinWithJavaTarget<KotlinJvmOptions>> {
|
||||||
|
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinWithJavaTarget<KotlinJvmOptions> {
|
||||||
|
project.plugins.apply(JavaPlugin::class.java)
|
||||||
|
|
||||||
|
val target = KotlinWithJavaTarget<KotlinJvmOptions>(project, KotlinPlatformType.jvm, name).apply {
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinJvmWithJavaTargetPreset
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractKotlinPlugin.configureTarget(target) { compilation ->
|
||||||
|
Kotlin2JvmSourceSetProcessor(project, KotlinTasksProvider(name), compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
target.compilations.getByName("test").run {
|
||||||
|
val main = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
|
||||||
|
compileDependencyFiles = project.files(
|
||||||
|
main.output.allOutputs,
|
||||||
|
project.configurations.maybeCreate(compileDependencyConfigurationName)
|
||||||
|
)
|
||||||
|
runtimeDependencyFiles = project.files(
|
||||||
|
output.allOutputs,
|
||||||
|
main.output.allOutputs,
|
||||||
|
project.configurations.maybeCreate(runtimeDependencyConfigurationName)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "jvmWithJava"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeTargetPreset(
|
||||||
|
private val name: String,
|
||||||
|
val project: Project,
|
||||||
|
val konanTarget: KonanTarget,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinNativeTarget> {
|
||||||
|
|
||||||
|
init {
|
||||||
|
// This is required to obtain Kotlin/Native home in CLion plugin:
|
||||||
|
setupNativeHomePrivateProperty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName(): String = name
|
||||||
|
|
||||||
|
private fun setupNativeHomePrivateProperty() = with(project) {
|
||||||
|
if (!hasProperty(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY))
|
||||||
|
extensions.extraProperties.set(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY, konanHome)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupNativeCompiler() = with(project) {
|
||||||
|
if (!hasProperty(KotlinNativeProjectProperty.KONAN_HOME_OVERRIDE)) {
|
||||||
|
NativeCompilerDownloader(this).downloadIfNeeded()
|
||||||
|
logger.info("Kotlin/Native distribution: $konanHome")
|
||||||
|
} else {
|
||||||
|
logger.info("User-provided Kotlin/Native distribution: $konanHome")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We declare default K/N dependencies as files to avoid searching them in remote repos (see KT-28128).
|
||||||
|
private fun defaultLibs(target: KonanTarget? = null): List<Dependency> = with(project) {
|
||||||
|
|
||||||
|
val relPath = if (target != null) "platform/${target.name}" else "common"
|
||||||
|
|
||||||
|
file("$konanHome/klib/$relPath")
|
||||||
|
.listFiles { file -> file.isDirectory }
|
||||||
|
?.sortedBy { dir -> dir.name.toLowerCase() }
|
||||||
|
?.map { dir -> dependencies.create(files(dir)) } ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinNativeTarget {
|
||||||
|
setupNativeCompiler()
|
||||||
|
|
||||||
|
val result = KotlinNativeTarget(project, konanTarget).apply {
|
||||||
|
targetName = name
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinNativeTargetPreset
|
||||||
|
|
||||||
|
val compilationFactory = KotlinNativeCompilationFactory(project, this)
|
||||||
|
compilations = project.container(compilationFactory.itemClass, compilationFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinNativeTargetConfigurator(kotlinPluginVersion).configureTarget(result)
|
||||||
|
|
||||||
|
// Allow IDE to resolve the libraries provided by the compiler by adding them into dependencies.
|
||||||
|
result.compilations.all { compilation ->
|
||||||
|
val target = compilation.target.konanTarget
|
||||||
|
// First, put common libs:
|
||||||
|
defaultLibs().forEach {
|
||||||
|
project.dependencies.add(compilation.compileDependencyConfigurationName, it)
|
||||||
|
}
|
||||||
|
// Then, platform-specific libs:
|
||||||
|
defaultLibs(target).forEach {
|
||||||
|
project.dependencies.add(compilation.compileDependencyConfigurationName, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!konanTarget.enabledOnCurrentHost) {
|
||||||
|
with(HostManager()) {
|
||||||
|
val supportedHosts = enabledTargetsByHost.filterValues { konanTarget in it }.keys
|
||||||
|
val supportedHostsString =
|
||||||
|
if (supportedHosts.size == 1)
|
||||||
|
"a ${supportedHosts.single()} host" else
|
||||||
|
"one of the host platforms: ${supportedHosts.joinToString(", ")}"
|
||||||
|
project.logger.warn(
|
||||||
|
"Target '$name' for platform ${konanTarget} is ignored during build on this ${HostManager.host} machine. " +
|
||||||
|
"You can build it with $supportedHostsString."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY = "konanHome"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val KonanTarget.isCurrentHost: Boolean
|
||||||
|
get() = this == HostManager.host
|
||||||
|
|
||||||
|
internal val KonanTarget.enabledOnCurrentHost
|
||||||
|
get() = HostManager().isEnabled(this)
|
||||||
|
|
||||||
|
internal val KotlinNativeCompilation.isMainCompilation: Boolean
|
||||||
|
get() = name == KotlinCompilation.MAIN_COMPILATION_NAME
|
||||||
+471
@@ -0,0 +1,471 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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 groovy.lang.Closure
|
||||||
|
import org.gradle.api.Action
|
||||||
|
import org.gradle.api.NamedDomainObjectContainer
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.attributes.AttributeContainer
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.file.SourceDirectorySet
|
||||||
|
import org.gradle.api.tasks.SourceSet
|
||||||
|
import org.gradle.util.ConfigureUtil
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.*
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.defaultSourceSetLanguageSettingsChecker
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.getSourceSetHierarchy
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.*
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
|
internal fun KotlinCompilation<*>.composeName(prefix: String? = null, suffix: String? = null): String {
|
||||||
|
val compilationNamePart = compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }
|
||||||
|
val targetNamePart = target.disambiguationClassifier
|
||||||
|
|
||||||
|
return lowerCamelCaseName(prefix, targetNamePart, compilationNamePart, suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val KotlinCompilation<*>.defaultSourceSetName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName)
|
||||||
|
|
||||||
|
abstract class AbstractKotlinCompilation<T : KotlinCommonOptions>(
|
||||||
|
target: KotlinTarget,
|
||||||
|
override val compilationName: String
|
||||||
|
) : KotlinCompilation<T>, HasKotlinDependencies {
|
||||||
|
|
||||||
|
override val kotlinOptions: T
|
||||||
|
get() = compileKotlinTask.kotlinOptions
|
||||||
|
|
||||||
|
override fun kotlinOptions(configure: T.() -> Unit) =
|
||||||
|
configure(kotlinOptions)
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override val compileKotlinTask: KotlinCompile<T>
|
||||||
|
get() = (target.project.tasks.getByName(compileKotlinTaskName) as KotlinCompile<T>)
|
||||||
|
|
||||||
|
// Don't declare this property in the constructor to avoid NPE
|
||||||
|
// when an overriding property of a subclass is accessed instead.
|
||||||
|
override val target: KotlinTarget = target
|
||||||
|
|
||||||
|
private val attributeContainer = HierarchyAttributeContainer(target.attributes)
|
||||||
|
|
||||||
|
override fun getAttributes(): AttributeContainer = attributeContainer
|
||||||
|
|
||||||
|
override val kotlinSourceSets: MutableSet<KotlinSourceSet> = mutableSetOf()
|
||||||
|
|
||||||
|
override val allKotlinSourceSets: Set<KotlinSourceSet>
|
||||||
|
get() = kotlinSourceSets.flatMapTo(mutableSetOf()) { it.getSourceSetHierarchy() }
|
||||||
|
|
||||||
|
override val defaultSourceSet: KotlinSourceSet
|
||||||
|
get() = target.project.kotlinExtension.sourceSets.getByName(defaultSourceSetName)
|
||||||
|
|
||||||
|
override fun defaultSourceSet(configure: KotlinSourceSet.() -> Unit) =
|
||||||
|
configure(defaultSourceSet)
|
||||||
|
|
||||||
|
override val output: KotlinCompilationOutput by lazy {
|
||||||
|
DefaultKotlinCompilationOutput(
|
||||||
|
target.project,
|
||||||
|
Callable { target.project.buildDir.resolve("processedResources/${target.targetName}/$name") })
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun addSourcesToCompileTask(sourceSet: KotlinSourceSet, addAsCommonSources: Boolean) {
|
||||||
|
fun AbstractKotlinCompile<*>.configureAction() {
|
||||||
|
source(sourceSet.kotlin)
|
||||||
|
sourceFilesExtensions(sourceSet.customSourceFilesExtensions)
|
||||||
|
if (addAsCommonSources) {
|
||||||
|
commonSourceSet += sourceSet.kotlin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note! Invocation of withType-all results in preliminary task instantiation.
|
||||||
|
// After fix of this issue the following code should be uncommented:
|
||||||
|
// if (useLazyTaskConfiguration) {
|
||||||
|
// (target.project.tasks.named(compileKotlinTaskName) as TaskProvider<AbstractKotlinCompile<*>>).configure {
|
||||||
|
// it.configureAction()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
target.project.tasks
|
||||||
|
// To configure a task that may have not yet been created at this point, use 'withType-matching-all`:
|
||||||
|
.withType(AbstractKotlinCompile::class.java)
|
||||||
|
.matching { it.name == compileKotlinTaskName }
|
||||||
|
.all { compileKotlinTask ->
|
||||||
|
compileKotlinTask.configureAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun source(sourceSet: KotlinSourceSet) {
|
||||||
|
if (kotlinSourceSets.add(sourceSet)) {
|
||||||
|
//TODO possibly issue with forced instantiation
|
||||||
|
target.project.whenEvaluated {
|
||||||
|
sourceSet.getSourceSetHierarchy().forEach { sourceSet ->
|
||||||
|
val isCommonSource =
|
||||||
|
CompilationSourceSetUtil.sourceSetsInMultipleCompilations(project)?.contains(sourceSet) ?: false
|
||||||
|
|
||||||
|
addSourcesToCompileTask(sourceSet, addAsCommonSources = isCommonSource)
|
||||||
|
|
||||||
|
// Use `forced = false` since `api`, `implementation`, and `compileOnly` may be missing in some cases like
|
||||||
|
// old Java & Android projects:
|
||||||
|
addExtendsFromRelation(apiConfigurationName, sourceSet.apiConfigurationName, forced = false)
|
||||||
|
addExtendsFromRelation(implementationConfigurationName, sourceSet.implementationConfigurationName, forced = false)
|
||||||
|
addExtendsFromRelation(compileOnlyConfigurationName, sourceSet.compileOnlyConfigurationName, forced = false)
|
||||||
|
|
||||||
|
if (this@AbstractKotlinCompilation is KotlinCompilationToRunnableFiles<*>) {
|
||||||
|
addExtendsFromRelation(runtimeOnlyConfigurationName, sourceSet.runtimeOnlyConfigurationName, forced = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceSet.name != defaultSourceSetName) {
|
||||||
|
kotlinExtension.sourceSets.findByName(defaultSourceSetName)?.let { defaultSourceSet ->
|
||||||
|
// Temporary solution for checking consistency across source sets participating in a compilation that may
|
||||||
|
// not be interconnected with the dependsOn relation: check the settings as if the default source set of
|
||||||
|
// the compilation depends on the one added to the compilation:
|
||||||
|
defaultSourceSetLanguageSettingsChecker.runAllChecks(
|
||||||
|
defaultSourceSet,
|
||||||
|
sourceSet
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }.orEmpty(),
|
||||||
|
"compileClasspath"
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileKotlinTaskName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
"compile",
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
"Kotlin",
|
||||||
|
target.targetName
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "classes")
|
||||||
|
|
||||||
|
override lateinit var compileDependencyFiles: FileCollection
|
||||||
|
|
||||||
|
override val apiConfigurationName: String
|
||||||
|
get() = disambiguateName("api")
|
||||||
|
|
||||||
|
override val implementationConfigurationName: String
|
||||||
|
get() = disambiguateName("implementation")
|
||||||
|
|
||||||
|
override val compileOnlyConfigurationName: String
|
||||||
|
get() = disambiguateName("compileOnly")
|
||||||
|
|
||||||
|
override val runtimeOnlyConfigurationName: String
|
||||||
|
get() = disambiguateName("runtimeOnly")
|
||||||
|
|
||||||
|
override fun dependencies(configure: KotlinDependencyHandler.() -> Unit): Unit =
|
||||||
|
DefaultKotlinDependencyHandler(this, target.project).run(configure)
|
||||||
|
|
||||||
|
override fun dependencies(configureClosure: Closure<Any?>) =
|
||||||
|
dependencies f@{ ConfigureUtil.configure(configureClosure, this@f) }
|
||||||
|
|
||||||
|
override fun toString(): String = "compilation '$compilationName' ($target)"
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AbstractKotlinCompilationToRunnableFiles<T : KotlinCommonOptions>(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<T>(target, name), KotlinCompilationToRunnableFiles<T> {
|
||||||
|
override val runtimeDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
"runtimeClasspath"
|
||||||
|
)
|
||||||
|
|
||||||
|
override lateinit var runtimeDependencyFiles: FileCollection
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KotlinCompilation<*>.disambiguateName(simpleName: String): String {
|
||||||
|
return lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
simpleName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
open class KotlinJvmCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJvmOptions>(target, name), KotlinCompilationWithResources<KotlinJvmOptions> {
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
override val compileKotlinTask: org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
get() = super.compileKotlinTask as org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinWithJavaCompilation<KotlinOptionsType : KotlinCommonOptions>(
|
||||||
|
target: KotlinWithJavaTarget<KotlinOptionsType>,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinOptionsType>(target, name), KotlinCompilationWithResources<KotlinOptionsType> {
|
||||||
|
lateinit var javaSourceSet: SourceSet
|
||||||
|
|
||||||
|
override val output: KotlinCompilationOutput by lazy { KotlinWithJavaCompilationOutput(this) }
|
||||||
|
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = javaSourceSet.processResourcesTaskName
|
||||||
|
|
||||||
|
override var runtimeDependencyFiles: FileCollection
|
||||||
|
get() = javaSourceSet.runtimeClasspath
|
||||||
|
set(value) {
|
||||||
|
javaSourceSet.runtimeClasspath = value
|
||||||
|
}
|
||||||
|
|
||||||
|
override val runtimeDependencyConfigurationName: String
|
||||||
|
get() = javaSourceSet.runtimeClasspathConfigurationName
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = javaSourceSet.compileClasspathConfigurationName
|
||||||
|
|
||||||
|
override val runtimeOnlyConfigurationName: String
|
||||||
|
get() = javaSourceSet.runtimeOnlyConfigurationName
|
||||||
|
|
||||||
|
override val implementationConfigurationName: String
|
||||||
|
get() = javaSourceSet.implementationConfigurationName
|
||||||
|
|
||||||
|
override val apiConfigurationName: String
|
||||||
|
get() = javaSourceSet.apiConfigurationName
|
||||||
|
|
||||||
|
override val compileOnlyConfigurationName: String
|
||||||
|
get() = javaSourceSet.compileOnlyConfigurationName
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = javaSourceSet.classesTaskName
|
||||||
|
|
||||||
|
override var compileDependencyFiles: FileCollection
|
||||||
|
get() = javaSourceSet.compileClasspath
|
||||||
|
set(value) {
|
||||||
|
javaSourceSet.compileClasspath = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun source(javaSourceSet: SourceSet) {
|
||||||
|
with(target.project) {
|
||||||
|
afterEvaluate {
|
||||||
|
(tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>).source(javaSourceSet.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmAndroidCompilation(
|
||||||
|
target: KotlinAndroidTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJvmOptions>(target, name) {
|
||||||
|
override val compileKotlinTask: org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
get() = super.compileKotlinTask as org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
override val relatedConfigurationNames: List<String>
|
||||||
|
get() = super.relatedConfigurationNames + listOf("${name}ApiElements", "${name}RuntimeElements")
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJsOptions>(target, name), KotlinCompilationWithResources<KotlinJsOptions> {
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
override val compileKotlinTask: Kotlin2JsCompile
|
||||||
|
get() = super.compileKotlinTask as Kotlin2JsCompile
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinCommonCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<KotlinMultiplatformCommonOptions>(target, name) {
|
||||||
|
override val compileKotlinTask: KotlinCompileCommon
|
||||||
|
get() = super.compileKotlinTask as KotlinCompileCommon
|
||||||
|
|
||||||
|
// TODO once we properly compile metadata for each source set, the default source sets will likely become just the source sets
|
||||||
|
// which are transformed to metadata
|
||||||
|
private val commonSourceSetName = when (compilationName) {
|
||||||
|
KotlinCompilation.MAIN_COMPILATION_NAME -> KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME
|
||||||
|
else -> error("Custom metadata compilations are not supported yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
override val defaultSourceSet: KotlinSourceSet
|
||||||
|
get() = target.project.kotlinExtension.sourceSets.getByName(commonSourceSetName)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeCompilation(
|
||||||
|
override val target: KotlinNativeTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<KotlinCommonOptions>(target, name), KotlinCompilationWithResources<KotlinCommonOptions> {
|
||||||
|
|
||||||
|
override val kotlinOptions: KotlinCommonOptions
|
||||||
|
get() = compileKotlinTask.kotlinOptions
|
||||||
|
|
||||||
|
override val compileKotlinTask: KotlinNativeCompile
|
||||||
|
get() = super.compileKotlinTask as KotlinNativeCompile
|
||||||
|
|
||||||
|
private val project: Project
|
||||||
|
get() = target.project
|
||||||
|
|
||||||
|
// A collection containing all source sets used by this compilation
|
||||||
|
// (taking into account dependencies between source sets). Used by both compilation
|
||||||
|
// and linking tasks. Unlike kotlinSourceSets, includes dependency source sets.
|
||||||
|
// TODO: Move into the compilation task when the linking task does klib linking instead of compilation.
|
||||||
|
internal val allSources: MutableSet<SourceDirectorySet> = mutableSetOf()
|
||||||
|
|
||||||
|
// TODO: Move into the compilation task when the linking task does klib linking instead of compilation.
|
||||||
|
internal val commonSources: MutableSet<SourceDirectorySet> = mutableSetOf()
|
||||||
|
|
||||||
|
var isTestCompilation = false
|
||||||
|
|
||||||
|
var friendCompilationName: String? = null
|
||||||
|
|
||||||
|
internal val friendCompilation: KotlinNativeCompilation?
|
||||||
|
get() = friendCompilationName?.let {
|
||||||
|
target.compilations.getByName(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used only to support the old APIs. TODO: Remove when the old APIs are removed.
|
||||||
|
internal val binaries = mutableMapOf<Pair<NativeOutputKind, NativeBuildType>, NativeBinary>()
|
||||||
|
|
||||||
|
// Native-specific DSL.
|
||||||
|
var extraOpts = mutableListOf<String>()
|
||||||
|
|
||||||
|
fun extraOpts(vararg values: Any) = extraOpts(values.toList())
|
||||||
|
fun extraOpts(values: List<Any>) {
|
||||||
|
extraOpts.addAll(values.map { it.toString() })
|
||||||
|
}
|
||||||
|
|
||||||
|
var buildTypes = mutableListOf<NativeBuildType>()
|
||||||
|
var outputKinds = mutableListOf<NativeOutputKind>()
|
||||||
|
|
||||||
|
fun outputKind(kind: NativeOutputKind) = outputKinds.add(kind)
|
||||||
|
|
||||||
|
fun outputKinds(vararg kinds: NativeOutputKind) {
|
||||||
|
outputKinds = kinds.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun outputKinds(vararg kinds: String) {
|
||||||
|
outputKinds = kinds.map { NativeOutputKind.valueOf(it.toUpperCase()) }.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun outputKinds(kinds: List<Any>) {
|
||||||
|
outputKinds = kinds.map {
|
||||||
|
when (it) {
|
||||||
|
is NativeOutputKind -> it
|
||||||
|
is String -> NativeOutputKind.valueOf(it.toUpperCase())
|
||||||
|
else -> error("Cannot use $it as an output kind")
|
||||||
|
}
|
||||||
|
}.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
var entryPoint: String? = null
|
||||||
|
fun entryPoint(value: String) {
|
||||||
|
entryPoint = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interop DSL.
|
||||||
|
val cinterops = project.container(DefaultCInteropSettings::class.java) { cinteropName ->
|
||||||
|
DefaultCInteropSettings(project, cinteropName, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
var linkerOpts = mutableListOf<String>()
|
||||||
|
|
||||||
|
fun cinterops(action: NamedDomainObjectContainer<DefaultCInteropSettings>.() -> Unit) = cinterops.action()
|
||||||
|
fun cinterops(action: Closure<Unit>) = cinterops(ConfigureUtil.configureUsing(action))
|
||||||
|
fun cinterops(action: Action<NamedDomainObjectContainer<DefaultCInteropSettings>>) = action.execute(cinterops)
|
||||||
|
|
||||||
|
fun linkerOpts(vararg values: String) = linkerOpts(values.toList())
|
||||||
|
fun linkerOpts(values: List<String>) {
|
||||||
|
linkerOpts.addAll(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Task accessors.
|
||||||
|
fun findLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeLink? = binaries[kind to buildType]?.linkTask
|
||||||
|
|
||||||
|
fun getLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeLink =
|
||||||
|
findLinkTask(kind, buildType)
|
||||||
|
?: throw IllegalArgumentException("Cannot find a link task for the binary kind '$kind' and the build type '$buildType'")
|
||||||
|
|
||||||
|
fun findLinkTask(kind: String, buildType: String) =
|
||||||
|
findLinkTask(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun getLinkTask(kind: String, buildType: String) =
|
||||||
|
getLinkTask(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun findBinary(kind: NativeOutputKind, buildType: NativeBuildType): File? = findLinkTask(kind, buildType)?.outputFile?.get()
|
||||||
|
|
||||||
|
fun getBinary(kind: NativeOutputKind, buildType: NativeBuildType): File = getLinkTask(kind, buildType).outputFile.get()
|
||||||
|
|
||||||
|
fun findBinary(kind: String, buildType: String) =
|
||||||
|
findBinary(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun getBinary(kind: String, buildType: String) =
|
||||||
|
getBinary(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
// Naming
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
fun linkTaskName(kind: NativeOutputKind, buildType: NativeBuildType): String =
|
||||||
|
lowerCamelCaseName(
|
||||||
|
"link",
|
||||||
|
KotlinNativeBinaryContainer.generateBinaryName(compilationName, buildType, kind.taskNameClassifier),
|
||||||
|
target.targetName
|
||||||
|
)
|
||||||
|
|
||||||
|
fun linkTaskName(kind: String, buildType: String) =
|
||||||
|
linkTaskName(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }.orEmpty(),
|
||||||
|
"compileKlibraries"
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "klibrary")
|
||||||
|
|
||||||
|
val binariesTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "binaries")
|
||||||
|
|
||||||
|
override fun addSourcesToCompileTask(sourceSet: KotlinSourceSet, addAsCommonSources: Boolean) {
|
||||||
|
allSources.add(sourceSet.kotlin)
|
||||||
|
if (addAsCommonSources) {
|
||||||
|
commonSources.add(sourceSet.kotlin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private object CompilationSourceSetUtil {
|
||||||
|
// Cache the results per project
|
||||||
|
private val projectSourceSetsInMultipleCompilationsCache = WeakHashMap<Project, Set<KotlinSourceSet>>()
|
||||||
|
|
||||||
|
fun sourceSetsInMultipleCompilations(project: Project) =
|
||||||
|
projectSourceSetsInMultipleCompilationsCache.computeIfAbsent(project) { _ ->
|
||||||
|
check(project.state.executed) { "Should only be computed after the project is evaluated" }
|
||||||
|
|
||||||
|
val compilations = (project.kotlinExtension as? KotlinMultiplatformExtension)?.targets?.flatMap { it.compilations }
|
||||||
|
?: return@computeIfAbsent null
|
||||||
|
|
||||||
|
compilations
|
||||||
|
.flatMap { compilation -> compilation.allKotlinSourceSets.map { sourceSet -> compilation to sourceSet } }
|
||||||
|
.groupingBy { (_, sourceSet) -> sourceSet }
|
||||||
|
.eachCount()
|
||||||
|
.filterValues { it > 1 }
|
||||||
|
.keys
|
||||||
|
}
|
||||||
|
}
|
||||||
+93
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.NamedDomainObjectFactory
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
|
|
||||||
|
interface KotlinCompilationFactory<T : KotlinCompilation<*>> : NamedDomainObjectFactory<T> {
|
||||||
|
val itemClass: Class<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinCommonCompilationFactory(
|
||||||
|
val target: KotlinOnlyTarget<KotlinCommonCompilation>
|
||||||
|
) : KotlinCompilationFactory<KotlinCommonCompilation> {
|
||||||
|
override val itemClass: Class<KotlinCommonCompilation>
|
||||||
|
get() = KotlinCommonCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinCommonCompilation =
|
||||||
|
KotlinCommonCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmCompilationFactory(
|
||||||
|
val target: KotlinOnlyTarget<KotlinJvmCompilation>
|
||||||
|
) : KotlinCompilationFactory<KotlinJvmCompilation> {
|
||||||
|
override val itemClass: Class<KotlinJvmCompilation>
|
||||||
|
get() = KotlinJvmCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinJvmCompilation =
|
||||||
|
KotlinJvmCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinWithJavaCompilationFactory<KotlinOptionsType : KotlinCommonOptions>(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinWithJavaTarget<KotlinOptionsType>
|
||||||
|
) : KotlinCompilationFactory<KotlinWithJavaCompilation<KotlinOptionsType>> {
|
||||||
|
|
||||||
|
override val itemClass: Class<KotlinWithJavaCompilation<KotlinOptionsType>>
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
get() = KotlinWithJavaCompilation::class.java as Class<KotlinWithJavaCompilation<KotlinOptionsType>>
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinWithJavaCompilation<KotlinOptionsType> {
|
||||||
|
val result = KotlinWithJavaCompilation(target, name)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmAndroidCompilationFactory(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinAndroidTarget
|
||||||
|
) : KotlinCompilationFactory<KotlinJvmAndroidCompilation> {
|
||||||
|
|
||||||
|
override val itemClass: Class<KotlinJvmAndroidCompilation>
|
||||||
|
get() = KotlinJvmAndroidCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinJvmAndroidCompilation =
|
||||||
|
KotlinJvmAndroidCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsCompilationFactory(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinOnlyTarget<KotlinJsCompilation>
|
||||||
|
) : KotlinCompilationFactory<KotlinJsCompilation> {
|
||||||
|
override val itemClass: Class<KotlinJsCompilation>
|
||||||
|
get() = KotlinJsCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinJsCompilation =
|
||||||
|
KotlinJsCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeCompilationFactory(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinNativeTarget
|
||||||
|
) : KotlinCompilationFactory<KotlinNativeCompilation> {
|
||||||
|
|
||||||
|
override val itemClass: Class<KotlinNativeCompilation>
|
||||||
|
get() = KotlinNativeCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinNativeCompilation =
|
||||||
|
KotlinNativeCompilation(target, name).apply {
|
||||||
|
if (name == KotlinCompilation.TEST_COMPILATION_NAME) {
|
||||||
|
friendCompilationName = KotlinCompilation.MAIN_COMPILATION_NAME
|
||||||
|
isTestCompilation = true
|
||||||
|
}
|
||||||
|
buildTypes = mutableListOf(NativeBuildType.DEBUG, NativeBuildType.RELEASE)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+437
@@ -0,0 +1,437 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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 groovy.lang.Closure
|
||||||
|
import org.gradle.api.*
|
||||||
|
import org.gradle.api.artifacts.ConfigurablePublishArtifact
|
||||||
|
import org.gradle.api.artifacts.Dependency
|
||||||
|
import org.gradle.api.artifacts.PublishArtifact
|
||||||
|
import org.gradle.api.attributes.Attribute
|
||||||
|
import org.gradle.api.attributes.AttributeContainer
|
||||||
|
import org.gradle.api.attributes.Usage.JAVA_API
|
||||||
|
import org.gradle.api.attributes.Usage.JAVA_RUNTIME_JARS
|
||||||
|
import org.gradle.api.plugins.JavaPlugin
|
||||||
|
import org.gradle.api.publish.maven.MavenPublication
|
||||||
|
import org.gradle.util.ConfigureUtil
|
||||||
|
import org.gradle.util.WrapUtil
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeBinaryContainer
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
|
||||||
|
abstract class AbstractKotlinTarget(
|
||||||
|
final override val project: Project
|
||||||
|
) : KotlinTarget {
|
||||||
|
private val attributeContainer = HierarchyAttributeContainer(parent = null)
|
||||||
|
|
||||||
|
override fun getAttributes(): AttributeContainer = attributeContainer
|
||||||
|
|
||||||
|
override val defaultConfigurationName: String
|
||||||
|
get() = disambiguateName("default")
|
||||||
|
|
||||||
|
override val apiElementsConfigurationName: String
|
||||||
|
get() = disambiguateName("apiElements")
|
||||||
|
|
||||||
|
override val runtimeElementsConfigurationName: String
|
||||||
|
get() = disambiguateName("runtimeElements")
|
||||||
|
|
||||||
|
override val artifactsTaskName: String
|
||||||
|
get() = disambiguateName("jar")
|
||||||
|
|
||||||
|
override fun toString(): String = "target $name ($platformType)"
|
||||||
|
|
||||||
|
override val publishable: Boolean
|
||||||
|
get() = true
|
||||||
|
|
||||||
|
override val components: Set<KotlinTargetComponent> by lazy {
|
||||||
|
val mainCompilation = compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
val usageContexts = createUsageContexts(mainCompilation)
|
||||||
|
setOf(
|
||||||
|
if (isGradleVersionAtLeast(4, 7)) {
|
||||||
|
val componentName = mainCompilation.target.name
|
||||||
|
createKotlinVariant(componentName, mainCompilation, usageContexts).apply {
|
||||||
|
sourcesArtifacts = setOf(
|
||||||
|
sourcesJarArtifact(
|
||||||
|
mainCompilation, componentName,
|
||||||
|
dashSeparatedName(target.name.toLowerCase(), componentName.toLowerCase())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
KotlinVariant(mainCompilation, usageContexts)
|
||||||
|
}
|
||||||
|
).also { project.components.addAll(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun createKotlinVariant(
|
||||||
|
componentName: String,
|
||||||
|
compilation: KotlinCompilation<*>,
|
||||||
|
usageContexts: Set<DefaultKotlinUsageContext>
|
||||||
|
): KotlinVariant {
|
||||||
|
|
||||||
|
val kotlinExtension = project.kotlinExtension as? KotlinMultiplatformExtension
|
||||||
|
?: return KotlinVariantWithCoordinates(compilation, usageContexts)
|
||||||
|
|
||||||
|
if (targetName == KotlinMultiplatformPlugin.METADATA_TARGET_NAME)
|
||||||
|
return KotlinVariantWithCoordinates(compilation, usageContexts)
|
||||||
|
|
||||||
|
val separateMetadataTarget = kotlinExtension.targets.getByName(KotlinMultiplatformPlugin.METADATA_TARGET_NAME)
|
||||||
|
|
||||||
|
val result = if (kotlinExtension.isGradleMetadataAvailable) {
|
||||||
|
KotlinVariantWithMetadataVariant(compilation, usageContexts, separateMetadataTarget)
|
||||||
|
} else {
|
||||||
|
// we should only add the Kotlin metadata dependency if we publish no Gradle metadata related to Kotlin MPP;
|
||||||
|
// with metadata, such a dependency would get invalid, since a platform module should only depend on modules for that
|
||||||
|
// same platform, not Kotlin metadata modules
|
||||||
|
KotlinVariantWithMetadataDependency(compilation, usageContexts, separateMetadataTarget)
|
||||||
|
}
|
||||||
|
|
||||||
|
result.componentName = componentName
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createUsageContexts(
|
||||||
|
producingCompilation: KotlinCompilation<*>
|
||||||
|
): Set<DefaultKotlinUsageContext> {
|
||||||
|
// Here, `JAVA_API` and `JAVA_RUNTIME_JARS` are used intentionally as Gradle needs this for
|
||||||
|
// ordering of the usage contexts (prioritizing the dependencies) when merging them into the POM;
|
||||||
|
// These Java usages should not be replaced with the custom Kotlin usages.
|
||||||
|
return listOfNotNull(
|
||||||
|
JAVA_API to apiElementsConfigurationName,
|
||||||
|
(JAVA_RUNTIME_JARS to runtimeElementsConfigurationName).takeIf { producingCompilation is KotlinCompilationToRunnableFiles }
|
||||||
|
).mapTo(mutableSetOf()) { (usageName, dependenciesConfigurationName) ->
|
||||||
|
DefaultKotlinUsageContext(
|
||||||
|
producingCompilation,
|
||||||
|
project.usageByName(usageName),
|
||||||
|
dependenciesConfigurationName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun sourcesJarArtifact(
|
||||||
|
producingCompilation: KotlinCompilation<*>,
|
||||||
|
componentName: String,
|
||||||
|
artifactNameAppendix: String,
|
||||||
|
classifierPrefix: String? = null
|
||||||
|
): PublishArtifact {
|
||||||
|
val sourcesJarTask = sourcesJarTask(producingCompilation, componentName, artifactNameAppendix)
|
||||||
|
val sourceArtifactConfigurationName = producingCompilation.disambiguateName("sourceArtifacts")
|
||||||
|
return producingCompilation.target.project.run {
|
||||||
|
(configurations.findByName(sourceArtifactConfigurationName) ?: run {
|
||||||
|
val configuration = configurations.create(sourceArtifactConfigurationName) {
|
||||||
|
it.isCanBeResolved = false
|
||||||
|
it.isCanBeConsumed = false
|
||||||
|
}
|
||||||
|
artifacts.add(sourceArtifactConfigurationName, sourcesJarTask)
|
||||||
|
configuration
|
||||||
|
}).artifacts.single().apply {
|
||||||
|
this as ConfigurablePublishArtifact
|
||||||
|
classifier = dashSeparatedName(classifierPrefix, "sources")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
internal val publicationConfigureActions =
|
||||||
|
WrapUtil.toDomainObjectSet(Action::class.java) as DomainObjectSet<Action<MavenPublication>>
|
||||||
|
|
||||||
|
override fun mavenPublication(action: Action<MavenPublication>) {
|
||||||
|
publicationConfigureActions.add(action)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mavenPublication(action: Closure<Unit>) =
|
||||||
|
mavenPublication(ConfigureUtil.configureUsing(action))
|
||||||
|
|
||||||
|
override var preset: KotlinTargetPreset<out KotlinTarget>? = null
|
||||||
|
internal set
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KotlinTarget.disambiguateName(simpleName: String) =
|
||||||
|
lowerCamelCaseName(targetName, simpleName)
|
||||||
|
|
||||||
|
open class KotlinAndroidTarget(
|
||||||
|
override val targetName: String,
|
||||||
|
project: Project
|
||||||
|
) : AbstractKotlinTarget(project) {
|
||||||
|
|
||||||
|
override var disambiguationClassifier: String? = null
|
||||||
|
internal set
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.androidJvm
|
||||||
|
|
||||||
|
private val compilationFactory = KotlinJvmAndroidCompilationFactory(project, this)
|
||||||
|
|
||||||
|
override val compilations: NamedDomainObjectContainer<out KotlinJvmAndroidCompilation> =
|
||||||
|
project.container(compilationFactory.itemClass, compilationFactory)
|
||||||
|
|
||||||
|
/** Names of the Android library variants that should be published from the target's project within the default publications which are
|
||||||
|
* set up if the `maven-publish` Gradle plugin is applied.
|
||||||
|
*
|
||||||
|
* Item examples:
|
||||||
|
* * 'release' (in case no product flavors were defined)
|
||||||
|
* * 'fooRelease' (for the release build type of a flavor 'foo')
|
||||||
|
* * 'fooBarRelease' (for the release build type multi-dimensional flavors 'foo' and 'bar').
|
||||||
|
*
|
||||||
|
* If set to null, which can also be done with [publishAllLibraryVariants],
|
||||||
|
* all library variants will be published, but not test or application variants. */
|
||||||
|
var publishLibraryVariants: List<String>? = listOf()
|
||||||
|
// Workaround for Groovy GString items in a list:
|
||||||
|
set(value) { field = value?.map(Any::toString) }
|
||||||
|
|
||||||
|
/** Add Android library variant names to [publishLibraryVariants]. */
|
||||||
|
fun publishLibraryVariants(vararg names: String) {
|
||||||
|
publishLibraryVariants = publishLibraryVariants.orEmpty() + names
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set up all of the Android library variants to be published from this target's project within the default publications, which are
|
||||||
|
* set up if the `maven-publish` Gradle plugin is applied. This overrides the variants chosen with [publishLibraryVariants] */
|
||||||
|
fun publishAllLibraryVariants() {
|
||||||
|
publishLibraryVariants = null
|
||||||
|
}
|
||||||
|
|
||||||
|
/** If true, a publication will be created per merged product flavor, with the build types used as classifiers for the artifacts
|
||||||
|
* published within each publication. If set to false, each Android variant will have a separate publication. */
|
||||||
|
var publishLibraryVariantsGroupedByFlavor = false
|
||||||
|
|
||||||
|
private fun checkPublishLibraryVariantsExist() {
|
||||||
|
// Capture type parameter T
|
||||||
|
fun <T> AbstractAndroidProjectHandler<T>.getLibraryVariantNames() =
|
||||||
|
mutableSetOf<String>().apply {
|
||||||
|
forEachVariant(project) {
|
||||||
|
if (getLibraryOutputTask(it) != null)
|
||||||
|
add(getVariantName(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val variantNames =
|
||||||
|
KotlinAndroidPlugin.androidTargetHandler(project.getKotlinPluginVersion()!!, this)
|
||||||
|
.getLibraryVariantNames()
|
||||||
|
|
||||||
|
val missingVariants =
|
||||||
|
publishLibraryVariants?.minus(variantNames).orEmpty()
|
||||||
|
|
||||||
|
if (missingVariants.isNotEmpty())
|
||||||
|
throw InvalidUserDataException(
|
||||||
|
"Kotlin target '$targetName' tried to set up publishing for Android build variants that are not library variants " +
|
||||||
|
"or do not exist:\n" + missingVariants.joinToString("\n") { "* $it" } +
|
||||||
|
"\nCheck the 'publishLibraryVariants' property, it should point to existing Android library variants. Publishing " +
|
||||||
|
"of application and test variants is not supported."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val components by lazy {
|
||||||
|
checkPublishLibraryVariantsExist()
|
||||||
|
|
||||||
|
KotlinAndroidPlugin.androidTargetHandler(project.getKotlinPluginVersion()!!, this).doCreateComponents()
|
||||||
|
.also { project.components.addAll(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capture the type parameter T for `AbstractAndroidProjectHandler`
|
||||||
|
private fun <T> AbstractAndroidProjectHandler<T>.doCreateComponents(): Set<KotlinTargetComponent> {
|
||||||
|
if (!isGradleVersionAtLeast(4, 7))
|
||||||
|
return emptySet()
|
||||||
|
|
||||||
|
val publishableVariants = mutableListOf<T>()
|
||||||
|
.apply { forEachVariant(project) { add(it) } }
|
||||||
|
.toList() // Defensive copy against unlikely modification by the lambda that captures the list above in forEachVariant { }
|
||||||
|
.filter { getLibraryOutputTask(it) != null && publishLibraryVariants?.contains(getVariantName(it)) ?: true }
|
||||||
|
|
||||||
|
val publishableVariantGroups = publishableVariants.groupBy { variant ->
|
||||||
|
val flavorNames = getFlavorNames(variant)
|
||||||
|
if (publishLibraryVariantsGroupedByFlavor) {
|
||||||
|
// For each flavor, we group its variants (which differ only in the build type) in a single component in order to publish
|
||||||
|
// all of the build types of the flavor as a single module with the build type as the classifier of the artifacts
|
||||||
|
flavorNames
|
||||||
|
} else {
|
||||||
|
flavorNames + getBuildTypeName(variant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return publishableVariantGroups.map { (flavorGroupNameParts, androidVariants) ->
|
||||||
|
val nestedVariants = androidVariants.mapTo(mutableSetOf()) { androidVariant ->
|
||||||
|
val androidVariantName = getVariantName(androidVariant)
|
||||||
|
val compilation = compilations.getByName(androidVariantName)
|
||||||
|
|
||||||
|
val flavorNames = getFlavorNames(androidVariant)
|
||||||
|
val buildTypeName = getBuildTypeName(androidVariant)
|
||||||
|
|
||||||
|
val artifactClassifier = buildTypeName.takeIf { it != "release" && publishLibraryVariantsGroupedByFlavor }
|
||||||
|
|
||||||
|
val usageContexts = createAndroidUsageContexts(androidVariant, compilation, artifactClassifier)
|
||||||
|
createKotlinVariant(
|
||||||
|
lowerCamelCaseName(compilation.target.name, *flavorGroupNameParts.toTypedArray()),
|
||||||
|
compilation,
|
||||||
|
usageContexts
|
||||||
|
).apply {
|
||||||
|
sourcesArtifacts = setOf(
|
||||||
|
sourcesJarArtifact(
|
||||||
|
compilation, compilation.disambiguateName(""),
|
||||||
|
dashSeparatedName(
|
||||||
|
compilation.target.name.toLowerCase(),
|
||||||
|
*flavorNames.map { it.toLowerCase() }.toTypedArray(),
|
||||||
|
buildTypeName.takeIf { it != "release" }?.toLowerCase()
|
||||||
|
),
|
||||||
|
classifierPrefix = artifactClassifier
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!publishLibraryVariantsGroupedByFlavor) {
|
||||||
|
defaultArtifactIdSuffix =
|
||||||
|
dashSeparatedName(
|
||||||
|
(getFlavorNames(androidVariant) + getBuildTypeName(androidVariant).takeIf { it != "release" })
|
||||||
|
.map { it?.toLowerCase() }
|
||||||
|
).takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (publishLibraryVariantsGroupedByFlavor) {
|
||||||
|
JointAndroidKotlinTargetComponent(
|
||||||
|
this@KotlinAndroidTarget,
|
||||||
|
nestedVariants,
|
||||||
|
flavorGroupNameParts,
|
||||||
|
nestedVariants.flatMap { it.sourcesArtifacts }.toSet()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
nestedVariants.single()
|
||||||
|
} as KotlinTargetComponent
|
||||||
|
}.toSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> AbstractAndroidProjectHandler<T>.createAndroidUsageContexts(
|
||||||
|
variant: T,
|
||||||
|
compilation: KotlinCompilation<*>,
|
||||||
|
artifactClassifier: String?
|
||||||
|
): Set<DefaultKotlinUsageContext> {
|
||||||
|
val variantName = getVariantName(variant)
|
||||||
|
val outputTask = getLibraryOutputTask(variant) ?: return emptySet()
|
||||||
|
val artifact = run {
|
||||||
|
val archivesConfigurationName = lowerCamelCaseName(targetName, variantName, "archives")
|
||||||
|
project.configurations.maybeCreate(archivesConfigurationName).apply {
|
||||||
|
isCanBeConsumed = false
|
||||||
|
isCanBeResolved = false
|
||||||
|
}
|
||||||
|
project.artifacts.add(archivesConfigurationName, outputTask) { artifact ->
|
||||||
|
artifact.classifier = artifactClassifier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val apiElementsConfigurationName = lowerCamelCaseName(variantName, "apiElements")
|
||||||
|
val runtimeElementsConfigurationName = lowerCamelCaseName(variantName, "runtimeElements")
|
||||||
|
|
||||||
|
// Here, `JAVA_API` and `JAVA_RUNTIME_JARS` are used intentionally as Gradle needs this for
|
||||||
|
// ordering of the usage contexts (prioritizing the dependencies) when merging them into the POM;
|
||||||
|
// These Java usages should not be replaced with the custom Kotlin usages.
|
||||||
|
return listOf(
|
||||||
|
apiElementsConfigurationName to JAVA_API,
|
||||||
|
runtimeElementsConfigurationName to JAVA_RUNTIME_JARS
|
||||||
|
).mapTo(mutableSetOf()) { (dependencyConfigurationName, usageName) ->
|
||||||
|
DefaultKotlinUsageContext(
|
||||||
|
compilation,
|
||||||
|
project.usageByName(usageName),
|
||||||
|
dependencyConfigurationName,
|
||||||
|
overrideConfigurationArtifacts = setOf(artifact)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class KotlinWithJavaTarget<KotlinOptionsType : KotlinCommonOptions>(
|
||||||
|
project: Project,
|
||||||
|
override val platformType: KotlinPlatformType,
|
||||||
|
override val targetName: String
|
||||||
|
) : AbstractKotlinTarget(project) {
|
||||||
|
override var disambiguationClassifier: String? = null
|
||||||
|
internal set
|
||||||
|
|
||||||
|
override val defaultConfigurationName: String
|
||||||
|
get() = Dependency.DEFAULT_CONFIGURATION
|
||||||
|
|
||||||
|
override val apiElementsConfigurationName: String
|
||||||
|
get() = JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME
|
||||||
|
|
||||||
|
override val runtimeElementsConfigurationName: String
|
||||||
|
get() = JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME
|
||||||
|
|
||||||
|
override val artifactsTaskName: String
|
||||||
|
get() = JavaPlugin.JAR_TASK_NAME
|
||||||
|
|
||||||
|
override val compilations: NamedDomainObjectContainer<KotlinWithJavaCompilation<KotlinOptionsType>> =
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
project.container(
|
||||||
|
KotlinWithJavaCompilation::class.java as Class<KotlinWithJavaCompilation<KotlinOptionsType>>,
|
||||||
|
KotlinWithJavaCompilationFactory(project, this)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
open class KotlinOnlyTarget<T : KotlinCompilation<*>>(
|
||||||
|
project: Project,
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
) : AbstractKotlinTarget(project) {
|
||||||
|
|
||||||
|
override lateinit var compilations: NamedDomainObjectContainer<T>
|
||||||
|
internal set
|
||||||
|
|
||||||
|
override lateinit var targetName: String
|
||||||
|
internal set
|
||||||
|
|
||||||
|
override var disambiguationClassifier: String? = null
|
||||||
|
internal set
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeTarget(
|
||||||
|
project: Project,
|
||||||
|
val konanTarget: KonanTarget
|
||||||
|
) : KotlinOnlyTarget<KotlinNativeCompilation>(project, KotlinPlatformType.native) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
attributes.attribute(konanTargetAttribute, konanTarget.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
val binaries = if(isGradleVersionAtLeast(4, 2)) {
|
||||||
|
// Use newInstance to allow accessing binaries by their names in Groovy using the extension mechanism.
|
||||||
|
project.objects.newInstance(KotlinNativeBinaryContainer::class.java, this, WrapUtil.toDomainObjectSet(NativeBinary::class.java))
|
||||||
|
} else {
|
||||||
|
KotlinNativeBinaryContainer(this, WrapUtil.toDomainObjectSet(NativeBinary::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun binaries(configure: KotlinNativeBinaryContainer.() -> Unit) {
|
||||||
|
binaries.configure()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun binaries(configure: Closure<*>) {
|
||||||
|
ConfigureUtil.configure(configure, binaries)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val artifactsTaskName: String
|
||||||
|
get() = disambiguateName("binaries")
|
||||||
|
|
||||||
|
override val publishable: Boolean
|
||||||
|
get() = konanTarget.enabledOnCurrentHost
|
||||||
|
|
||||||
|
// User-visible constants
|
||||||
|
val DEBUG = NativeBuildType.DEBUG
|
||||||
|
val RELEASE = NativeBuildType.RELEASE
|
||||||
|
|
||||||
|
val EXECUTABLE = NativeOutputKind.EXECUTABLE
|
||||||
|
val FRAMEWORK = NativeOutputKind.FRAMEWORK
|
||||||
|
val DYNAMIC = NativeOutputKind.DYNAMIC
|
||||||
|
val STATIC = NativeOutputKind.STATIC
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val konanTargetAttribute = Attribute.of(
|
||||||
|
"org.jetbrains.kotlin.native.target",
|
||||||
|
String::class.java
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+330
@@ -0,0 +1,330 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.artifacts.Dependency
|
||||||
|
import org.gradle.api.internal.file.FileResolver
|
||||||
|
import org.gradle.api.plugins.JavaPlugin
|
||||||
|
import org.gradle.internal.reflect.Instantiator
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.KotlinNativeProjectProperty
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.hasProperty
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.konanHome
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinTask
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
|
||||||
|
import org.jetbrains.kotlin.konan.KonanVersion
|
||||||
|
import org.jetbrains.kotlin.konan.target.HostManager
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
abstract class KotlinOnlyTargetPreset<T : KotlinCompilation<*>>(
|
||||||
|
protected val project: Project,
|
||||||
|
private val instantiator: Instantiator,
|
||||||
|
private val fileResolver: FileResolver,
|
||||||
|
protected val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinOnlyTarget<T>> {
|
||||||
|
|
||||||
|
protected open fun createKotlinTargetConfigurator(): KotlinTargetConfigurator<T> =
|
||||||
|
KotlinTargetConfigurator(createDefaultSourceSets = true, createTestCompilation = true)
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinOnlyTarget<T> {
|
||||||
|
val result = KotlinOnlyTarget<T>(project, platformType).apply {
|
||||||
|
targetName = name
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinOnlyTargetPreset
|
||||||
|
|
||||||
|
val compilationFactory = createCompilationFactory(this)
|
||||||
|
compilations = project.container(compilationFactory.itemClass, compilationFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
createKotlinTargetConfigurator().configureTarget(result)
|
||||||
|
|
||||||
|
result.compilations.all { compilation ->
|
||||||
|
buildCompilationProcessor(compilation).run()
|
||||||
|
if (compilation.name == KotlinCompilation.MAIN_COMPILATION_NAME) {
|
||||||
|
sourcesJarTask(compilation, result.targetName, result.targetName.toLowerCase())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun createCompilationFactory(forTarget: KotlinOnlyTarget<T>): KotlinCompilationFactory<T>
|
||||||
|
protected abstract val platformType: KotlinPlatformType
|
||||||
|
internal abstract fun buildCompilationProcessor(compilation: T): KotlinSourceSetProcessor<*>
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinMetadataTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinCommonCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(
|
||||||
|
forTarget: KotlinOnlyTarget<KotlinCommonCompilation>
|
||||||
|
): KotlinCompilationFactory<KotlinCommonCompilation> =
|
||||||
|
KotlinCommonCompilationFactory(forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.common
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinCommonCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return KotlinCommonSourceSetProcessor(project, compilation, tasksProvider, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "metadata"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createKotlinTargetConfigurator(): KotlinTargetConfigurator<KotlinCommonCompilation> =
|
||||||
|
KotlinTargetConfigurator(createDefaultSourceSets = false, createTestCompilation = false)
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinOnlyTarget<KotlinCommonCompilation> =
|
||||||
|
super.createTarget(name).apply {
|
||||||
|
val mainCompilation = compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
val commonMainSourceSet = project.kotlinExtension.sourceSets.getByName(KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME)
|
||||||
|
|
||||||
|
mainCompilation.source(commonMainSourceSet)
|
||||||
|
|
||||||
|
project.afterEvaluate {
|
||||||
|
// Since there's no default source set, apply language settings from commonMain:
|
||||||
|
val compileKotlinMetadata = project.tasks.getByName(mainCompilation.compileKotlinTaskName) as KotlinCompile<*>
|
||||||
|
applyLanguageSettingsToKotlinTask(commonMainSourceSet.languageSettings, compileKotlinMetadata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinJvmCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinJvmCompilation>): KotlinCompilationFactory<KotlinJvmCompilation> =
|
||||||
|
KotlinJvmCompilationFactory(forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.jvm
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinJvmCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return Kotlin2JvmSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "jvm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsTargetPreset(
|
||||||
|
project: Project,
|
||||||
|
instantiator: Instantiator,
|
||||||
|
fileResolver: FileResolver,
|
||||||
|
kotlinPluginVersion: String
|
||||||
|
) : KotlinOnlyTargetPreset<KotlinJsCompilation>(
|
||||||
|
project,
|
||||||
|
instantiator,
|
||||||
|
fileResolver,
|
||||||
|
kotlinPluginVersion
|
||||||
|
) {
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createCompilationFactory(forTarget: KotlinOnlyTarget<KotlinJsCompilation>) =
|
||||||
|
KotlinJsCompilationFactory(project, forTarget)
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.js
|
||||||
|
|
||||||
|
override fun buildCompilationProcessor(compilation: KotlinJsCompilation): KotlinSourceSetProcessor<*> {
|
||||||
|
val tasksProvider = KotlinTasksProvider(compilation.target.targetName)
|
||||||
|
return Kotlin2JsSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinAndroidTargetPreset(
|
||||||
|
private val project: Project,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinAndroidTarget> {
|
||||||
|
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinAndroidTarget {
|
||||||
|
val result = KotlinAndroidTarget(name, project).apply {
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinAndroidTargetPreset
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinAndroidPlugin.applyToTarget(kotlinPluginVersion, result)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "android"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmWithJavaTargetPreset(
|
||||||
|
private val project: Project,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinWithJavaTarget<KotlinJvmOptions>> {
|
||||||
|
|
||||||
|
override fun getName(): String = PRESET_NAME
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinWithJavaTarget<KotlinJvmOptions> {
|
||||||
|
project.plugins.apply(JavaPlugin::class.java)
|
||||||
|
|
||||||
|
val target = KotlinWithJavaTarget<KotlinJvmOptions>(project, KotlinPlatformType.jvm, name).apply {
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinJvmWithJavaTargetPreset
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractKotlinPlugin.configureTarget(target) { compilation ->
|
||||||
|
Kotlin2JvmSourceSetProcessor(project, KotlinTasksProvider(name), compilation, kotlinPluginVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
target.compilations.getByName("test").run {
|
||||||
|
val main = target.compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
|
||||||
|
compileDependencyFiles = project.files(
|
||||||
|
main.output.allOutputs,
|
||||||
|
project.configurations.maybeCreate(compileDependencyConfigurationName)
|
||||||
|
)
|
||||||
|
runtimeDependencyFiles = project.files(
|
||||||
|
output.allOutputs,
|
||||||
|
main.output.allOutputs,
|
||||||
|
project.configurations.maybeCreate(runtimeDependencyConfigurationName)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PRESET_NAME = "jvmWithJava"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeTargetPreset(
|
||||||
|
private val name: String,
|
||||||
|
val project: Project,
|
||||||
|
val konanTarget: KonanTarget,
|
||||||
|
private val kotlinPluginVersion: String
|
||||||
|
) : KotlinTargetPreset<KotlinNativeTarget> {
|
||||||
|
|
||||||
|
init {
|
||||||
|
// This is required to obtain Kotlin/Native home in CLion plugin:
|
||||||
|
setupNativeHomePrivateProperty()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName(): String = name
|
||||||
|
|
||||||
|
private fun setupNativeHomePrivateProperty() = with(project) {
|
||||||
|
if (!hasProperty(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY))
|
||||||
|
extensions.extraProperties.set(KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY, konanHome)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupNativeCompiler() = with(project) {
|
||||||
|
if (!hasProperty(KotlinNativeProjectProperty.KONAN_HOME_OVERRIDE)) {
|
||||||
|
NativeCompilerDownloader(this).downloadIfNeeded()
|
||||||
|
logger.info("Kotlin/Native distribution: $konanHome")
|
||||||
|
} else {
|
||||||
|
logger.info("User-provided Kotlin/Native distribution: $konanHome")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We declare default K/N dependencies as files to avoid searching them in remote repos (see KT-28128).
|
||||||
|
private fun defaultLibs(target: KonanTarget? = null): List<Dependency> = with(project) {
|
||||||
|
|
||||||
|
val relPath = if (target != null) "platform/${target.name}" else "common"
|
||||||
|
|
||||||
|
file("$konanHome/klib/$relPath")
|
||||||
|
.listFiles { file -> file.isDirectory }
|
||||||
|
?.sortedBy { dir -> dir.name.toLowerCase() }
|
||||||
|
?.map { dir -> dependencies.create(files(dir)) } ?: emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createTarget(name: String): KotlinNativeTarget {
|
||||||
|
setupNativeCompiler()
|
||||||
|
|
||||||
|
val result = KotlinNativeTarget(project, konanTarget).apply {
|
||||||
|
targetName = name
|
||||||
|
disambiguationClassifier = name
|
||||||
|
preset = this@KotlinNativeTargetPreset
|
||||||
|
|
||||||
|
val compilationFactory = KotlinNativeCompilationFactory(project, this)
|
||||||
|
compilations = project.container(compilationFactory.itemClass, compilationFactory)
|
||||||
|
}
|
||||||
|
|
||||||
|
KotlinNativeTargetConfigurator(kotlinPluginVersion).configureTarget(result)
|
||||||
|
|
||||||
|
// Allow IDE to resolve the libraries provided by the compiler by adding them into dependencies.
|
||||||
|
result.compilations.all { compilation ->
|
||||||
|
val target = compilation.target.konanTarget
|
||||||
|
// First, put common libs:
|
||||||
|
defaultLibs().forEach {
|
||||||
|
project.dependencies.add(compilation.compileDependencyConfigurationName, it)
|
||||||
|
}
|
||||||
|
// Then, platform-specific libs:
|
||||||
|
defaultLibs(target).forEach {
|
||||||
|
project.dependencies.add(compilation.compileDependencyConfigurationName, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!konanTarget.enabledOnCurrentHost) {
|
||||||
|
with(HostManager()) {
|
||||||
|
val supportedHosts = enabledTargetsByHost.filterValues { konanTarget in it }.keys
|
||||||
|
val supportedHostsString =
|
||||||
|
if (supportedHosts.size == 1)
|
||||||
|
"a ${supportedHosts.single()} host" else
|
||||||
|
"one of the host platforms: ${supportedHosts.joinToString(", ")}"
|
||||||
|
project.logger.warn(
|
||||||
|
"Target '$name' for platform ${konanTarget} is ignored during build on this ${HostManager.host} machine. " +
|
||||||
|
"You can build it with $supportedHostsString."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val KOTLIN_NATIVE_HOME_PRIVATE_PROPERTY = "konanHome"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val KonanTarget.isCurrentHost: Boolean
|
||||||
|
get() = this == HostManager.host
|
||||||
|
|
||||||
|
internal val KonanTarget.enabledOnCurrentHost
|
||||||
|
get() = HostManager().isEnabled(this)
|
||||||
|
|
||||||
|
internal val KotlinNativeCompilation.isMainCompilation: Boolean
|
||||||
|
get() = name == KotlinCompilation.MAIN_COMPILATION_NAME
|
||||||
+471
@@ -0,0 +1,471 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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 groovy.lang.Closure
|
||||||
|
import org.gradle.api.Action
|
||||||
|
import org.gradle.api.NamedDomainObjectContainer
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.attributes.AttributeContainer
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.file.SourceDirectorySet
|
||||||
|
import org.gradle.api.tasks.SourceSet
|
||||||
|
import org.gradle.util.ConfigureUtil
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.*
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.defaultSourceSetLanguageSettingsChecker
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.sources.getSourceSetHierarchy
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.*
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
|
internal fun KotlinCompilation<*>.composeName(prefix: String? = null, suffix: String? = null): String {
|
||||||
|
val compilationNamePart = compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }
|
||||||
|
val targetNamePart = target.disambiguationClassifier
|
||||||
|
|
||||||
|
return lowerCamelCaseName(prefix, targetNamePart, compilationNamePart, suffix)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val KotlinCompilation<*>.defaultSourceSetName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName)
|
||||||
|
|
||||||
|
abstract class AbstractKotlinCompilation<T : KotlinCommonOptions>(
|
||||||
|
target: KotlinTarget,
|
||||||
|
override val compilationName: String
|
||||||
|
) : KotlinCompilation<T>, HasKotlinDependencies {
|
||||||
|
|
||||||
|
override val kotlinOptions: T
|
||||||
|
get() = compileKotlinTask.kotlinOptions
|
||||||
|
|
||||||
|
override fun kotlinOptions(configure: T.() -> Unit) =
|
||||||
|
configure(kotlinOptions)
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
override val compileKotlinTask: KotlinCompile<T>
|
||||||
|
get() = (target.project.tasks.getByName(compileKotlinTaskName) as KotlinCompile<T>)
|
||||||
|
|
||||||
|
// Don't declare this property in the constructor to avoid NPE
|
||||||
|
// when an overriding property of a subclass is accessed instead.
|
||||||
|
override val target: KotlinTarget = target
|
||||||
|
|
||||||
|
private val attributeContainer = HierarchyAttributeContainer(target.attributes)
|
||||||
|
|
||||||
|
override fun getAttributes(): AttributeContainer = attributeContainer
|
||||||
|
|
||||||
|
override val kotlinSourceSets: MutableSet<KotlinSourceSet> = mutableSetOf()
|
||||||
|
|
||||||
|
override val allKotlinSourceSets: Set<KotlinSourceSet>
|
||||||
|
get() = kotlinSourceSets.flatMapTo(mutableSetOf()) { it.getSourceSetHierarchy() }
|
||||||
|
|
||||||
|
override val defaultSourceSet: KotlinSourceSet
|
||||||
|
get() = target.project.kotlinExtension.sourceSets.getByName(defaultSourceSetName)
|
||||||
|
|
||||||
|
override fun defaultSourceSet(configure: KotlinSourceSet.() -> Unit) =
|
||||||
|
configure(defaultSourceSet)
|
||||||
|
|
||||||
|
override val output: KotlinCompilationOutput by lazy {
|
||||||
|
DefaultKotlinCompilationOutput(
|
||||||
|
target.project,
|
||||||
|
Callable { target.project.buildDir.resolve("processedResources/${target.targetName}/$name") })
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun addSourcesToCompileTask(sourceSet: KotlinSourceSet, addAsCommonSources: Boolean) {
|
||||||
|
fun AbstractKotlinCompile<*>.configureAction() {
|
||||||
|
source(sourceSet.kotlin)
|
||||||
|
sourceFilesExtensions(sourceSet.customSourceFilesExtensions)
|
||||||
|
if (addAsCommonSources) {
|
||||||
|
commonSourceSet += sourceSet.kotlin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note! Invocation of withType-all results in preliminary task instantiation.
|
||||||
|
// After fix of this issue the following code should be uncommented:
|
||||||
|
// if (useLazyTaskConfiguration) {
|
||||||
|
// (target.project.tasks.named(compileKotlinTaskName) as TaskProvider<AbstractKotlinCompile<*>>).configure {
|
||||||
|
// it.configureAction()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
target.project.tasks
|
||||||
|
// To configure a task that may have not yet been created at this point, use 'withType-matching-all`:
|
||||||
|
.withType(AbstractKotlinCompile::class.java)
|
||||||
|
.matching { it.name == compileKotlinTaskName }
|
||||||
|
.all { compileKotlinTask ->
|
||||||
|
compileKotlinTask.configureAction()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun source(sourceSet: KotlinSourceSet) {
|
||||||
|
if (kotlinSourceSets.add(sourceSet)) {
|
||||||
|
//TODO possibly issue with forced instantiation
|
||||||
|
target.project.whenEvaluated {
|
||||||
|
sourceSet.getSourceSetHierarchy().forEach { sourceSet ->
|
||||||
|
val isCommonSource =
|
||||||
|
CompilationSourceSetUtil.sourceSetsInMultipleCompilations(project)?.contains(sourceSet) ?: false
|
||||||
|
|
||||||
|
addSourcesToCompileTask(sourceSet, addAsCommonSources = isCommonSource)
|
||||||
|
|
||||||
|
// Use `forced = false` since `api`, `implementation`, and `compileOnly` may be missing in some cases like
|
||||||
|
// old Java & Android projects:
|
||||||
|
addExtendsFromRelation(apiConfigurationName, sourceSet.apiConfigurationName, forced = false)
|
||||||
|
addExtendsFromRelation(implementationConfigurationName, sourceSet.implementationConfigurationName, forced = false)
|
||||||
|
addExtendsFromRelation(compileOnlyConfigurationName, sourceSet.compileOnlyConfigurationName, forced = false)
|
||||||
|
|
||||||
|
if (this@AbstractKotlinCompilation is KotlinCompilationToRunnableFiles<*>) {
|
||||||
|
addExtendsFromRelation(runtimeOnlyConfigurationName, sourceSet.runtimeOnlyConfigurationName, forced = false)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceSet.name != defaultSourceSetName) {
|
||||||
|
kotlinExtension.sourceSets.findByName(defaultSourceSetName)?.let { defaultSourceSet ->
|
||||||
|
// Temporary solution for checking consistency across source sets participating in a compilation that may
|
||||||
|
// not be interconnected with the dependsOn relation: check the settings as if the default source set of
|
||||||
|
// the compilation depends on the one added to the compilation:
|
||||||
|
defaultSourceSetLanguageSettingsChecker.runAllChecks(
|
||||||
|
defaultSourceSet,
|
||||||
|
sourceSet
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }.orEmpty(),
|
||||||
|
"compileClasspath"
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileKotlinTaskName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
"compile",
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
"Kotlin",
|
||||||
|
target.targetName
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "classes")
|
||||||
|
|
||||||
|
override lateinit var compileDependencyFiles: FileCollection
|
||||||
|
|
||||||
|
override val apiConfigurationName: String
|
||||||
|
get() = disambiguateName("api")
|
||||||
|
|
||||||
|
override val implementationConfigurationName: String
|
||||||
|
get() = disambiguateName("implementation")
|
||||||
|
|
||||||
|
override val compileOnlyConfigurationName: String
|
||||||
|
get() = disambiguateName("compileOnly")
|
||||||
|
|
||||||
|
override val runtimeOnlyConfigurationName: String
|
||||||
|
get() = disambiguateName("runtimeOnly")
|
||||||
|
|
||||||
|
override fun dependencies(configure: KotlinDependencyHandler.() -> Unit): Unit =
|
||||||
|
DefaultKotlinDependencyHandler(this, target.project).run(configure)
|
||||||
|
|
||||||
|
override fun dependencies(configureClosure: Closure<Any?>) =
|
||||||
|
dependencies f@{ ConfigureUtil.configure(configureClosure, this@f) }
|
||||||
|
|
||||||
|
override fun toString(): String = "compilation '$compilationName' ($target)"
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AbstractKotlinCompilationToRunnableFiles<T : KotlinCommonOptions>(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<T>(target, name), KotlinCompilationToRunnableFiles<T> {
|
||||||
|
override val runtimeDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
"runtimeClasspath"
|
||||||
|
)
|
||||||
|
|
||||||
|
override lateinit var runtimeDependencyFiles: FileCollection
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KotlinCompilation<*>.disambiguateName(simpleName: String): String {
|
||||||
|
return lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
|
||||||
|
simpleName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
open class KotlinJvmCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJvmOptions>(target, name), KotlinCompilationWithResources<KotlinJvmOptions> {
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
override val compileKotlinTask: org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
get() = super.compileKotlinTask as org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinWithJavaCompilation<KotlinOptionsType : KotlinCommonOptions>(
|
||||||
|
target: KotlinWithJavaTarget<KotlinOptionsType>,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinOptionsType>(target, name), KotlinCompilationWithResources<KotlinOptionsType> {
|
||||||
|
lateinit var javaSourceSet: SourceSet
|
||||||
|
|
||||||
|
override val output: KotlinCompilationOutput by lazy { KotlinWithJavaCompilationOutput(this) }
|
||||||
|
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = javaSourceSet.processResourcesTaskName
|
||||||
|
|
||||||
|
override var runtimeDependencyFiles: FileCollection
|
||||||
|
get() = javaSourceSet.runtimeClasspath
|
||||||
|
set(value) {
|
||||||
|
javaSourceSet.runtimeClasspath = value
|
||||||
|
}
|
||||||
|
|
||||||
|
override val runtimeDependencyConfigurationName: String
|
||||||
|
get() = javaSourceSet.runtimeClasspathConfigurationName
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = javaSourceSet.compileClasspathConfigurationName
|
||||||
|
|
||||||
|
override val runtimeOnlyConfigurationName: String
|
||||||
|
get() = javaSourceSet.runtimeOnlyConfigurationName
|
||||||
|
|
||||||
|
override val implementationConfigurationName: String
|
||||||
|
get() = javaSourceSet.implementationConfigurationName
|
||||||
|
|
||||||
|
override val apiConfigurationName: String
|
||||||
|
get() = javaSourceSet.apiConfigurationName
|
||||||
|
|
||||||
|
override val compileOnlyConfigurationName: String
|
||||||
|
get() = javaSourceSet.compileOnlyConfigurationName
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = javaSourceSet.classesTaskName
|
||||||
|
|
||||||
|
override var compileDependencyFiles: FileCollection
|
||||||
|
get() = javaSourceSet.compileClasspath
|
||||||
|
set(value) {
|
||||||
|
javaSourceSet.compileClasspath = value
|
||||||
|
}
|
||||||
|
|
||||||
|
fun source(javaSourceSet: SourceSet) {
|
||||||
|
with(target.project) {
|
||||||
|
afterEvaluate {
|
||||||
|
(tasks.getByName(compileKotlinTaskName) as AbstractKotlinCompile<*>).source(javaSourceSet.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmAndroidCompilation(
|
||||||
|
target: KotlinAndroidTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJvmOptions>(target, name) {
|
||||||
|
override val compileKotlinTask: org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
get() = super.compileKotlinTask as org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
|
|
||||||
|
override val relatedConfigurationNames: List<String>
|
||||||
|
get() = super.relatedConfigurationNames + listOf("${name}ApiElements", "${name}RuntimeElements")
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilationToRunnableFiles<KotlinJsOptions>(target, name), KotlinCompilationWithResources<KotlinJsOptions> {
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
override val compileKotlinTask: Kotlin2JsCompile
|
||||||
|
get() = super.compileKotlinTask as Kotlin2JsCompile
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinCommonCompilation(
|
||||||
|
target: KotlinTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<KotlinMultiplatformCommonOptions>(target, name) {
|
||||||
|
override val compileKotlinTask: KotlinCompileCommon
|
||||||
|
get() = super.compileKotlinTask as KotlinCompileCommon
|
||||||
|
|
||||||
|
// TODO once we properly compile metadata for each source set, the default source sets will likely become just the source sets
|
||||||
|
// which are transformed to metadata
|
||||||
|
private val commonSourceSetName = when (compilationName) {
|
||||||
|
KotlinCompilation.MAIN_COMPILATION_NAME -> KotlinSourceSet.COMMON_MAIN_SOURCE_SET_NAME
|
||||||
|
else -> error("Custom metadata compilations are not supported yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
override val defaultSourceSet: KotlinSourceSet
|
||||||
|
get() = target.project.kotlinExtension.sourceSets.getByName(commonSourceSetName)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeCompilation(
|
||||||
|
override val target: KotlinNativeTarget,
|
||||||
|
name: String
|
||||||
|
) : AbstractKotlinCompilation<KotlinCommonOptions>(target, name), KotlinCompilationWithResources<KotlinCommonOptions> {
|
||||||
|
|
||||||
|
override val kotlinOptions: KotlinCommonOptions
|
||||||
|
get() = compileKotlinTask.kotlinOptions
|
||||||
|
|
||||||
|
override val compileKotlinTask: KotlinNativeCompile
|
||||||
|
get() = super.compileKotlinTask as KotlinNativeCompile
|
||||||
|
|
||||||
|
private val project: Project
|
||||||
|
get() = target.project
|
||||||
|
|
||||||
|
// A collection containing all source sets used by this compilation
|
||||||
|
// (taking into account dependencies between source sets). Used by both compilation
|
||||||
|
// and linking tasks. Unlike kotlinSourceSets, includes dependency source sets.
|
||||||
|
// TODO: Move into the compilation task when the linking task does klib linking instead of compilation.
|
||||||
|
internal val allSources: MutableSet<SourceDirectorySet> = mutableSetOf()
|
||||||
|
|
||||||
|
// TODO: Move into the compilation task when the linking task does klib linking instead of compilation.
|
||||||
|
internal val commonSources: MutableSet<SourceDirectorySet> = mutableSetOf()
|
||||||
|
|
||||||
|
var isTestCompilation = false
|
||||||
|
|
||||||
|
var friendCompilationName: String? = null
|
||||||
|
|
||||||
|
internal val friendCompilation: KotlinNativeCompilation?
|
||||||
|
get() = friendCompilationName?.let {
|
||||||
|
target.compilations.getByName(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used only to support the old APIs. TODO: Remove when the old APIs are removed.
|
||||||
|
internal val binaries = mutableMapOf<Pair<NativeOutputKind, NativeBuildType>, NativeBinary>()
|
||||||
|
|
||||||
|
// Native-specific DSL.
|
||||||
|
var extraOpts = mutableListOf<String>()
|
||||||
|
|
||||||
|
fun extraOpts(vararg values: Any) = extraOpts(values.toList())
|
||||||
|
fun extraOpts(values: List<Any>) {
|
||||||
|
extraOpts.addAll(values.map { it.toString() })
|
||||||
|
}
|
||||||
|
|
||||||
|
var buildTypes = mutableListOf<NativeBuildType>()
|
||||||
|
var outputKinds = mutableListOf<NativeOutputKind>()
|
||||||
|
|
||||||
|
fun outputKind(kind: NativeOutputKind) = outputKinds.add(kind)
|
||||||
|
|
||||||
|
fun outputKinds(vararg kinds: NativeOutputKind) {
|
||||||
|
outputKinds = kinds.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun outputKinds(vararg kinds: String) {
|
||||||
|
outputKinds = kinds.map { NativeOutputKind.valueOf(it.toUpperCase()) }.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun outputKinds(kinds: List<Any>) {
|
||||||
|
outputKinds = kinds.map {
|
||||||
|
when (it) {
|
||||||
|
is NativeOutputKind -> it
|
||||||
|
is String -> NativeOutputKind.valueOf(it.toUpperCase())
|
||||||
|
else -> error("Cannot use $it as an output kind")
|
||||||
|
}
|
||||||
|
}.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
var entryPoint: String? = null
|
||||||
|
fun entryPoint(value: String) {
|
||||||
|
entryPoint = value
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interop DSL.
|
||||||
|
val cinterops = project.container(DefaultCInteropSettings::class.java) { cinteropName ->
|
||||||
|
DefaultCInteropSettings(project, cinteropName, this)
|
||||||
|
}
|
||||||
|
|
||||||
|
var linkerOpts = mutableListOf<String>()
|
||||||
|
|
||||||
|
fun cinterops(action: NamedDomainObjectContainer<DefaultCInteropSettings>.() -> Unit) = cinterops.action()
|
||||||
|
fun cinterops(action: Closure<Unit>) = cinterops(ConfigureUtil.configureUsing(action))
|
||||||
|
fun cinterops(action: Action<NamedDomainObjectContainer<DefaultCInteropSettings>>) = action.execute(cinterops)
|
||||||
|
|
||||||
|
fun linkerOpts(vararg values: String) = linkerOpts(values.toList())
|
||||||
|
fun linkerOpts(values: List<String>) {
|
||||||
|
linkerOpts.addAll(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Task accessors.
|
||||||
|
fun findLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeLink? = binaries[kind to buildType]?.linkTask
|
||||||
|
|
||||||
|
fun getLinkTask(kind: NativeOutputKind, buildType: NativeBuildType): KotlinNativeLink =
|
||||||
|
findLinkTask(kind, buildType)
|
||||||
|
?: throw IllegalArgumentException("Cannot find a link task for the binary kind '$kind' and the build type '$buildType'")
|
||||||
|
|
||||||
|
fun findLinkTask(kind: String, buildType: String) =
|
||||||
|
findLinkTask(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun getLinkTask(kind: String, buildType: String) =
|
||||||
|
getLinkTask(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun findBinary(kind: NativeOutputKind, buildType: NativeBuildType): File? = findLinkTask(kind, buildType)?.outputFile?.get()
|
||||||
|
|
||||||
|
fun getBinary(kind: NativeOutputKind, buildType: NativeBuildType): File = getLinkTask(kind, buildType).outputFile.get()
|
||||||
|
|
||||||
|
fun findBinary(kind: String, buildType: String) =
|
||||||
|
findBinary(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
fun getBinary(kind: String, buildType: String) =
|
||||||
|
getBinary(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
// Naming
|
||||||
|
override val processResourcesTaskName: String
|
||||||
|
get() = disambiguateName("processResources")
|
||||||
|
|
||||||
|
fun linkTaskName(kind: NativeOutputKind, buildType: NativeBuildType): String =
|
||||||
|
lowerCamelCaseName(
|
||||||
|
"link",
|
||||||
|
KotlinNativeBinaryContainer.generateBinaryName(compilationName, buildType, kind.taskNameClassifier),
|
||||||
|
target.targetName
|
||||||
|
)
|
||||||
|
|
||||||
|
fun linkTaskName(kind: String, buildType: String) =
|
||||||
|
linkTaskName(NativeOutputKind.valueOf(kind.toUpperCase()), NativeBuildType.valueOf(buildType.toUpperCase()))
|
||||||
|
|
||||||
|
override val compileDependencyConfigurationName: String
|
||||||
|
get() = lowerCamelCaseName(
|
||||||
|
target.disambiguationClassifier,
|
||||||
|
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }.orEmpty(),
|
||||||
|
"compileKlibraries"
|
||||||
|
)
|
||||||
|
|
||||||
|
override val compileAllTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "klibrary")
|
||||||
|
|
||||||
|
val binariesTaskName: String
|
||||||
|
get() = lowerCamelCaseName(target.disambiguationClassifier, compilationName, "binaries")
|
||||||
|
|
||||||
|
override fun addSourcesToCompileTask(sourceSet: KotlinSourceSet, addAsCommonSources: Boolean) {
|
||||||
|
allSources.add(sourceSet.kotlin)
|
||||||
|
if (addAsCommonSources) {
|
||||||
|
commonSources.add(sourceSet.kotlin)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private object CompilationSourceSetUtil {
|
||||||
|
// Cache the results per project
|
||||||
|
private val projectSourceSetsInMultipleCompilationsCache = WeakHashMap<Project, Set<KotlinSourceSet>>()
|
||||||
|
|
||||||
|
fun sourceSetsInMultipleCompilations(project: Project) =
|
||||||
|
projectSourceSetsInMultipleCompilationsCache.computeIfAbsent(project) { _ ->
|
||||||
|
check(project.state.executed) { "Should only be computed after the project is evaluated" }
|
||||||
|
|
||||||
|
val compilations = (project.kotlinExtension as? KotlinMultiplatformExtension)?.targets?.flatMap { it.compilations }
|
||||||
|
?: return@computeIfAbsent null
|
||||||
|
|
||||||
|
compilations
|
||||||
|
.flatMap { compilation -> compilation.allKotlinSourceSets.map { sourceSet -> compilation to sourceSet } }
|
||||||
|
.groupingBy { (_, sourceSet) -> sourceSet }
|
||||||
|
.eachCount()
|
||||||
|
.filterValues { it > 1 }
|
||||||
|
.keys
|
||||||
|
}
|
||||||
|
}
|
||||||
+93
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.NamedDomainObjectFactory
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
|
|
||||||
|
interface KotlinCompilationFactory<T : KotlinCompilation<*>> : NamedDomainObjectFactory<T> {
|
||||||
|
val itemClass: Class<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinCommonCompilationFactory(
|
||||||
|
val target: KotlinOnlyTarget<KotlinCommonCompilation>
|
||||||
|
) : KotlinCompilationFactory<KotlinCommonCompilation> {
|
||||||
|
override val itemClass: Class<KotlinCommonCompilation>
|
||||||
|
get() = KotlinCommonCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinCommonCompilation =
|
||||||
|
KotlinCommonCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmCompilationFactory(
|
||||||
|
val target: KotlinOnlyTarget<KotlinJvmCompilation>
|
||||||
|
) : KotlinCompilationFactory<KotlinJvmCompilation> {
|
||||||
|
override val itemClass: Class<KotlinJvmCompilation>
|
||||||
|
get() = KotlinJvmCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinJvmCompilation =
|
||||||
|
KotlinJvmCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinWithJavaCompilationFactory<KotlinOptionsType : KotlinCommonOptions>(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinWithJavaTarget<KotlinOptionsType>
|
||||||
|
) : KotlinCompilationFactory<KotlinWithJavaCompilation<KotlinOptionsType>> {
|
||||||
|
|
||||||
|
override val itemClass: Class<KotlinWithJavaCompilation<KotlinOptionsType>>
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
get() = KotlinWithJavaCompilation::class.java as Class<KotlinWithJavaCompilation<KotlinOptionsType>>
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinWithJavaCompilation<KotlinOptionsType> {
|
||||||
|
val result = KotlinWithJavaCompilation(target, name)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmAndroidCompilationFactory(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinAndroidTarget
|
||||||
|
) : KotlinCompilationFactory<KotlinJvmAndroidCompilation> {
|
||||||
|
|
||||||
|
override val itemClass: Class<KotlinJvmAndroidCompilation>
|
||||||
|
get() = KotlinJvmAndroidCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinJvmAndroidCompilation =
|
||||||
|
KotlinJvmAndroidCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJsCompilationFactory(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinOnlyTarget<KotlinJsCompilation>
|
||||||
|
) : KotlinCompilationFactory<KotlinJsCompilation> {
|
||||||
|
override val itemClass: Class<KotlinJsCompilation>
|
||||||
|
get() = KotlinJsCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinJsCompilation =
|
||||||
|
KotlinJsCompilation(target, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeCompilationFactory(
|
||||||
|
val project: Project,
|
||||||
|
val target: KotlinNativeTarget
|
||||||
|
) : KotlinCompilationFactory<KotlinNativeCompilation> {
|
||||||
|
|
||||||
|
override val itemClass: Class<KotlinNativeCompilation>
|
||||||
|
get() = KotlinNativeCompilation::class.java
|
||||||
|
|
||||||
|
override fun create(name: String): KotlinNativeCompilation =
|
||||||
|
KotlinNativeCompilation(target, name).apply {
|
||||||
|
if (name == KotlinCompilation.TEST_COMPILATION_NAME) {
|
||||||
|
friendCompilationName = KotlinCompilation.MAIN_COMPILATION_NAME
|
||||||
|
isTestCompilation = true
|
||||||
|
}
|
||||||
|
buildTypes = mutableListOf(NativeBuildType.DEBUG, NativeBuildType.RELEASE)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+56
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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.file.ConfigurableFileCollection
|
||||||
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationOutput
|
||||||
|
import java.io.File
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
|
class DefaultKotlinCompilationOutput(
|
||||||
|
private val project: Project,
|
||||||
|
override var resourcesDirProvider: Any
|
||||||
|
) : KotlinCompilationOutput, Callable<FileCollection> {
|
||||||
|
|
||||||
|
override val classesDirs: ConfigurableFileCollection = project.files()
|
||||||
|
|
||||||
|
override val allOutputs = project.files().apply {
|
||||||
|
from(classesDirs)
|
||||||
|
from(Callable { resourcesDir })
|
||||||
|
}
|
||||||
|
|
||||||
|
override val resourcesDir: File
|
||||||
|
get() = project.file(resourcesDirProvider)
|
||||||
|
|
||||||
|
override fun call(): FileCollection = allOutputs
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinWithJavaCompilationOutput(
|
||||||
|
internal val compilation: KotlinWithJavaCompilation<*>
|
||||||
|
) : KotlinCompilationOutput, Callable<FileCollection> {
|
||||||
|
|
||||||
|
private val javaSourceSetOutput
|
||||||
|
get() = compilation.javaSourceSet.output
|
||||||
|
|
||||||
|
override val resourcesDir: File
|
||||||
|
get() = javaSourceSetOutput.resourcesDir!!
|
||||||
|
|
||||||
|
override var resourcesDirProvider: Any
|
||||||
|
get() = javaSourceSetOutput.resourcesDir!!
|
||||||
|
set(value) {
|
||||||
|
javaSourceSetOutput.setResourcesDir(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val classesDirs: ConfigurableFileCollection =
|
||||||
|
javaSourceSetOutput.classesDirs as ConfigurableFileCollection
|
||||||
|
|
||||||
|
override val allOutputs: FileCollection
|
||||||
|
get() = javaSourceSetOutput
|
||||||
|
|
||||||
|
override fun call(): FileCollection = allOutputs
|
||||||
|
}
|
||||||
+437
@@ -0,0 +1,437 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2018 JetBrains s.r.o. 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 groovy.lang.Closure
|
||||||
|
import org.gradle.api.*
|
||||||
|
import org.gradle.api.artifacts.ConfigurablePublishArtifact
|
||||||
|
import org.gradle.api.artifacts.Dependency
|
||||||
|
import org.gradle.api.artifacts.PublishArtifact
|
||||||
|
import org.gradle.api.attributes.Attribute
|
||||||
|
import org.gradle.api.attributes.AttributeContainer
|
||||||
|
import org.gradle.api.attributes.Usage.JAVA_API
|
||||||
|
import org.gradle.api.attributes.Usage.JAVA_RUNTIME_JARS
|
||||||
|
import org.gradle.api.plugins.JavaPlugin
|
||||||
|
import org.gradle.api.publish.maven.MavenPublication
|
||||||
|
import org.gradle.util.ConfigureUtil
|
||||||
|
import org.gradle.util.WrapUtil
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.KotlinNativeBinaryContainer
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.*
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.dashSeparatedName
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
|
|
||||||
|
abstract class AbstractKotlinTarget(
|
||||||
|
final override val project: Project
|
||||||
|
) : KotlinTarget {
|
||||||
|
private val attributeContainer = HierarchyAttributeContainer(parent = null)
|
||||||
|
|
||||||
|
override fun getAttributes(): AttributeContainer = attributeContainer
|
||||||
|
|
||||||
|
override val defaultConfigurationName: String
|
||||||
|
get() = disambiguateName("default")
|
||||||
|
|
||||||
|
override val apiElementsConfigurationName: String
|
||||||
|
get() = disambiguateName("apiElements")
|
||||||
|
|
||||||
|
override val runtimeElementsConfigurationName: String
|
||||||
|
get() = disambiguateName("runtimeElements")
|
||||||
|
|
||||||
|
override val artifactsTaskName: String
|
||||||
|
get() = disambiguateName("jar")
|
||||||
|
|
||||||
|
override fun toString(): String = "target $name ($platformType)"
|
||||||
|
|
||||||
|
override val publishable: Boolean
|
||||||
|
get() = true
|
||||||
|
|
||||||
|
override val components: Set<KotlinTargetComponent> by lazy {
|
||||||
|
val mainCompilation = compilations.getByName(KotlinCompilation.MAIN_COMPILATION_NAME)
|
||||||
|
val usageContexts = createUsageContexts(mainCompilation)
|
||||||
|
setOf(
|
||||||
|
if (isGradleVersionAtLeast(4, 7)) {
|
||||||
|
val componentName = mainCompilation.target.name
|
||||||
|
createKotlinVariant(componentName, mainCompilation, usageContexts).apply {
|
||||||
|
sourcesArtifacts = setOf(
|
||||||
|
sourcesJarArtifact(
|
||||||
|
mainCompilation, componentName,
|
||||||
|
dashSeparatedName(target.name.toLowerCase(), componentName.toLowerCase())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
KotlinVariant(mainCompilation, usageContexts)
|
||||||
|
}
|
||||||
|
).also { project.components.addAll(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun createKotlinVariant(
|
||||||
|
componentName: String,
|
||||||
|
compilation: KotlinCompilation<*>,
|
||||||
|
usageContexts: Set<DefaultKotlinUsageContext>
|
||||||
|
): KotlinVariant {
|
||||||
|
|
||||||
|
val kotlinExtension = project.kotlinExtension as? KotlinMultiplatformExtension
|
||||||
|
?: return KotlinVariantWithCoordinates(compilation, usageContexts)
|
||||||
|
|
||||||
|
if (targetName == KotlinMultiplatformPlugin.METADATA_TARGET_NAME)
|
||||||
|
return KotlinVariantWithCoordinates(compilation, usageContexts)
|
||||||
|
|
||||||
|
val separateMetadataTarget = kotlinExtension.targets.getByName(KotlinMultiplatformPlugin.METADATA_TARGET_NAME)
|
||||||
|
|
||||||
|
val result = if (kotlinExtension.isGradleMetadataAvailable) {
|
||||||
|
KotlinVariantWithMetadataVariant(compilation, usageContexts, separateMetadataTarget)
|
||||||
|
} else {
|
||||||
|
// we should only add the Kotlin metadata dependency if we publish no Gradle metadata related to Kotlin MPP;
|
||||||
|
// with metadata, such a dependency would get invalid, since a platform module should only depend on modules for that
|
||||||
|
// same platform, not Kotlin metadata modules
|
||||||
|
KotlinVariantWithMetadataDependency(compilation, usageContexts, separateMetadataTarget)
|
||||||
|
}
|
||||||
|
|
||||||
|
result.componentName = componentName
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createUsageContexts(
|
||||||
|
producingCompilation: KotlinCompilation<*>
|
||||||
|
): Set<DefaultKotlinUsageContext> {
|
||||||
|
// Here, `JAVA_API` and `JAVA_RUNTIME_JARS` are used intentionally as Gradle needs this for
|
||||||
|
// ordering of the usage contexts (prioritizing the dependencies) when merging them into the POM;
|
||||||
|
// These Java usages should not be replaced with the custom Kotlin usages.
|
||||||
|
return listOfNotNull(
|
||||||
|
JAVA_API to apiElementsConfigurationName,
|
||||||
|
(JAVA_RUNTIME_JARS to runtimeElementsConfigurationName).takeIf { producingCompilation is KotlinCompilationToRunnableFiles }
|
||||||
|
).mapTo(mutableSetOf()) { (usageName, dependenciesConfigurationName) ->
|
||||||
|
DefaultKotlinUsageContext(
|
||||||
|
producingCompilation,
|
||||||
|
project.usageByName(usageName),
|
||||||
|
dependenciesConfigurationName
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected fun sourcesJarArtifact(
|
||||||
|
producingCompilation: KotlinCompilation<*>,
|
||||||
|
componentName: String,
|
||||||
|
artifactNameAppendix: String,
|
||||||
|
classifierPrefix: String? = null
|
||||||
|
): PublishArtifact {
|
||||||
|
val sourcesJarTask = sourcesJarTask(producingCompilation, componentName, artifactNameAppendix)
|
||||||
|
val sourceArtifactConfigurationName = producingCompilation.disambiguateName("sourceArtifacts")
|
||||||
|
return producingCompilation.target.project.run {
|
||||||
|
(configurations.findByName(sourceArtifactConfigurationName) ?: run {
|
||||||
|
val configuration = configurations.create(sourceArtifactConfigurationName) {
|
||||||
|
it.isCanBeResolved = false
|
||||||
|
it.isCanBeConsumed = false
|
||||||
|
}
|
||||||
|
artifacts.add(sourceArtifactConfigurationName, sourcesJarTask)
|
||||||
|
configuration
|
||||||
|
}).artifacts.single().apply {
|
||||||
|
this as ConfigurablePublishArtifact
|
||||||
|
classifier = dashSeparatedName(classifierPrefix, "sources")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
internal val publicationConfigureActions =
|
||||||
|
WrapUtil.toDomainObjectSet(Action::class.java) as DomainObjectSet<Action<MavenPublication>>
|
||||||
|
|
||||||
|
override fun mavenPublication(action: Action<MavenPublication>) {
|
||||||
|
publicationConfigureActions.add(action)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mavenPublication(action: Closure<Unit>) =
|
||||||
|
mavenPublication(ConfigureUtil.configureUsing(action))
|
||||||
|
|
||||||
|
override var preset: KotlinTargetPreset<out KotlinTarget>? = null
|
||||||
|
internal set
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun KotlinTarget.disambiguateName(simpleName: String) =
|
||||||
|
lowerCamelCaseName(targetName, simpleName)
|
||||||
|
|
||||||
|
open class KotlinAndroidTarget(
|
||||||
|
override val targetName: String,
|
||||||
|
project: Project
|
||||||
|
) : AbstractKotlinTarget(project) {
|
||||||
|
|
||||||
|
override var disambiguationClassifier: String? = null
|
||||||
|
internal set
|
||||||
|
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
get() = KotlinPlatformType.androidJvm
|
||||||
|
|
||||||
|
private val compilationFactory = KotlinJvmAndroidCompilationFactory(project, this)
|
||||||
|
|
||||||
|
override val compilations: NamedDomainObjectContainer<out KotlinJvmAndroidCompilation> =
|
||||||
|
project.container(compilationFactory.itemClass, compilationFactory)
|
||||||
|
|
||||||
|
/** Names of the Android library variants that should be published from the target's project within the default publications which are
|
||||||
|
* set up if the `maven-publish` Gradle plugin is applied.
|
||||||
|
*
|
||||||
|
* Item examples:
|
||||||
|
* * 'release' (in case no product flavors were defined)
|
||||||
|
* * 'fooRelease' (for the release build type of a flavor 'foo')
|
||||||
|
* * 'fooBarRelease' (for the release build type multi-dimensional flavors 'foo' and 'bar').
|
||||||
|
*
|
||||||
|
* If set to null, which can also be done with [publishAllLibraryVariants],
|
||||||
|
* all library variants will be published, but not test or application variants. */
|
||||||
|
var publishLibraryVariants: List<String>? = listOf()
|
||||||
|
// Workaround for Groovy GString items in a list:
|
||||||
|
set(value) { field = value?.map(Any::toString) }
|
||||||
|
|
||||||
|
/** Add Android library variant names to [publishLibraryVariants]. */
|
||||||
|
fun publishLibraryVariants(vararg names: String) {
|
||||||
|
publishLibraryVariants = publishLibraryVariants.orEmpty() + names
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set up all of the Android library variants to be published from this target's project within the default publications, which are
|
||||||
|
* set up if the `maven-publish` Gradle plugin is applied. This overrides the variants chosen with [publishLibraryVariants] */
|
||||||
|
fun publishAllLibraryVariants() {
|
||||||
|
publishLibraryVariants = null
|
||||||
|
}
|
||||||
|
|
||||||
|
/** If true, a publication will be created per merged product flavor, with the build types used as classifiers for the artifacts
|
||||||
|
* published within each publication. If set to false, each Android variant will have a separate publication. */
|
||||||
|
var publishLibraryVariantsGroupedByFlavor = false
|
||||||
|
|
||||||
|
private fun checkPublishLibraryVariantsExist() {
|
||||||
|
// Capture type parameter T
|
||||||
|
fun <T> AbstractAndroidProjectHandler<T>.getLibraryVariantNames() =
|
||||||
|
mutableSetOf<String>().apply {
|
||||||
|
forEachVariant(project) {
|
||||||
|
if (getLibraryOutputTask(it) != null)
|
||||||
|
add(getVariantName(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val variantNames =
|
||||||
|
KotlinAndroidPlugin.androidTargetHandler(project.getKotlinPluginVersion()!!, this)
|
||||||
|
.getLibraryVariantNames()
|
||||||
|
|
||||||
|
val missingVariants =
|
||||||
|
publishLibraryVariants?.minus(variantNames).orEmpty()
|
||||||
|
|
||||||
|
if (missingVariants.isNotEmpty())
|
||||||
|
throw InvalidUserDataException(
|
||||||
|
"Kotlin target '$targetName' tried to set up publishing for Android build variants that are not library variants " +
|
||||||
|
"or do not exist:\n" + missingVariants.joinToString("\n") { "* $it" } +
|
||||||
|
"\nCheck the 'publishLibraryVariants' property, it should point to existing Android library variants. Publishing " +
|
||||||
|
"of application and test variants is not supported."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val components by lazy {
|
||||||
|
checkPublishLibraryVariantsExist()
|
||||||
|
|
||||||
|
KotlinAndroidPlugin.androidTargetHandler(project.getKotlinPluginVersion()!!, this).doCreateComponents()
|
||||||
|
.also { project.components.addAll(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capture the type parameter T for `AbstractAndroidProjectHandler`
|
||||||
|
private fun <T> AbstractAndroidProjectHandler<T>.doCreateComponents(): Set<KotlinTargetComponent> {
|
||||||
|
if (!isGradleVersionAtLeast(4, 7))
|
||||||
|
return emptySet()
|
||||||
|
|
||||||
|
val publishableVariants = mutableListOf<T>()
|
||||||
|
.apply { forEachVariant(project) { add(it) } }
|
||||||
|
.toList() // Defensive copy against unlikely modification by the lambda that captures the list above in forEachVariant { }
|
||||||
|
.filter { getLibraryOutputTask(it) != null && publishLibraryVariants?.contains(getVariantName(it)) ?: true }
|
||||||
|
|
||||||
|
val publishableVariantGroups = publishableVariants.groupBy { variant ->
|
||||||
|
val flavorNames = getFlavorNames(variant)
|
||||||
|
if (publishLibraryVariantsGroupedByFlavor) {
|
||||||
|
// For each flavor, we group its variants (which differ only in the build type) in a single component in order to publish
|
||||||
|
// all of the build types of the flavor as a single module with the build type as the classifier of the artifacts
|
||||||
|
flavorNames
|
||||||
|
} else {
|
||||||
|
flavorNames + getBuildTypeName(variant)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return publishableVariantGroups.map { (flavorGroupNameParts, androidVariants) ->
|
||||||
|
val nestedVariants = androidVariants.mapTo(mutableSetOf()) { androidVariant ->
|
||||||
|
val androidVariantName = getVariantName(androidVariant)
|
||||||
|
val compilation = compilations.getByName(androidVariantName)
|
||||||
|
|
||||||
|
val flavorNames = getFlavorNames(androidVariant)
|
||||||
|
val buildTypeName = getBuildTypeName(androidVariant)
|
||||||
|
|
||||||
|
val artifactClassifier = buildTypeName.takeIf { it != "release" && publishLibraryVariantsGroupedByFlavor }
|
||||||
|
|
||||||
|
val usageContexts = createAndroidUsageContexts(androidVariant, compilation, artifactClassifier)
|
||||||
|
createKotlinVariant(
|
||||||
|
lowerCamelCaseName(compilation.target.name, *flavorGroupNameParts.toTypedArray()),
|
||||||
|
compilation,
|
||||||
|
usageContexts
|
||||||
|
).apply {
|
||||||
|
sourcesArtifacts = setOf(
|
||||||
|
sourcesJarArtifact(
|
||||||
|
compilation, compilation.disambiguateName(""),
|
||||||
|
dashSeparatedName(
|
||||||
|
compilation.target.name.toLowerCase(),
|
||||||
|
*flavorNames.map { it.toLowerCase() }.toTypedArray(),
|
||||||
|
buildTypeName.takeIf { it != "release" }?.toLowerCase()
|
||||||
|
),
|
||||||
|
classifierPrefix = artifactClassifier
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!publishLibraryVariantsGroupedByFlavor) {
|
||||||
|
defaultArtifactIdSuffix =
|
||||||
|
dashSeparatedName(
|
||||||
|
(getFlavorNames(androidVariant) + getBuildTypeName(androidVariant).takeIf { it != "release" })
|
||||||
|
.map { it?.toLowerCase() }
|
||||||
|
).takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (publishLibraryVariantsGroupedByFlavor) {
|
||||||
|
JointAndroidKotlinTargetComponent(
|
||||||
|
this@KotlinAndroidTarget,
|
||||||
|
nestedVariants,
|
||||||
|
flavorGroupNameParts,
|
||||||
|
nestedVariants.flatMap { it.sourcesArtifacts }.toSet()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
nestedVariants.single()
|
||||||
|
} as KotlinTargetComponent
|
||||||
|
}.toSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> AbstractAndroidProjectHandler<T>.createAndroidUsageContexts(
|
||||||
|
variant: T,
|
||||||
|
compilation: KotlinCompilation<*>,
|
||||||
|
artifactClassifier: String?
|
||||||
|
): Set<DefaultKotlinUsageContext> {
|
||||||
|
val variantName = getVariantName(variant)
|
||||||
|
val outputTask = getLibraryOutputTask(variant) ?: return emptySet()
|
||||||
|
val artifact = run {
|
||||||
|
val archivesConfigurationName = lowerCamelCaseName(targetName, variantName, "archives")
|
||||||
|
project.configurations.maybeCreate(archivesConfigurationName).apply {
|
||||||
|
isCanBeConsumed = false
|
||||||
|
isCanBeResolved = false
|
||||||
|
}
|
||||||
|
project.artifacts.add(archivesConfigurationName, outputTask) { artifact ->
|
||||||
|
artifact.classifier = artifactClassifier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val apiElementsConfigurationName = lowerCamelCaseName(variantName, "apiElements")
|
||||||
|
val runtimeElementsConfigurationName = lowerCamelCaseName(variantName, "runtimeElements")
|
||||||
|
|
||||||
|
// Here, `JAVA_API` and `JAVA_RUNTIME_JARS` are used intentionally as Gradle needs this for
|
||||||
|
// ordering of the usage contexts (prioritizing the dependencies) when merging them into the POM;
|
||||||
|
// These Java usages should not be replaced with the custom Kotlin usages.
|
||||||
|
return listOf(
|
||||||
|
apiElementsConfigurationName to JAVA_API,
|
||||||
|
runtimeElementsConfigurationName to JAVA_RUNTIME_JARS
|
||||||
|
).mapTo(mutableSetOf()) { (dependencyConfigurationName, usageName) ->
|
||||||
|
DefaultKotlinUsageContext(
|
||||||
|
compilation,
|
||||||
|
project.usageByName(usageName),
|
||||||
|
dependencyConfigurationName,
|
||||||
|
overrideConfigurationArtifacts = setOf(artifact)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open class KotlinWithJavaTarget<KotlinOptionsType : KotlinCommonOptions>(
|
||||||
|
project: Project,
|
||||||
|
override val platformType: KotlinPlatformType,
|
||||||
|
override val targetName: String
|
||||||
|
) : AbstractKotlinTarget(project) {
|
||||||
|
override var disambiguationClassifier: String? = null
|
||||||
|
internal set
|
||||||
|
|
||||||
|
override val defaultConfigurationName: String
|
||||||
|
get() = Dependency.DEFAULT_CONFIGURATION
|
||||||
|
|
||||||
|
override val apiElementsConfigurationName: String
|
||||||
|
get() = JavaPlugin.API_ELEMENTS_CONFIGURATION_NAME
|
||||||
|
|
||||||
|
override val runtimeElementsConfigurationName: String
|
||||||
|
get() = JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME
|
||||||
|
|
||||||
|
override val artifactsTaskName: String
|
||||||
|
get() = JavaPlugin.JAR_TASK_NAME
|
||||||
|
|
||||||
|
override val compilations: NamedDomainObjectContainer<KotlinWithJavaCompilation<KotlinOptionsType>> =
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
project.container(
|
||||||
|
KotlinWithJavaCompilation::class.java as Class<KotlinWithJavaCompilation<KotlinOptionsType>>,
|
||||||
|
KotlinWithJavaCompilationFactory(project, this)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
open class KotlinOnlyTarget<T : KotlinCompilation<*>>(
|
||||||
|
project: Project,
|
||||||
|
override val platformType: KotlinPlatformType
|
||||||
|
) : AbstractKotlinTarget(project) {
|
||||||
|
|
||||||
|
override lateinit var compilations: NamedDomainObjectContainer<T>
|
||||||
|
internal set
|
||||||
|
|
||||||
|
override lateinit var targetName: String
|
||||||
|
internal set
|
||||||
|
|
||||||
|
override var disambiguationClassifier: String? = null
|
||||||
|
internal set
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinNativeTarget(
|
||||||
|
project: Project,
|
||||||
|
val konanTarget: KonanTarget
|
||||||
|
) : KotlinOnlyTarget<KotlinNativeCompilation>(project, KotlinPlatformType.native) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
attributes.attribute(konanTargetAttribute, konanTarget.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
val binaries = if(isGradleVersionAtLeast(4, 2)) {
|
||||||
|
// Use newInstance to allow accessing binaries by their names in Groovy using the extension mechanism.
|
||||||
|
project.objects.newInstance(KotlinNativeBinaryContainer::class.java, this, WrapUtil.toDomainObjectSet(NativeBinary::class.java))
|
||||||
|
} else {
|
||||||
|
KotlinNativeBinaryContainer(this, WrapUtil.toDomainObjectSet(NativeBinary::class.java))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun binaries(configure: KotlinNativeBinaryContainer.() -> Unit) {
|
||||||
|
binaries.configure()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun binaries(configure: Closure<*>) {
|
||||||
|
ConfigureUtil.configure(configure, binaries)
|
||||||
|
}
|
||||||
|
|
||||||
|
override val artifactsTaskName: String
|
||||||
|
get() = disambiguateName("binaries")
|
||||||
|
|
||||||
|
override val publishable: Boolean
|
||||||
|
get() = konanTarget.enabledOnCurrentHost
|
||||||
|
|
||||||
|
// User-visible constants
|
||||||
|
val DEBUG = NativeBuildType.DEBUG
|
||||||
|
val RELEASE = NativeBuildType.RELEASE
|
||||||
|
|
||||||
|
val EXECUTABLE = NativeOutputKind.EXECUTABLE
|
||||||
|
val FRAMEWORK = NativeOutputKind.FRAMEWORK
|
||||||
|
val DYNAMIC = NativeOutputKind.DYNAMIC
|
||||||
|
val STATIC = NativeOutputKind.STATIC
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val konanTargetAttribute = Attribute.of(
|
||||||
|
"org.jetbrains.kotlin.native.target",
|
||||||
|
String::class.java
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user