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