[Gradle] Implement KotlinJvmCompilation with new underlying KotlinCompilationImpl

KT-54312
This commit is contained in:
Sebastian Sellmair
2022-09-28 13:40:54 +02:00
committed by Space Team
parent 35dacd6add
commit a67b2a8be5
45 changed files with 1246 additions and 281 deletions
+1
View File
@@ -2,6 +2,7 @@
<dictionary name="sebastiansellmair">
<words>
<w>actuals</w>
<w>associator</w>
<w>cinterops</w>
<w>instantiator</w>
<w>interops</w>
@@ -9,6 +9,7 @@ package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Action
import org.gradle.api.Named
import org.gradle.api.Project
import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.attributes.HasAttributes
import org.gradle.api.file.FileCollection
@@ -20,6 +21,9 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
interface KotlinCompilation<out T : KotlinCommonOptionsDeprecated> : Named,
HasAttributes,
HasKotlinDependencies {
val project: Project
val target: KotlinTarget
val compilationName: String
@@ -40,6 +44,10 @@ interface KotlinCompilation<out T : KotlinCommonOptionsDeprecated> : Named,
var compileDependencyFiles: FileCollection
val runtimeDependencyConfigurationName: String?
val runtimeDependencyFiles: FileCollection?
val output: KotlinCompilationOutput
val platformType get() = target.platformType
@@ -113,15 +121,18 @@ interface KotlinCompilation<out T : KotlinCommonOptionsDeprecated> : Named,
get() = target.disambiguationClassifier + name
}
// TODO NOW: Revisit/Remove?
interface KotlinCompilationToRunnableFiles<T : KotlinCommonOptionsDeprecated> : KotlinCompilation<T> {
val runtimeDependencyConfigurationName: String
override val runtimeDependencyConfigurationName: String
var runtimeDependencyFiles: FileCollection
override var runtimeDependencyFiles: FileCollection
override val relatedConfigurationNames: List<String>
get() = super.relatedConfigurationNames + runtimeDependencyConfigurationName
}
@Deprecated("Scheduled for removal with Kotlin 1.9")
@Suppress("EXTENSION_SHADOWED_BY_MEMBER") // kept for compatibility
val <T : KotlinCommonOptionsDeprecated> KotlinCompilation<T>.runtimeDependencyConfigurationName: String?
get() = (this as? KotlinCompilationToRunnableFiles<T>)?.runtimeDependencyConfigurationName
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Project
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.dsl.CompilerJsOptionsDefault
import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
@@ -29,7 +28,7 @@ internal open class Kotlin2JsPlugin(
project: Project,
compilation: AbstractKotlinCompilation<*>
): KotlinSourceSetProcessor<*> =
Kotlin2JsSourceSetProcessor(tasksProvider, compilation)
Kotlin2JsSourceSetProcessor(tasksProvider, KotlinCompilationProjection(compilation))
override fun apply(project: Project) {
@Suppress("UNCHECKED_CAST")
@@ -10,7 +10,6 @@ import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.dsl.CompilerJsOptions
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
import org.jetbrains.kotlin.gradle.tasks.configuration.Kotlin2JsCompileConfig
@@ -18,41 +17,39 @@ import java.io.File
internal class Kotlin2JsSourceSetProcessor(
tasksProvider: KotlinTasksProvider,
kotlinCompilation: KotlinCompilationData<*>
kotlinCompilation: KotlinCompilationProjection
) : KotlinSourceSetProcessor<Kotlin2JsCompile>(
tasksProvider,
taskDescription = "Compiles the Kotlin sources in $kotlinCompilation to JavaScript.",
kotlinCompilation = kotlinCompilation
) {
override fun doRegisterTask(project: Project, taskName: String): TaskProvider<out Kotlin2JsCompile> {
val configAction = Kotlin2JsCompileConfig(kotlinCompilation)
val configAction = Kotlin2JsCompileConfig(compilationProjection)
applyStandardTaskConfiguration(configAction)
return tasksProvider.registerKotlinJSTask(
project,
taskName,
kotlinCompilation.compilerOptions.options as CompilerJsOptions,
compilationProjection.compilerOptions.options as CompilerJsOptions,
configAction
)
}
override fun doTargetSpecificProcessing() {
project.tasks.named(kotlinCompilation.compileAllTaskName).configure {
project.tasks.named(compilationProjection.compileAllTaskName).configure {
it.dependsOn(kotlinTask)
}
if (kotlinCompilation is KotlinWithJavaCompilation<*, *>) {
kotlinCompilation.javaSourceSet.clearJavaSrcDirs()
}
compilationProjection.tcsOrNull?.compilation?.run { this as? KotlinWithJavaCompilation<*, *> }?.javaSourceSet?.clearJavaSrcDirs()
project.whenEvaluated {
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project)
if (kotlinCompilation is KotlinCompilation<*>) { // FIXME support compiler plugins with PM20
subpluginEnvironment.addSubpluginOptions(project, kotlinCompilation)
/* Not supported in KPM */
compilationProjection.tcsOrNull?.compilation?.let { compilation ->
subpluginEnvironment.addSubpluginOptions(project, compilation)
}
}
}
}
private fun SourceSet.clearJavaSrcDirs() {
@@ -13,7 +13,6 @@ import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.compile.AbstractCompile
import org.jetbrains.kotlin.gradle.dsl.CompilerJvmOptions
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.scripting.internal.ScriptingGradleSubplugin
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
@@ -23,33 +22,34 @@ import org.jetbrains.kotlin.gradle.utils.whenKaptEnabled
internal class Kotlin2JvmSourceSetProcessor(
tasksProvider: KotlinTasksProvider,
kotlinCompilation: KotlinCompilationData<*>
kotlinCompilation: KotlinCompilationProjection
) : KotlinSourceSetProcessor<KotlinCompile>(
tasksProvider, "Compiles the $kotlinCompilation.", kotlinCompilation
) {
override fun doRegisterTask(project: Project, taskName: String): TaskProvider<out KotlinCompile> {
val configAction = KotlinCompileConfig(kotlinCompilation)
val configAction = KotlinCompileConfig(compilationProjection)
applyStandardTaskConfiguration(configAction)
return tasksProvider.registerKotlinJVMTask(
project,
taskName,
kotlinCompilation.compilerOptions.options as CompilerJvmOptions,
compilationProjection.compilerOptions.options as CompilerJvmOptions,
configAction
)
}
override fun doTargetSpecificProcessing() {
project.whenKaptEnabled {
Kapt3GradleSubplugin.createAptConfigurationIfNeeded(project, kotlinCompilation.compilationPurpose)
Kapt3GradleSubplugin.createAptConfigurationIfNeeded(project, compilationProjection.compilationName)
}
ScriptingGradleSubplugin.configureForSourceSet(project, kotlinCompilation.compilationPurpose)
ScriptingGradleSubplugin.configureForSourceSet(project, compilationProjection.compilationName)
project.whenEvaluated {
val subpluginEnvironment = SubpluginEnvironment.loadSubplugins(project)
if (kotlinCompilation is KotlinCompilation<*>) // FIXME support compiler plugins with PM20
subpluginEnvironment.addSubpluginOptions(project, kotlinCompilation)
/* Not supported in KPM yet */
compilationProjection.tcsOrNull?.compilation?.let { compilation ->
subpluginEnvironment.addSubpluginOptions(project, compilation)
}
javaSourceSet?.let { java ->
val javaTask = project.tasks.withType<AbstractCompile>().named(java.compileJavaTaskName)
@@ -24,7 +24,7 @@ internal open class KotlinCommonPlugin(
project: Project,
compilation: AbstractKotlinCompilation<*>
): KotlinSourceSetProcessor<*> =
KotlinCommonSourceSetProcessor(compilation, tasksProvider)
KotlinCommonSourceSetProcessor(KotlinCompilationProjection(compilation), tasksProvider)
override fun apply(project: Project) {
@Suppress("UNCHECKED_CAST")
@@ -9,9 +9,6 @@ import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.dsl.CompilerMultiplatformCommonOptions
import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.isMainCompilationData
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileCommon
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
import org.jetbrains.kotlin.gradle.tasks.configuration.KotlinCompileCommonConfig
@@ -19,33 +16,36 @@ import org.jetbrains.kotlin.gradle.tasks.dependsOn
import org.jetbrains.kotlin.gradle.tasks.locateTask
internal class KotlinCommonSourceSetProcessor(
compilation: KotlinCompilationData<*>,
compilation: KotlinCompilationProjection,
tasksProvider: KotlinTasksProvider
) : KotlinSourceSetProcessor<KotlinCompileCommon>(
tasksProvider, taskDescription = "Compiles the kotlin sources in $compilation to Metadata.", kotlinCompilation = compilation
) {
override fun doTargetSpecificProcessing() {
project.tasks.named(kotlinCompilation.compileAllTaskName).dependsOn(kotlinTask)
project.tasks.named(compilationProjection.compileAllTaskName).dependsOn(kotlinTask)
// can be missing (e.g. in case of tests)
if ((kotlinCompilation as? AbstractKotlinCompilation<*>)?.isMainCompilationData() == true) {
project.locateTask<Task>(kotlinCompilation.target.artifactsTaskName)?.dependsOn(kotlinTask)
if (compilationProjection.isMain) {
compilationProjection.tcsOrNull?.compilation?.target?.let { target ->
project.locateTask<Task>(target.artifactsTaskName)?.dependsOn(kotlinTask)
}
}
if (kotlinCompilation is KotlinCompilation<*>) {
project.whenEvaluated {
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project)
subpluginEnvironment.addSubpluginOptions(project, kotlinCompilation)
project.whenEvaluated {
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project)
/* Not supported in KPM yet */
compilationProjection.tcsOrNull?.compilation?.let { compilation ->
subpluginEnvironment.addSubpluginOptions(project, compilation)
}
}
}
override fun doRegisterTask(project: Project, taskName: String): TaskProvider<out KotlinCompileCommon> {
val configAction = KotlinCompileCommonConfig(kotlinCompilation)
val configAction = KotlinCompileCommonConfig(compilationProjection)
applyStandardTaskConfiguration(configAction)
return tasksProvider.registerKotlinCommonTask(
project,
taskName,
kotlinCompilation.compilerOptions.options as CompilerMultiplatformCommonOptions,
compilationProjection.compilerOptions.options as CompilerMultiplatformCommonOptions,
configAction
)
}
@@ -11,17 +11,17 @@ import org.gradle.api.provider.Provider
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleJavaTargetExtension
import org.jetbrains.kotlin.gradle.dsl.topLevelExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompileTool
abstract class KotlinCompilationProcessor<out T : AbstractKotlinCompileTool<*>>(
open val kotlinCompilation: KotlinCompilationData<*>
abstract class KotlinCompilationProcessor<out T : AbstractKotlinCompileTool<*>> internal constructor(
internal val compilationProjection: KotlinCompilationProjection
) {
abstract val kotlinTask: TaskProvider<out T>
abstract fun run()
protected val project: Project
get() = kotlinCompilation.project
get() = compilationProjection.project
protected val defaultKotlinDestinationDir: Provider<Directory>
get() {
@@ -30,7 +30,7 @@ abstract class KotlinCompilationProcessor<out T : AbstractKotlinCompileTool<*>>(
if (kotlinExt is KotlinSingleJavaTargetExtension)
"" // In single-target projects, don't add the target name part to this path
else
kotlinCompilation.compilationClassifier?.let { "$it/" }.orEmpty()
return project.layout.buildDirectory.dir("classes/kotlin/$targetSubDirectory${kotlinCompilation.compilationPurpose}")
compilationProjection.targetDisambiguationClassifier?.let { "$it/" }.orEmpty()
return project.layout.buildDirectory.dir("classes/kotlin/$targetSubDirectory${compilationProjection.compilationName}")
}
}
}
@@ -0,0 +1,155 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("FunctionName")
package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Project
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.FileCollection
import org.gradle.api.file.SourceDirectorySet
import org.jetbrains.kotlin.gradle.plugin.mpp.internal
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.isMainCompilationData
import org.jetbrains.kotlin.gradle.utils.filesProvider
import org.jetbrains.kotlin.project.model.LanguageSettings
internal sealed class KotlinCompilationProjection {
abstract val origin: Any
abstract val project: Project
abstract val platformType: KotlinPlatformType
abstract val targetDisambiguationClassifier: String?
abstract val compilationName: String
abstract val ownModuleName: String
abstract val moduleName: String
abstract val compilerOptions: HasCompilerOptions<*>
abstract val compileKotlinTaskName: String
abstract val compileAllTaskName: String
abstract val languageSettings: LanguageSettings
abstract val friendPaths: FileCollection
abstract val isMain: Boolean
abstract val classesDirs: ConfigurableFileCollection
abstract val compileDependencyFiles: FileCollection
abstract val sources: List<SourceDirectorySet>
class TCS(val compilation: KotlinCompilation<*>) : KotlinCompilationProjection() {
override val origin: KotlinCompilation<*> = compilation
override val project: Project
get() = origin.project
override val platformType: KotlinPlatformType
get() = origin.platformType
override val targetDisambiguationClassifier: String?
get() = origin.target.disambiguationClassifier
override val compilationName: String
get() = origin.compilationName
override val ownModuleName: String
get() = origin.internal.compilationModule.ownModuleName.get()
override val moduleName: String
get() = origin.internal.moduleName
override val compilerOptions: HasCompilerOptions<*>
get() = origin.compilerOptions
override val compileKotlinTaskName: String
get() = origin.compileKotlinTaskName
override val compileAllTaskName: String
get() = origin.compileAllTaskName
override val languageSettings: LanguageSettings
get() = origin.defaultSourceSet.languageSettings
override val friendPaths: FileCollection
get() = project.filesProvider { origin.internal.friendPaths }
override val isMain: Boolean
get() = origin.isMain()
override val classesDirs: ConfigurableFileCollection
get() = origin.output.classesDirs
override val compileDependencyFiles: FileCollection
get() = project.filesProvider { origin.compileDependencyFiles }
override val sources: List<SourceDirectorySet>
get() = origin.allKotlinSourceSets.map { it.kotlin }
}
class KPM(val compilationData: KotlinCompilationData<*>) : KotlinCompilationProjection() {
override val origin: KotlinCompilationData<*> = compilationData
override val project: Project
get() = origin.project
override val platformType: KotlinPlatformType
get() = origin.platformType
override val targetDisambiguationClassifier: String?
get() = origin.compilationClassifier
override val compilationName: String
get() = origin.compilationPurpose
override val ownModuleName: String
get() = origin.ownModuleName
override val moduleName: String
get() = origin.moduleName
override val compilerOptions: HasCompilerOptions<*>
get() = origin.compilerOptions
override val compileKotlinTaskName: String
get() = origin.compileKotlinTaskName
override val compileAllTaskName: String
get() = origin.compileAllTaskName
override val languageSettings: LanguageSettings
get() = origin.languageSettings
override val friendPaths: FileCollection
get() = project.filesProvider { origin.friendPaths }
override val isMain: Boolean
get() = origin.isMainCompilationData()
override val classesDirs: ConfigurableFileCollection
get() = origin.output.classesDirs
override val compileDependencyFiles: FileCollection
get() = project.filesProvider { origin.compileDependencyFiles }
override val sources: List<SourceDirectorySet>
get() = origin.kotlinSourceDirectoriesByFragmentName.values.toList()
}
}
internal fun KotlinCompilationProjection(compilation: KotlinCompilation<*>): KotlinCompilationProjection.TCS {
return KotlinCompilationProjection.TCS(compilation)
}
internal val KotlinCompilationProjection.tcsOrNull: KotlinCompilationProjection.TCS?
get() = when (this) {
is KotlinCompilationProjection.KPM -> null
is KotlinCompilationProjection.TCS -> this
}
internal val KotlinCompilationProjection.kpmOrNull: KotlinCompilationProjection.KPM?
get() = when (this) {
is KotlinCompilationProjection.KPM -> this
is KotlinCompilationProjection.TCS -> null
}
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Project
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.dsl.CompilerJsOptions
import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinCompilation
import org.jetbrains.kotlin.gradle.targets.js.ir.JsIrBinary
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrCompilation
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
@@ -18,28 +17,28 @@ import org.jetbrains.kotlin.gradle.tasks.configuration.KotlinJsIrLinkConfig
internal class KotlinJsIrSourceSetProcessor(
tasksProvider: KotlinTasksProvider,
kotlinCompilation: AbstractKotlinCompilation<*>
kotlinCompilation: KotlinCompilationProjection
) : KotlinSourceSetProcessor<Kotlin2JsCompile>(
tasksProvider, taskDescription = "Compiles the Kotlin sources in $kotlinCompilation to JavaScript.",
kotlinCompilation = kotlinCompilation
) {
override fun doRegisterTask(project: Project, taskName: String): TaskProvider<out Kotlin2JsCompile> {
val configAction = Kotlin2JsCompileConfig(kotlinCompilation)
val configAction = Kotlin2JsCompileConfig(compilationProjection)
applyStandardTaskConfiguration(configAction)
return tasksProvider.registerKotlinJSTask(
project,
taskName,
kotlinCompilation.compilerOptions.options as CompilerJsOptions,
compilationProjection.compilerOptions.options as CompilerJsOptions,
configAction
)
}
override fun doTargetSpecificProcessing() {
project.tasks.named(kotlinCompilation.compileAllTaskName).configure {
project.tasks.named(compilationProjection.compileAllTaskName).configure {
it.dependsOn(kotlinTask)
}
val compilation = kotlinCompilation as KotlinJsIrCompilation
val compilation = compilationProjection.tcsOrNull?.compilation as KotlinJsIrCompilation
compilation.binaries
.withType(JsIrBinary::class.java)
@@ -47,7 +46,7 @@ internal class KotlinJsIrSourceSetProcessor(
val configAction = KotlinJsIrLinkConfig(binary)
configAction.configureTask {
it.description = taskDescription
it.libraries.from({ kotlinCompilation.compileDependencyFiles })
it.libraries.from({ compilationProjection.compileDependencyFiles })
}
configAction.configureTask { task ->
task.modeProperty.set(binary.mode)
@@ -59,7 +58,11 @@ internal class KotlinJsIrSourceSetProcessor(
project.whenEvaluated {
val subpluginEnvironment: SubpluginEnvironment = SubpluginEnvironment.loadSubplugins(project)
subpluginEnvironment.addSubpluginOptions(project, kotlinCompilation)
/* Not supported in KPM, yet */
compilationProjection.tcsOrNull?.compilation?.let { compilation ->
subpluginEnvironment.addSubpluginOptions(project, compilation)
}
}
}
}
@@ -38,7 +38,7 @@ internal open class KotlinJvmPlugin(
}
override fun buildSourceSetProcessor(project: Project, compilation: AbstractKotlinCompilation<*>) =
Kotlin2JvmSourceSetProcessor(tasksProvider, compilation)
Kotlin2JvmSourceSetProcessor(tasksProvider, KotlinCompilationProjection(compilation))
override fun apply(project: Project) {
@Suppress("UNCHECKED_CAST")
@@ -15,7 +15,6 @@ import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.plugin.internal.JavaSourceSetsAccessor
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
@@ -27,39 +26,41 @@ import java.util.concurrent.Callable
internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
val tasksProvider: KotlinTasksProvider,
val taskDescription: String,
kotlinCompilation: KotlinCompilationData<*>
kotlinCompilation: KotlinCompilationProjection
) : KotlinCompilationProcessor<T>(kotlinCompilation) {
protected abstract fun doTargetSpecificProcessing()
protected val logger = Logging.getLogger(this.javaClass)!!
protected val sourceSetName: String = kotlinCompilation.compilationPurpose
protected val sourceSetName: String = kotlinCompilation.compilationName
override val kotlinTask: TaskProvider<out T> = prepareKotlinCompileTask()
protected val javaSourceSet: SourceSet?
get() {
val compilation = kotlinCompilation
if (compilationProjection !is KotlinCompilationProjection.TCS) return null
val compilation = compilationProjection.origin
val target = compilationProjection.origin.target
return (compilation as? KotlinWithJavaCompilation<*, *>)?.javaSourceSet
?: kotlinCompilation.owner.let {
if (it is KotlinJvmTarget && it.withJavaEnabled && compilation is KotlinJvmCompilation)
project.gradle.variantImplementationFactory<JavaSourceSetsAccessor.JavaSourceSetsAccessorVariantFactory>()
.getInstance(project)
.sourceSets
.maybeCreate(compilation.name)
else null
}
?: if (target is KotlinJvmTarget && target.withJavaEnabled && compilation is KotlinJvmCompilation)
project.gradle.variantImplementationFactory<JavaSourceSetsAccessor.JavaSourceSetsAccessorVariantFactory>()
.getInstance(project)
.sourceSets
.maybeCreate(compilation.name)
else null
}
private fun prepareKotlinCompileTask(): TaskProvider<out T> =
doRegisterTask(project, kotlinCompilation.compileKotlinTaskName).also { task ->
kotlinCompilation.output.classesDirs.from(task.flatMap { it.destinationDirectory })
doRegisterTask(project, compilationProjection.compileKotlinTaskName).also { task ->
compilationProjection.classesDirs.from(task.flatMap { it.destinationDirectory })
}
override fun run() {
addKotlinDirectoriesToJavaSourceSet()
doTargetSpecificProcessing()
if (kotlinCompilation is KotlinWithJavaCompilation<*, *>) {
if (compilationProjection.tcsOrNull?.compilation is KotlinWithJavaCompilation<*, *>) {
createAdditionalClassesTaskForIdeRunner()
}
}
@@ -69,7 +70,7 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
// Try to avoid duplicate Java sources in allSource; run lazily to allow changing the directory set:
val kotlinSrcDirsToAdd = Callable {
kotlinCompilation.kotlinSourceDirectoriesByFragmentName.values.map { filterOutJavaSrcDirsIfPossible(it) }
compilationProjection.sources.map { filterOutJavaSrcDirsIfPossible(it) }
}
java.allJava.srcDirs(kotlinSrcDirsToAdd)
@@ -84,7 +85,7 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
}
private fun createAdditionalClassesTaskForIdeRunner() {
val kotlinCompilation = kotlinCompilation as? KotlinCompilation<*> ?: return
val kotlinCompilation = compilationProjection.tcsOrNull?.compilation ?: return
open class IDEClassesTask : DefaultTask()
// Workaround: as per KT-26641, when there's a Kotlin compilation with a Java source set, we create another task
@@ -108,7 +109,7 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
} else {
it.destinationDirectory.convention(defaultKotlinDestinationDir)
}
it.libraries.from({ kotlinCompilation.compileDependencyFiles })
it.libraries.from({ compilationProjection.compileDependencyFiles })
}
}
@@ -30,6 +30,7 @@ import org.gradle.language.jvm.tasks.ProcessResources
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.internal.reorderPluginClasspathDependencies
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsCompilerAttribute
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsTarget
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrTarget
@@ -106,6 +107,10 @@ abstract class AbstractKotlinTargetConfigurator<KotlinTargetType : KotlinTarget>
val project = target.project
target.compilations.all { compilation ->
compilation.internal.allKotlinSourceSets.forAll { sourceSet ->
sourceSet.internal.compilations.add(compilation)
}
defineConfigurationsForCompilation(compilation)
if (compilation is KotlinCompilationWithResources) {
@@ -297,6 +302,8 @@ abstract class AbstractKotlinTargetConfigurator<KotlinTargetType : KotlinTarget>
val apiConfiguration = configurations.maybeCreate(compilation.apiConfigurationName).apply {
compileConfiguration?.let { extendsFrom(it) }
// TODP NOW: Remove duplicate
isVisible = false
isCanBeConsumed = false
isCanBeResolved = false
@@ -50,6 +50,7 @@ abstract class AbstractKotlinCompilation<T : KotlinCommonOptions>(
final override val output: KotlinCompilationOutput get() = compilationData.output
final override val compileKotlinTaskName: String get() = compilationData.compileKotlinTaskName
override val compilerOptions: HasCompilerOptions<*>
get() = compilationData.compilerOptions
@@ -71,7 +72,7 @@ abstract class AbstractKotlinCompilation<T : KotlinCommonOptions>(
}
final override val kotlinSourceSets: ObservableSet<KotlinSourceSet>
get() = compilationDetails.directlyIncludedKotlinSourceSets
get() = compilationDetails.kotlinSourceSets
override val allKotlinSourceSets: ObservableSet<KotlinSourceSet>
get() = compilationDetails.allKotlinSourceSets
@@ -28,7 +28,7 @@ interface CompilationDetails<T : KotlinCommonOptions> {
fun source(sourceSet: KotlinSourceSet)
val directlyIncludedKotlinSourceSets: ObservableSet<KotlinSourceSet>
val kotlinSourceSets: ObservableSet<KotlinSourceSet>
val allKotlinSourceSets: ObservableSet<KotlinSourceSet>
@@ -5,14 +5,33 @@
package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.file.FileCollection
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationModuleManager
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationModuleManager.CompilationModule.Type.Auxiliary
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationModuleManager.CompilationModule.Type.Main
import org.jetbrains.kotlin.gradle.utils.ObservableSet
internal interface InternalKotlinCompilation<T : KotlinCommonOptions> : KotlinCompilation<T> {
internal interface InternalKotlinCompilation<out T : KotlinCommonOptions> : KotlinCompilation<T> {
override val kotlinSourceSets: ObservableSet<KotlinSourceSet>
override val allKotlinSourceSets: ObservableSet<KotlinSourceSet>
val friendPaths: Iterable<FileCollection>
// TODO NOW: Remove default impl
val compilationModule: KotlinCompilationModuleManager.CompilationModule
get() = KotlinCompilationModuleManager.CompilationModule(
compilationName = compilationName,
ownModuleName = project.provider { (this as AbstractKotlinCompilation<*>).ownModuleName },
type = if (isMain()) Main else Auxiliary
)
// TODO NOW: Remove default impl
override val runtimeDependencyFiles: FileCollection? get() = null
override val runtimeDependencyConfigurationName: String? get() = null
val processResourcesTaskName: String? get() = null
}
internal val <T : KotlinCommonOptions> KotlinCompilation<T>.internal: InternalKotlinCompilation<T>
@@ -18,7 +18,7 @@ internal abstract class AbstractCompilationDetails<T : KotlinCommonOptions>(
) : CompilationDetails<T> {
private val directlyIncludedKotlinSourceSetsImpl: MutableObservableSet<KotlinSourceSet> = MutableObservableSetImpl(defaultSourceSet)
final override val directlyIncludedKotlinSourceSets: ObservableSet<KotlinSourceSet>
final override val kotlinSourceSets: ObservableSet<KotlinSourceSet>
get() = directlyIncludedKotlinSourceSetsImpl
private val allKotlinSourceSetsImpl: MutableObservableSet<KotlinSourceSet> = MutableObservableSetImpl<KotlinSourceSet>().also { set ->
@@ -17,10 +17,9 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinDependencyConfigurationsHolder
import org.jetbrains.kotlin.gradle.plugin.mpp.addSourcesToKotlinCompileTask
import org.jetbrains.kotlin.gradle.plugin.mpp.filterModuleName
import org.jetbrains.kotlin.gradle.plugin.mpp.internal.KotlinCompilationsModuleGroups
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationModuleManager
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationModuleManager.CompilationModule.Type
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.kotlinCompilationModuleManager
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.isMainCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.GradleKpmDependencyFilesHolder
@@ -80,7 +79,7 @@ internal open class DefaultCompilationDetails<T : KotlinCommonOptions, CO : Comp
get() = target.disambiguationClassifier
override val kotlinSourceDirectoriesByFragmentName: Map<String, SourceDirectorySet>
get() = directlyIncludedKotlinSourceSets.withDependsOnClosure.associate { it.name to it.kotlin }
get() = kotlinSourceSets.withDependsOnClosure.associate { it.name to it.kotlin }
override val compileKotlinTaskName: String
get() = lowerCamelCaseName(
@@ -107,16 +106,22 @@ internal open class DefaultCompilationDetails<T : KotlinCommonOptions, CO : Comp
override val platformType: KotlinPlatformType
get() = target.platformType
override val moduleName: String
get() = KotlinCompilationsModuleGroups.getModuleLeaderCompilation(this).takeIf { it != this }?.ownModuleName ?: ownModuleName
override val ownModuleName: String
get() {
private val compilationModule = KotlinCompilationModuleManager.CompilationModule(
ownModuleName = project.provider {
val baseName = project.archivesName.orNull
?: project.name
val suffix = if (isMainCompilationData()) "" else "_$compilationPurpose"
return filterModuleName("$baseName$suffix")
}
filterModuleName("$baseName$suffix")
},
compilationName = compilationPurpose,
type = if (isMainCompilationData()) Type.Main else Type.Auxiliary
)
override val moduleName: String
get() = project.kotlinCompilationModuleManager.getModuleLeader(compilationModule).ownModuleName.get()
override val ownModuleName: String
get() = compilationModule.ownModuleName.get()
override val friendPaths: Iterable<FileCollection>
get() = mutableListOf<FileCollection>().also { allCollections ->
@@ -169,7 +174,7 @@ internal open class DefaultCompilationDetails<T : KotlinCommonOptions, CO : Comp
require(other.target == target) { "Only associations between compilations of a single target are supported" }
_associateCompilations += other
addAssociateCompilationDependencies(other.compilation)
KotlinCompilationsModuleGroups.unionModules(this, other.compilationData)
project.kotlinCompilationModuleManager.unionModules(this.compilationModule, other.compilation.internal.compilationModule)
_associateCompilations.add(other)
}
@@ -0,0 +1,95 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.compilationImpl
import org.gradle.api.Project
import org.gradle.api.artifacts.Dependency
import org.gradle.api.tasks.SourceSet
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.InternalKotlinCompilation
import org.jetbrains.kotlin.gradle.utils.filesProvider
internal fun interface KotlinCompilationAssociator {
fun associate(target: KotlinTarget, first: InternalKotlinCompilation<*>, second: InternalKotlinCompilation<*>)
}
internal object DefaultKotlinCompilationAssociator : KotlinCompilationAssociator {
override fun associate(target: KotlinTarget, first: InternalKotlinCompilation<*>, second: InternalKotlinCompilation<*>) {
target.project.kotlinCompilationModuleManager.unionModules(first.compilationModule, second.compilationModule)
val project = target.project
/*
we add dependencies to compileDependencyConfiguration ('compileClasspath' usually) and runtimeDependency
('runtimeClasspath') instead of modifying respective api/implementation/compileOnly/runtimeOnly configs
This is needed because api/implementation/compileOnly/runtimeOnly are used in IDE Import and will leak
to dependencies of IDE modules. But they are not needed here, because IDE resolution works inherently
transitively and symbols from associated compilation will be resolved from source sets of associated
compilation itself (moreover, direct dependencies are not equivalent to transitive ones because of
resolution order - e.g. in case of FQNs clash, so it's even harmful)
*/
project.dependencies.add(first.compileOnlyConfigurationName, project.files({ second.output.classesDirs }))
project.dependencies.add(first.runtimeOnlyConfigurationName, project.files({ second.output.allOutputs }))
first.compileDependencyConfigurationName.addAllDependenciesFromOtherConfigurations(
project,
second.apiConfigurationName,
second.implementationConfigurationName,
second.compileOnlyConfigurationName
)
first.runtimeDependencyConfigurationName?.addAllDependenciesFromOtherConfigurations(
project,
second.apiConfigurationName,
second.implementationConfigurationName,
second.runtimeOnlyConfigurationName
)
}
/**
* Adds `allDependencies` of configurations mentioned in `configurationNames` to configuration named [this] in
* a lazy manner
*/
private fun String.addAllDependenciesFromOtherConfigurations(project: Project, vararg configurationNames: String) {
project.configurations.named(this).configure { receiverConfiguration ->
receiverConfiguration.dependencies.addAllLater(
project.objects.listProperty(Dependency::class.java).apply {
set(
project.provider {
configurationNames
.map { project.configurations.getByName(it) }
.flatMap { it.allDependencies }
}
)
}
)
}
}
}
internal object KotlinNativeCompilationAssociator : KotlinCompilationAssociator {
override fun associate(target: KotlinTarget, first: InternalKotlinCompilation<*>, second: InternalKotlinCompilation<*>) {
target.project.kotlinCompilationModuleManager.unionModules(first.compilationModule, second.compilationModule)
first.compileDependencyFiles +=
second.output.classesDirs + target.project.filesProvider { second.compileDependencyFiles }
target.project.configurations.named(first.implementationConfigurationName).configure { configuration ->
configuration.extendsFrom(target.project.configurations.findByName(second.implementationConfigurationName))
}
}
}
internal object KotlinJvmWithJavaCompilationAssociator : KotlinCompilationAssociator {
override fun associate(target: KotlinTarget, first: InternalKotlinCompilation<*>, second: InternalKotlinCompilation<*>) {
target.project.kotlinCompilationModuleManager.unionModules(first.compilationModule, second.compilationModule)
if (first.compilationName != SourceSet.TEST_SOURCE_SET_NAME || second.compilationName != SourceSet.MAIN_SOURCE_SET_NAME) {
DefaultKotlinCompilationAssociator.associate(target, first, second)
} // otherwise, do nothing: the Java Gradle plugin adds these dependencies for us, we don't need to add them to the classpath
}
}
@@ -0,0 +1,53 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.compilationImpl
import org.gradle.api.Action
import org.gradle.api.Project
import org.gradle.api.artifacts.Configuration
import org.jetbrains.kotlin.gradle.plugin.HasKotlinDependencies
import org.jetbrains.kotlin.gradle.plugin.KotlinDependencyHandler
import org.jetbrains.kotlin.gradle.plugin.mpp.DefaultKotlinDependencyHandler
internal interface KotlinCompilationDependencyConfigurationsContainer {
val apiConfiguration: Configuration
val implementationConfiguration: Configuration
val compileOnlyConfiguration: Configuration
val runtimeOnlyConfiguration: Configuration
val compileDependencyConfiguration: Configuration
val runtimeDependencyConfiguration: Configuration?
}
internal class DefaultKotlinCompilationDependencyConfigurationsContainer(
override val apiConfiguration: Configuration,
override val implementationConfiguration: Configuration,
override val compileOnlyConfiguration: Configuration,
override val runtimeOnlyConfiguration: Configuration,
override val compileDependencyConfiguration: Configuration,
override val runtimeDependencyConfiguration: Configuration?
) : KotlinCompilationDependencyConfigurationsContainer
internal fun HasKotlinDependencies(
project: Project, compilationDependencyContainer: KotlinCompilationDependencyConfigurationsContainer
): HasKotlinDependencies = object : HasKotlinDependencies {
override fun dependencies(configure: KotlinDependencyHandler.() -> Unit): Unit =
DefaultKotlinDependencyHandler(this, project).run(configure)
override fun dependencies(configure: Action<KotlinDependencyHandler>) =
dependencies { configure.execute(this) }
override val apiConfigurationName: String
get() = compilationDependencyContainer.apiConfiguration.name
override val implementationConfigurationName: String
get() = compilationDependencyContainer.implementationConfiguration.name
override val compileOnlyConfigurationName: String
get() = compilationDependencyContainer.compileOnlyConfiguration.name
override val runtimeOnlyConfigurationName: String
get() = compilationDependencyContainer.runtimeOnlyConfiguration.name
}
@@ -0,0 +1,41 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.compilationImpl
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.TaskProvider
import org.gradle.api.tasks.bundling.AbstractArchiveTask
import org.jetbrains.kotlin.gradle.plugin.mpp.InternalKotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithClosure
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
import org.jetbrains.kotlin.gradle.utils.filesProvider
internal interface KotlinCompilationFriendPathsResolver {
fun resolveFriendPaths(compilation: InternalKotlinCompilation<*>): Iterable<FileCollection>
}
internal object DefaultKotlinCompilationFriendPathsResolver : KotlinCompilationFriendPathsResolver {
override fun resolveFriendPaths(compilation: InternalKotlinCompilation<*>): Iterable<FileCollection> {
return mutableListOf<FileCollection>().also { allCollections ->
compilation.associateWithClosure.forEach { allCollections.add(it.output.classesDirs) }
allCollections.add(resolveFriendArtifacts(compilation))
}
}
private fun resolveFriendArtifacts(compilation: InternalKotlinCompilation<*>): FileCollection {
return with(compilation.project) {
val friendArtifactsTaskProvider = resolveFriendArtifactsTask(compilation) ?: return files()
filesProvider { friendArtifactsTaskProvider.flatMap { it.archiveFile } }
}
}
private fun resolveFriendArtifactsTask(compilation: InternalKotlinCompilation<*>): TaskProvider<AbstractArchiveTask>? {
if (compilation.associateWithClosure.none { it.isMain() }) return null
val archiveTasks = compilation.project.tasks.withType(AbstractArchiveTask::class.java)
if (compilation.target.artifactsTaskName !in archiveTasks.names) return null
return archiveTasks.named(compilation.target.artifactsTaskName)
}
}
@@ -0,0 +1,223 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("DEPRECATION")
package org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl
import org.gradle.api.Action
import org.gradle.api.GradleException
import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.HierarchyAttributeContainer
import org.jetbrains.kotlin.gradle.plugin.mpp.InternalKotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.internal
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
import org.jetbrains.kotlin.gradle.tasks.locateTask
import org.jetbrains.kotlin.gradle.utils.ObservableSet
import javax.inject.Inject
internal class KotlinCompilationImpl @Inject constructor(
private val params: Params
) : InternalKotlinCompilation<KotlinCommonOptions> {
//region Params
data class Params(
val target: KotlinTarget,
val compilationModule: KotlinCompilationModuleManager.CompilationModule,
val sourceSets: KotlinCompilationSourceSetsContainer,
val dependencyConfigurations: KotlinCompilationDependencyConfigurationsContainer,
val compilationTaskNames: KotlinCompilationTaskNameContainer,
val processResourcesTaskName: String?,
val output: KotlinCompilationOutput,
val compilerOptions: HasCompilerOptions<*>,
val kotlinOptions: KotlinCommonOptions,
val compilationAssociator: KotlinCompilationAssociator,
val compilationFriendPathsResolver: KotlinCompilationFriendPathsResolver,
val compilationSourceSetInclusion: KotlinCompilationSourceSetInclusion
)
//endregion
//region direct access / convenience properties
override val project get() = params.target.project
override val target: KotlinTarget
get() = params.target
val sourceSets get() = params.sourceSets
val dependencyConfigurations: KotlinCompilationDependencyConfigurationsContainer
get() = params.dependencyConfigurations
override val compilationName: String
get() = params.compilationModule.compilationName
override val output: KotlinCompilationOutput
get() = params.output
override val processResourcesTaskName: String?
get() = params.processResourcesTaskName
override val friendPaths: Iterable<FileCollection>
get() = params.compilationFriendPathsResolver.resolveFriendPaths(this)
//endregion
//region Implement Source Set Management
override val defaultSourceSet: KotlinSourceSet
get() = sourceSets.defaultSourceSet
override val allKotlinSourceSets: ObservableSet<KotlinSourceSet>
get() = sourceSets.allKotlinSourceSets
override val kotlinSourceSets: ObservableSet<KotlinSourceSet>
get() = sourceSets.kotlinSourceSets
override fun source(sourceSet: KotlinSourceSet) {
sourceSets.source(sourceSet)
}
override fun defaultSourceSet(configure: KotlinSourceSet.() -> Unit) {
defaultSourceSet.configure()
}
//endregion
//region Dependency Configuration Management
override val apiConfigurationName: String
get() = dependencyConfigurations.apiConfiguration.name
override val implementationConfigurationName: String
get() = dependencyConfigurations.implementationConfiguration.name
override val compileOnlyConfigurationName: String
get() = dependencyConfigurations.compileOnlyConfiguration.name
override val runtimeOnlyConfigurationName: String
get() = dependencyConfigurations.runtimeOnlyConfiguration.name
override val compileDependencyConfigurationName: String
get() = dependencyConfigurations.compileDependencyConfiguration.name
override val runtimeDependencyConfigurationName: String?
get() = dependencyConfigurations.runtimeDependencyConfiguration?.name
override var compileDependencyFiles: FileCollection = dependencyConfigurations.compileDependencyConfiguration
override var runtimeDependencyFiles: FileCollection? = dependencyConfigurations.runtimeDependencyConfiguration
override val relatedConfigurationNames: List<String> = listOfNotNull(
apiConfigurationName,
implementationConfigurationName,
compileOnlyConfigurationName,
runtimeOnlyConfigurationName,
compileDependencyConfigurationName,
runtimeDependencyConfigurationName
)
override fun dependencies(configure: KotlinDependencyHandler.() -> Unit) {
HasKotlinDependencies(project, dependencyConfigurations).dependencies(configure)
}
override fun dependencies(configure: Action<KotlinDependencyHandler>) {
HasKotlinDependencies(project, dependencyConfigurations).dependencies(configure)
}
//endregion
//region Compiler Module Management
override val compilationModule: KotlinCompilationModuleManager.CompilationModule
get() = params.compilationModule
override val moduleName: String
get() = project.kotlinCompilationModuleManager.getModuleLeader(compilationModule).ownModuleName.get()
//endregion
//region Compile Tasks
override val compileKotlinTaskName: String
get() = params.compilationTaskNames.compileTaskName
override val compileAllTaskName: String
get() = params.compilationTaskNames.compileAllTaskName
@Suppress("deprecation")
@Deprecated("Accessing task instance directly is deprecated", replaceWith = ReplaceWith("compileTaskProvider"))
override val compileKotlinTask: KotlinCompile<KotlinCommonOptions>
get() = compileKotlinTaskProvider.get()
@Suppress("deprecation")
@Deprecated("Replaced with compileTaskProvider", replaceWith = ReplaceWith("compileTaskProvider"))
override val compileKotlinTaskProvider: TaskProvider<out KotlinCompile<KotlinCommonOptions>>
get() = target.project.locateTask(compileKotlinTaskName) ?: throw GradleException("Couldn't locate task $compileKotlinTaskName")
override val compileTaskProvider: TaskProvider<out KotlinCompilationTask<*>>
get() = target.project.locateTask(compileKotlinTaskName) ?: throw GradleException("Couldn't locate task $compileKotlinTaskName")
//endregion
//region CompilerOptions & KotlinOptions
@Deprecated(message = "Replaced by compilerOptions", replaceWith = ReplaceWith("compilerOptions.options"))
override val kotlinOptions: KotlinCommonOptions
get() = params.kotlinOptions
override val compilerOptions: HasCompilerOptions<*>
get() = params.compilerOptions
//endregion
//region Attributes
private val attributes by lazy { HierarchyAttributeContainer(target.attributes) }
override fun getAttributes(): AttributeContainer = attributes
// endregion
private val associateWithImpl = mutableSetOf<KotlinCompilation<*>>()
override val associateWith: List<KotlinCompilation<*>>
get() = associateWithImpl.toList()
override fun associateWith(other: KotlinCompilation<*>) {
require(other.target == target) { "Only associations between compilations of a single target are supported" }
if (!associateWithImpl.add(other)) return
project.kotlinCompilationModuleManager.unionModules(this.compilationModule, other.internal.compilationModule)
params.compilationAssociator.associate(target, this, other.internal)
}
//region final init
init {
sourceSets.allKotlinSourceSets.forAll { sourceSet ->
params.compilationSourceSetInclusion.include(this, sourceSet)
}
}
//endregion
}
@@ -0,0 +1,62 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.compilationImpl
import org.gradle.api.Project
import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationModuleManager.CompilationModule
import org.jetbrains.kotlin.gradle.utils.getOrPut
import org.jetbrains.kotlin.tooling.core.withLinearClosure
/**
* This is a disjoint-set union-like approach to having a module name that is equal across associated compilations, as the compiler
* now requires that to properly compile internal calls to friend classes. Associating a compilation with another one leads to their
* disjoint sets being united, so their module names become equal, taken from the new leader compilation.
*/
internal interface KotlinCompilationModuleManager {
class CompilationModule(val compilationName: String, val ownModuleName: Provider<String>, val type: Type) {
enum class Type {
Main, /* Including tests */ Auxiliary
}
}
fun unionModules(first: CompilationModule, second: CompilationModule)
fun getModuleLeader(compilation: CompilationModule): CompilationModule
}
internal val Project.kotlinCompilationModuleManager: KotlinCompilationModuleManager
get() = extensions.extraProperties.getOrPut(KotlinCompilationModuleManager::class.java.name) {
DefaultKotlinCompilationModuleManager()
}
private class DefaultKotlinCompilationModuleManager : KotlinCompilationModuleManager {
private val leadingReferenceMap = mutableMapOf</*Follower compilationName*/String, /*Leader*/CompilationModule>()
override fun getModuleLeader(compilation: CompilationModule): CompilationModule {
return compilation.withLinearClosure { next -> leadingReferenceMap[next.compilationName] }.last()
}
override fun unionModules(first: CompilationModule, second: CompilationModule) {
val firstLeader = getModuleLeader(first)
val secondLeader = getModuleLeader(second)
if (firstLeader == secondLeader) return
val newLeaderCandidates = listOf(firstLeader, secondLeader)
/*
heuristically choose the new leader: choose `main` when possible, don't choose `*test*` when there's an alternative,
if that didn't work, choose the first name lexicographically
*/
val newLeader = newLeaderCandidates.singleOrNull { it.type == CompilationModule.Type.Main }
?: newLeaderCandidates.singleOrNull { it.compilationName.contains("main", true) }
?: newLeaderCandidates.singleOrNull { !it.compilationName.contains("test", true) }
?: checkNotNull(newLeaderCandidates.minByOrNull { it.compilationName })
setOf(first, second, firstLeader, secondLeader).forEach { compilationInfo ->
leadingReferenceMap[compilationInfo.compilationName] = newLeader
}
}
}
@@ -0,0 +1,100 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress("MoveLambdaOutsideParentheses")
package org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.mpp.InternalKotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.addSourcesToKotlinCompileTask
import org.jetbrains.kotlin.gradle.plugin.mpp.addSourcesToKotlinNativeCompileTask
import org.jetbrains.kotlin.gradle.plugin.sources.defaultSourceSetLanguageSettingsChecker
import org.jetbrains.kotlin.gradle.utils.addExtendsFromRelation
internal interface KotlinCompilationSourceSetInclusion {
fun include(compilation: InternalKotlinCompilation<*>, sourceSet: KotlinSourceSet)
}
internal class DefaultKotlinCompilationSourceSetInclusion(
private val addSourcesToCompileTask: AddSourcesToCompileTask
) : KotlinCompilationSourceSetInclusion {
interface AddSourcesToCompileTask {
fun addSources(compilation: KotlinCompilation<*>, sourceSet: KotlinSourceSet, addAsCommonSources: Lazy<Boolean>)
object Default : AddSourcesToCompileTask {
override fun addSources(
compilation: KotlinCompilation<*>, sourceSet: KotlinSourceSet, addAsCommonSources: Lazy<Boolean>
) {
addSourcesToKotlinCompileTask(
compilation.project,
compilation.compileKotlinTaskName,
sourceSet.customSourceFilesExtensions,
addAsCommonSources,
{ sourceSet.kotlin }
)
}
}
object Native : AddSourcesToCompileTask {
override fun addSources(compilation: KotlinCompilation<*>, sourceSet: KotlinSourceSet, addAsCommonSources: Lazy<Boolean>) {
addSourcesToKotlinNativeCompileTask(
compilation.project, compilation.compileKotlinTaskName, { sourceSet.kotlin }, addAsCommonSources
)
}
}
}
private val processedSourceSets = hashSetOf<KotlinSourceSet>()
override fun include(compilation: InternalKotlinCompilation<*>, sourceSet: KotlinSourceSet) {
if (!processedSourceSets.add(sourceSet)) return
addSourcesToCompileTask.addSources(
compilation, sourceSet,
addAsCommonSources = lazy {
compilation.project.kotlinExtension.sourceSets.any { otherSourceSet ->
sourceSet in otherSourceSet.dependsOn
}
}
)
// Use `forced = false` since `api`, `implementation`, and `compileOnly` may be missing in some cases like
// old Java & Android projects:
compilation.project.addExtendsFromRelation(
compilation.apiConfigurationName,
sourceSet.apiConfigurationName,
forced = false
)
compilation.project.addExtendsFromRelation(
compilation.implementationConfigurationName,
sourceSet.implementationConfigurationName,
forced = false
)
compilation.project.addExtendsFromRelation(
compilation.compileOnlyConfigurationName,
sourceSet.compileOnlyConfigurationName,
forced = false
)
compilation.project.addExtendsFromRelation(
compilation.runtimeOnlyConfigurationName,
sourceSet.runtimeOnlyConfigurationName,
forced = false
)
if (sourceSet.name != compilation.defaultSourceSet.name) {
// 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(compilation.defaultSourceSet, sourceSet)
}
}
}
@@ -0,0 +1,56 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.compilationImpl
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.gradle.utils.MutableObservableSet
import org.jetbrains.kotlin.gradle.utils.MutableObservableSetImpl
import org.jetbrains.kotlin.gradle.utils.ObservableSet
internal fun KotlinCompilationSourceSetsContainer(
defaultSourceSet: KotlinSourceSet
): KotlinCompilationSourceSetsContainer {
return DefaultKotlinCompilationSourceSetsContainer(defaultSourceSet)
}
internal interface KotlinCompilationSourceSetsContainer {
val defaultSourceSet: KotlinSourceSet
val kotlinSourceSets: ObservableSet<KotlinSourceSet>
val allKotlinSourceSets: ObservableSet<KotlinSourceSet>
fun source(sourceSet: KotlinSourceSet)
}
private class DefaultKotlinCompilationSourceSetsContainer(
override val defaultSourceSet: KotlinSourceSet
) : KotlinCompilationSourceSetsContainer {
private val kotlinSourceSetsImpl: MutableObservableSet<KotlinSourceSet> = MutableObservableSetImpl(defaultSourceSet)
private val allKotlinSourceSetsImpl: MutableObservableSet<KotlinSourceSet> = MutableObservableSetImpl<KotlinSourceSet>().also { set ->
defaultSourceSet.internal.withDependsOnClosure.forAll(set::add)
}
override val kotlinSourceSets: ObservableSet<KotlinSourceSet>
get() = kotlinSourceSetsImpl
override val allKotlinSourceSets: ObservableSet<KotlinSourceSet>
get() = allKotlinSourceSetsImpl
/**
* All SourceSets that have been processed by [source] already.
* [directlyIncludedKotlinSourceSets] cannot be used in this case, because
* the [defaultSourceSet] will always be already included.
*/
private val sourcedKotlinSourceSets = hashSetOf<KotlinSourceSet>()
override fun source(sourceSet: KotlinSourceSet) {
if (!sourcedKotlinSourceSets.add(sourceSet)) return
kotlinSourceSetsImpl.add(sourceSet)
sourceSet.internal.withDependsOnClosure.forAll { inDependsOnClosure ->
allKotlinSourceSetsImpl.add(inDependsOnClosure)
}
}
}
@@ -0,0 +1,11 @@
/*
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.compilationImpl
data class KotlinCompilationTaskNameContainer(
val compileTaskName: String,
val compileAllTaskName: String
)
@@ -1,74 +0,0 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.internal
import org.gradle.api.Project
import org.gradle.api.plugins.ExtraPropertiesExtension
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.isMainCompilationData
/** This is a disjoint-set union-like approach to having a module name that is equal across associated compilations, as the compiler
* now requires that to properly compile internal calls to friend classes. Associating a compilation with another one leads to their
* disjoint sets being united, so their module names become equal, taken from the new leader compilation.
*
* TODO: once the compiler is able to correctly generate calls to internals in other modules, remove this logic.
*/
internal class KotlinCompilationsModuleGroups {
private val moduleLeaderCompilationMap: MutableMap<KotlinCompilationData<*>, KotlinCompilationData<*>> =
mutableMapOf()
fun getModuleLeader(compilation: KotlinCompilationData<*>): KotlinCompilationData<*> {
if (compilation !in moduleLeaderCompilationMap) {
moduleLeaderCompilationMap[compilation] = compilation
}
val leader = moduleLeaderCompilationMap.getValue(compilation)
return when {
leader == compilation -> leader
else -> getModuleLeader(leader).also { moduleLeaderCompilationMap[compilation] = it }
}
}
fun unionModules(compilationA: KotlinCompilationData<*>, compilationB: KotlinCompilationData<*>) {
val aLeader = getModuleLeader(compilationA)
val bLeader = getModuleLeader(compilationB)
if (aLeader == bLeader)
return
listOf(aLeader, bLeader).run {
/** heuristically choose the new leader: choose `main` when possible, don't choose `*test*` when there's an alternative,
* if that didn't work, choose the first name lexicographically */
val newLeader = singleOrNull { it.isMainCompilationData() }
?: singleOrNull { it.compilationPurpose.contains("main", true) }
?: singleOrNull { !it.compilationPurpose.contains("test", true) }
?: minByOrNull { it.compilationPurpose }!!
forEach { moduleLeaderCompilationMap[it] = newLeader }
}
}
companion object {
private const val EXT_NAME = "kotlin.compilations.moduleGroups"
fun getModuleLeaderCompilation(compilation: KotlinCompilationData<*>): KotlinCompilationData<*> =
getInstance(compilation.project).getModuleLeader(compilation)
fun unionModules(compilationA: KotlinCompilationData<*>, compilationB: KotlinCompilationData<*>) {
getInstance(compilationA.project).unionModules(compilationA, compilationB)
}
private fun getInstance(project: Project): KotlinCompilationsModuleGroups {
val ext = project.extensions.getByType(ExtraPropertiesExtension::class.java)
if (!ext.has(EXT_NAME)) {
ext.set(EXT_NAME, KotlinCompilationsModuleGroups())
}
@Suppress("UNCHECKED_CAST")
return ext.get(EXT_NAME) as KotlinCompilationsModuleGroups
}
}
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20
import org.gradle.api.Project
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.plugin.Kotlin2JvmSourceSetProcessor
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationProjection
import org.jetbrains.kotlin.gradle.plugin.KotlinNativeTargetConfigurator
import org.jetbrains.kotlin.gradle.plugin.mpp.addCommonSourcesToKotlinCompileTask
import org.jetbrains.kotlin.gradle.plugin.mpp.addSourcesToKotlinCompileTask
@@ -30,7 +31,7 @@ open class GradleKpmCompilationTaskConfigurator(
variant: GradleKpmVariant,
compilationData: KotlinCompilationData<*>
): TaskProvider<out KotlinCompile> {
Kotlin2JvmSourceSetProcessor(KotlinTasksProvider(), compilationData).run()
Kotlin2JvmSourceSetProcessor(KotlinTasksProvider(), KotlinCompilationProjection.KPM(compilationData)).run()
val allSources = getSourcesForFragmentCompilation(variant)
val commonSources = getCommonSourcesForFragmentCompilation(variant)
@@ -12,13 +12,10 @@ import org.gradle.api.attributes.Usage
import org.gradle.api.tasks.TaskProvider
import org.gradle.jvm.tasks.Jar
import org.jetbrains.kotlin.gradle.dsl.pm20Extension
import org.jetbrains.kotlin.gradle.plugin.KotlinCommonSourceSetProcessor
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.categoryByName
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.ComputedCapability
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.disambiguateName
import org.jetbrains.kotlin.gradle.plugin.usageByName
import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigurator
import org.jetbrains.kotlin.gradle.targets.metadata.createGenerateProjectStructureMetadataTask
import org.jetbrains.kotlin.gradle.targets.metadata.filesWithUnpackedArchives
@@ -221,10 +218,7 @@ private class GradleKpmMetadataCompilationTasksConfigurator(project: Project) :
fragment: GradleKpmFragment,
compilationData: KotlinCommonFragmentMetadataCompilationData
) {
KotlinCommonSourceSetProcessor(
compilationData,
KotlinTasksProvider()
).run()
KotlinCommonSourceSetProcessor(KotlinCompilationProjection.KPM(compilationData), KotlinTasksProvider()).run()
val allSources = getSourcesForFragmentCompilation(fragment)
val commonSources = getCommonSourcesForFragmentCompilation(fragment)
@@ -224,7 +224,7 @@ internal class AndroidProjectHandler(
val defaultSourceSet = project.kotlinExtension.sourceSets.maybeCreate(compilation.defaultSourceSetName)
val configAction = KotlinCompileConfig(compilation)
val configAction = KotlinCompileConfig(KotlinCompilationProjection(compilation))
configAction.configureTask { task ->
task.useModuleDetection.value(true).disallowChanges()
// store kotlin classes in separate directory. They will serve as class-path to java compiler
@@ -54,7 +54,7 @@ open class KotlinJsTargetConfigurator :
override fun buildCompilationProcessor(compilation: KotlinJsCompilation): KotlinSourceSetProcessor<*> {
val tasksProvider = KotlinTasksProvider()
return Kotlin2JsSourceSetProcessor(tasksProvider, compilation)
return Kotlin2JsSourceSetProcessor(tasksProvider, KotlinCompilationProjection(compilation))
}
override fun configureCompilationDefaults(target: KotlinJsTarget) {
@@ -56,7 +56,7 @@ open class KotlinJsIrTargetConfigurator() :
override fun buildCompilationProcessor(compilation: KotlinJsIrCompilation): KotlinSourceSetProcessor<*> {
val tasksProvider = KotlinTasksProvider()
return KotlinJsIrSourceSetProcessor(tasksProvider, compilation)
return KotlinJsIrSourceSetProcessor(tasksProvider, KotlinCompilationProjection(compilation))
}
override fun createArchiveTasks(target: KotlinJsIrTarget): TaskProvider<out Zip> {
@@ -6,26 +6,93 @@
@file:Suppress("PackageDirectoryMismatch") // Old package for compatibility
package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.tasks.compile.JavaCompile
import org.gradle.api.file.FileCollection
import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.dsl.*
import org.gradle.api.tasks.compile.JavaCompile
import org.jetbrains.kotlin.gradle.dsl.CompilerCommonOptions
import org.jetbrains.kotlin.gradle.dsl.CompilerJvmOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
import org.jetbrains.kotlin.gradle.plugin.HasCompilerOptions
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationToRunnableFiles
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationWithResources
import org.jetbrains.kotlin.gradle.plugin.internal.JavaSourceSetsAccessor
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationImpl
import org.jetbrains.kotlin.gradle.plugin.variantImplementationFactory
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
import javax.inject.Inject
abstract class KotlinJvmCompilation @Inject constructor(
open class KotlinJvmCompilation @Inject internal constructor(
private val compilation: KotlinCompilationImpl
) : InternalKotlinCompilation<KotlinJvmOptions> by compilation.castKotlinOptionsType(),
KotlinCompilationWithResources<KotlinJvmOptions>,
KotlinCompilationToRunnableFiles<KotlinJvmOptions> {
override val target: KotlinJvmTarget = compilation.target as KotlinJvmTarget
override val compilerOptions: HasCompilerOptions<CompilerJvmOptions> =
compilation.compilerOptions.castCompilerOptionsType()
@Deprecated("Replaced with compileTaskProvider", replaceWith = ReplaceWith("compileTaskProvider"))
@Suppress("UNCHECKED_CAST", "DEPRECATION")
override val compileKotlinTaskProvider: TaskProvider<out org.jetbrains.kotlin.gradle.tasks.KotlinCompile>
get() = compilation.compileKotlinTaskProvider as TaskProvider<out org.jetbrains.kotlin.gradle.tasks.KotlinCompile>
@Suppress("DEPRECATION")
@Deprecated("Accessing task instance directly is deprecated", replaceWith = ReplaceWith("compileTaskProvider"))
override val compileKotlinTask: org.jetbrains.kotlin.gradle.tasks.KotlinCompile
get() = compilation.compileKotlinTask as org.jetbrains.kotlin.gradle.tasks.KotlinCompile
@Suppress("UNCHECKED_CAST")
override val compileTaskProvider: TaskProvider<out KotlinCompilationTask<CompilerJvmOptions>>
get() = compilation.compileTaskProvider as TaskProvider<KotlinCompilationTask<CompilerJvmOptions>>
val compileJavaTaskProvider: TaskProvider<out JavaCompile>?
get() = if (target.withJavaEnabled) {
val project = target.project
val javaSourceSets = project.gradle.variantImplementationFactory<JavaSourceSetsAccessor.JavaSourceSetsAccessorVariantFactory>()
.getInstance(project)
.sourceSets
val javaSourceSet = javaSourceSets.getByName(compilationName)
project.tasks.withType(JavaCompile::class.java).named(javaSourceSet.compileJavaTaskName)
} else null
override val runtimeDependencyConfigurationName: String
get() = compilation.runtimeDependencyConfigurationName ?: error("Missing 'runtimeDependencyConfigurationName'")
override var runtimeDependencyFiles: FileCollection = compilation.runtimeDependencyFiles ?: error("Missing 'runtimeDependencyFiles'")
override val processResourcesTaskName: String
get() = compilation.processResourcesTaskName ?: error("Missing 'processResourcesTaskName'")
override val relatedConfigurationNames: List<String>
get() = compilation.relatedConfigurationNames
}
private inline fun <reified T : KotlinCommonOptions> InternalKotlinCompilation<*>.castKotlinOptionsType(): InternalKotlinCompilation<T> {
this.kotlinOptions as T
@Suppress("UNCHECKED_CAST")
return this as InternalKotlinCompilation<T>
}
private inline fun <reified T : CompilerCommonOptions> HasCompilerOptions<*>.castCompilerOptionsType(): HasCompilerOptions<T> {
this.options as T
@Suppress("UNCHECKED_CAST")
return this as HasCompilerOptions<T>
}
abstract class oKotlinJvmCompilation @Inject constructor(
compilationDetails: CompilationDetailsWithRuntime<KotlinJvmOptions>,
) : AbstractKotlinCompilationToRunnableFiles<KotlinJvmOptions>(compilationDetails),
KotlinCompilationWithResources<KotlinJvmOptions> {
override val target: KotlinJvmTarget get() = compilationDetails.target as KotlinJvmTarget
@Suppress("UNCHECKED_CAST")
override val compilerOptions: HasCompilerOptions<KotlinJvmCompilerOptions>
get() = super.compilerOptions as HasCompilerOptions<KotlinJvmCompilerOptions>
override val compilerOptions: HasCompilerOptions<CompilerJvmOptions>
get() = super.compilerOptions as HasCompilerOptions<CompilerJvmOptions>
override val processResourcesTaskName: String
get() = disambiguateName("processResources")
@@ -41,16 +108,18 @@ abstract class KotlinJvmCompilation @Inject constructor(
get() = super.compileKotlinTask as org.jetbrains.kotlin.gradle.tasks.KotlinCompile
@Suppress("UNCHECKED_CAST")
override val compileTaskProvider: TaskProvider<out KotlinCompilationTask<KotlinJvmCompilerOptions>>
get() = super.compileTaskProvider as TaskProvider<KotlinCompilationTask<KotlinJvmCompilerOptions>>
override val compileTaskProvider: TaskProvider<out KotlinCompilationTask<CompilerJvmOptions>>
get() = super.compileTaskProvider as TaskProvider<KotlinCompilationTask<CompilerJvmOptions>>
val compileJavaTaskProvider: TaskProvider<out JavaCompile>?
get() = if (target.withJavaEnabled) {
val project = target.project
val javaSourceSets = project.gradle.variantImplementationFactory<JavaSourceSetsAccessor.JavaSourceSetsAccessorVariantFactory>()
.getInstance(project)
.sourceSets
val javaSourceSets =
project.gradle.variantImplementationFactory<JavaSourceSetsAccessor.JavaSourceSetsAccessorVariantFactory>()
.getInstance(project)
.sourceSets
val javaSourceSet = javaSourceSets.getByName(compilationPurpose)
project.tasks.withType(JavaCompile::class.java).named(javaSourceSet.compileJavaTaskName)
} else null
}
}
@@ -6,10 +6,20 @@
@file:Suppress("PackageDirectoryMismatch") // Old package for compatibility
package org.jetbrains.kotlin.gradle.plugin.mpp
import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.HasCompilerOptions
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationDetailsImpl.DefaultCompilationDetailsWithRuntime
import org.gradle.api.attributes.Category
import org.gradle.api.attributes.Usage
import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.dsl.CompilerJvmOptions
import org.jetbrains.kotlin.gradle.dsl.CompilerJvmOptionsDefault
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.*
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationModuleManager.CompilationModule.Type.Auxiliary
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationModuleManager.CompilationModule.Type.Main
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName
import org.jetbrains.kotlin.gradle.targets.jvm.KotlinJvmTarget
import org.jetbrains.kotlin.gradle.utils.*
import java.util.concurrent.Callable
open class KotlinJvmCompilationFactory(
override val target: KotlinJvmTarget
@@ -17,26 +27,151 @@ open class KotlinJvmCompilationFactory(
override val itemClass: Class<KotlinJvmCompilation>
get() = KotlinJvmCompilation::class.java
@Suppress("DEPRECATION")
override fun create(name: String): KotlinJvmCompilation =
target.project.objects.newInstance(
KotlinJvmCompilation::class.java,
DefaultCompilationDetailsWithRuntime<KotlinJvmOptions, KotlinJvmCompilerOptions>(
target,
name,
getOrCreateDefaultSourceSet(name),
{
object : HasCompilerOptions<KotlinJvmCompilerOptions> {
override val options: KotlinJvmCompilerOptions =
target.project.objects.newInstance(KotlinJvmCompilerOptionsDefault::class.java)
}
},
{
object : KotlinJvmOptions {
override val options: KotlinJvmCompilerOptions
get() = compilerOptions.options
}
}
override fun create(name: String): KotlinJvmCompilation {
val compilerOptions = createCompilerOptions()
val params = KotlinCompilationImpl.Params(
target = target,
compilationModule = KotlinCompilationModuleManager.CompilationModule(
compilationName = name,
ownModuleName = ownModuleName(target, name),
type = if (name == KotlinCompilation.MAIN_COMPILATION_NAME) Main else Auxiliary
),
sourceSets = KotlinCompilationSourceSetsContainer(getOrCreateDefaultSourceSet(name)),
dependencyConfigurations = createDependencyConfigurations(name),
compilationTaskNames = KotlinCompilationTaskNameContainer(
compileTaskName = lowerCamelCaseName(
"compile", name.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME }, "Kotlin", target.targetName
),
compileAllTaskName = lowerCamelCaseName(target.disambiguationClassifier, name, "classes")
),
processResourcesTaskName = lowerCamelCaseName(
target.disambiguationClassifier,
name.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
"processResources"
),
output = DefaultKotlinCompilationOutput(
project, Callable { target.project.buildDir.resolve("processedResources/${target.targetName}/$name") }
),
compilerOptions = compilerOptions,
kotlinOptions = compilerOptions.asKotlinJvmOptions(),
compilationAssociator = if (target.withJavaEnabled) KotlinJvmWithJavaCompilationAssociator else
DefaultKotlinCompilationAssociator,
compilationFriendPathsResolver = DefaultKotlinCompilationFriendPathsResolver,
compilationSourceSetInclusion = DefaultKotlinCompilationSourceSetInclusion(
DefaultKotlinCompilationSourceSetInclusion.AddSourcesToCompileTask.Default
)
)
}
return target.project.objects.newInstance(KotlinJvmCompilation::class.java, KotlinCompilationImpl(params))
}
private fun createDependencyConfigurations(
compilationName: String
): KotlinCompilationDependencyConfigurationsContainer {
val compilation = "${target.disambiguationClassifier}/$compilationName"
val prefix = lowerCamelCaseName(
target.disambiguationClassifier,
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
"compilation"
)
val apiConfiguration = target.project.configurations.maybeCreate(lowerCamelCaseName(prefix, API)).apply {
isVisible = false
isCanBeConsumed = false
isCanBeResolved = false
description = "API dependencies for $compilation"
}
val implementationConfiguration = target.project.configurations.maybeCreate(lowerCamelCaseName(prefix, IMPLEMENTATION)).apply {
extendsFrom(apiConfiguration)
isVisible = false
isCanBeConsumed = false
isCanBeResolved = false
description = "Implementation only dependencies for $compilation."
}
val compileOnlyConfiguration = target.project.configurations.maybeCreate(lowerCamelCaseName(prefix, COMPILE_ONLY)).apply {
isCanBeConsumed = false
setupAsLocalTargetSpecificConfigurationIfSupported(target)
attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY))
isVisible = false
isCanBeResolved = false
description = "Compile only dependencies for $compilation."
}
val runtimeOnlyConfiguration = target.project.configurations.maybeCreate(lowerCamelCaseName(prefix, RUNTIME_ONLY)).apply {
isVisible = false
isCanBeConsumed = false
isCanBeResolved = false
description = "Runtime only dependencies for $compilation."
}
val compileDependencyConfiguration = target.project.configurations.maybeCreate(
lowerCamelCaseName(
target.disambiguationClassifier,
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
"compileClasspath"
)
).apply {
extendsFrom(compileOnlyConfiguration, implementationConfiguration)
usesPlatformOf(target)
isVisible = false
isCanBeConsumed = false
attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.consumerApiUsage(target))
if (target.platformType != KotlinPlatformType.androidJvm) {
attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY))
}
description = "Compile classpath for $compilation."
}
val runtimeDependencyConfiguration = target.project.configurations.maybeCreate(
lowerCamelCaseName(
target.disambiguationClassifier,
compilationName.takeIf { it != KotlinCompilation.MAIN_COMPILATION_NAME },
"runtimeClasspath"
)
).apply {
extendsFrom(runtimeOnlyConfiguration, implementationConfiguration)
usesPlatformOf(target)
isVisible = false
isCanBeConsumed = false
isCanBeResolved = true
attributes.attribute(Usage.USAGE_ATTRIBUTE, KotlinUsages.consumerRuntimeUsage(target))
if (target.platformType != KotlinPlatformType.androidJvm) {
attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.categoryByName(Category.LIBRARY))
}
description = "Runtime classpath of $compilation."
}
return DefaultKotlinCompilationDependencyConfigurationsContainer(
apiConfiguration = apiConfiguration,
implementationConfiguration = implementationConfiguration,
compileOnlyConfiguration = compileOnlyConfiguration,
runtimeOnlyConfiguration = runtimeOnlyConfiguration,
compileDependencyConfiguration = compileDependencyConfiguration,
runtimeDependencyConfiguration = runtimeDependencyConfiguration
)
}
private fun createCompilerOptions(): HasCompilerOptions<CompilerJvmOptions> {
return object : HasCompilerOptions<CompilerJvmOptions> {
override val options: CompilerJvmOptions =
target.project.objects.newInstance(CompilerJvmOptionsDefault::class.java)
}
}
private fun HasCompilerOptions<CompilerJvmOptions>.asKotlinJvmOptions(): KotlinJvmOptions {
return object : KotlinJvmOptions {
override val options: CompilerJvmOptions
get() = this@asKotlinJvmOptions.options
}
}
}
private fun ownModuleName(target: KotlinTarget, compilationName: String): Provider<String> = target.project.provider {
val baseName = target.project.archivesName.orNull
?: target.project.name
val suffix = if (compilationName == KotlinCompilation.MAIN_COMPILATION_NAME) "" else "_$compilationName"
filterModuleName("$baseName$suffix")
}
@@ -8,8 +8,6 @@ package org.jetbrains.kotlin.gradle.targets.jvm
import org.gradle.api.Task
import org.gradle.api.plugins.JavaBasePlugin
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.Kotlin2JvmSourceSetProcessor
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetProcessor
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmCompilation
import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmTest
import org.jetbrains.kotlin.gradle.tasks.KotlinTasksProvider
@@ -74,6 +72,6 @@ open class KotlinJvmTargetConfigurator :
override fun buildCompilationProcessor(compilation: KotlinJvmCompilation): KotlinSourceSetProcessor<*> {
val tasksProvider = KotlinTasksProvider()
return Kotlin2JvmSourceSetProcessor(tasksProvider, compilation)
return Kotlin2JvmSourceSetProcessor(tasksProvider, KotlinCompilationProjection(compilation))
}
}
@@ -53,7 +53,7 @@ class KotlinJvmWithJavaTargetPreset(
}
AbstractKotlinPlugin.configureTarget(target) { compilation ->
Kotlin2JvmSourceSetProcessor(KotlinTasksProvider(), compilation)
Kotlin2JvmSourceSetProcessor(KotlinTasksProvider(), KotlinCompilationProjection(compilation))
}
target.compilations.getByName("test").run {
@@ -118,7 +118,7 @@ class KotlinMetadataTargetConfigurator :
override fun buildCompilationProcessor(compilation: AbstractKotlinCompilation<*>): KotlinCompilationProcessor<*> = when (compilation) {
is KotlinCommonCompilation -> {
val tasksProvider = KotlinTasksProvider()
KotlinCommonSourceSetProcessor(compilation, tasksProvider)
KotlinCommonSourceSetProcessor(KotlinCompilationProjection(compilation), tasksProvider)
}
is KotlinSharedNativeCompilation -> NativeSharedCompilationProcessor(compilation)
@@ -486,8 +486,8 @@ class KotlinMetadataTargetConfigurator :
}
internal class NativeSharedCompilationProcessor(
override val kotlinCompilation: KotlinNativeFragmentMetadataCompilationData
) : KotlinCompilationProcessor<KotlinNativeCompile>(kotlinCompilation) {
private val kotlinCompilation: KotlinSharedNativeCompilation
) : KotlinCompilationProcessor<KotlinNativeCompile>(KotlinCompilationProjection(kotlinCompilation)) {
override val kotlinTask: TaskProvider<out KotlinNativeCompile> =
KotlinNativeTargetConfigurator.createKlibCompilationTask(kotlinCompilation)
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.gradle.dsl.topLevelExtension
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider.Companion.kotlinPropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithClosure
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToCompilerOptions
import org.jetbrains.kotlin.gradle.report.BuildMetricsService
import org.jetbrains.kotlin.gradle.report.BuildReportsService
@@ -85,12 +84,12 @@ internal abstract class AbstractKotlinCompileConfig<TASK : AbstractKotlinCompile
protected fun getClasspathSnapshotDir(task: TASK): Provider<Directory> =
getKotlinBuildDir(task).map { it.dir("classpath-snapshot") }
constructor(compilation: KotlinCompilationData<*>) : this(
compilation.project, compilation.project.topLevelExtension, compilation.project.provider { compilation.languageSettings }
constructor(compilationProjection: KotlinCompilationProjection) : this(
compilationProjection.project, compilationProjection.project.topLevelExtension, compilationProjection.project.provider { compilationProjection.languageSettings }
) {
configureTask { task ->
task.friendPaths.from({ compilation.friendPaths })
if (compilation is KotlinCompilation<*>) {
task.friendPaths.from({ compilationProjection.friendPaths })
compilationProjection.tcsOrNull?.compilation?.let { compilation ->
task.friendSourceSets
.value(providers.provider { compilation.associateWithClosure.map { it.name } })
.disallowChanges()
@@ -98,12 +97,12 @@ internal abstract class AbstractKotlinCompileConfig<TASK : AbstractKotlinCompile
compilation.project.configurations.getByName(compilation.pluginConfigurationName)
)
}
task.moduleName.set(providers.provider { compilation.moduleName })
task.ownModuleName.set(project.provider { compilation.ownModuleName })
task.sourceSetName.value(providers.provider { compilation.compilationPurpose })
task.moduleName.set(providers.provider { compilationProjection.moduleName })
task.ownModuleName.set(project.provider { compilationProjection.ownModuleName })
task.sourceSetName.value(providers.provider { compilationProjection.compilationName })
task.multiPlatformEnabled.value(
providers.provider {
compilation.project.plugins.any {
compilationProjection.project.plugins.any {
it is KotlinPlatformPluginBase ||
it is AbstractKotlinMultiplatformPluginWrapper ||
it is AbstractKotlinPm20PluginWrapper
@@ -15,12 +15,11 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension
import org.jetbrains.kotlin.gradle.internal.*
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.KAPT_SUBPLUGIN_ID
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.isIncludeCompileClasspath
import org.jetbrains.kotlin.gradle.internal.KotlinJvmCompilerArgumentsContributor
import org.jetbrains.kotlin.gradle.internal.buildKaptSubpluginOptions
import org.jetbrains.kotlin.gradle.plugin.KaptExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationProjection
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompilerArgumentsProvider
import org.jetbrains.kotlin.gradle.utils.isConfigurationCacheAvailable
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
@@ -32,10 +31,10 @@ import java.util.concurrent.ConcurrentHashMap
internal class KaptGenerateStubsConfig : BaseKotlinCompileConfig<KaptGenerateStubsTask> {
constructor(
compilation: KotlinCompilationData<*>,
compilation: KotlinCompilation<*>,
kotlinTaskProvider: TaskProvider<KotlinCompile>,
kaptClassesDir: File,
) : super(compilation) {
kaptClassesDir: File
) : super(KotlinCompilationProjection(compilation)) {
configureFromExtension(project.extensions.getByType(KaptExtension::class.java))
configureTask { task ->
val kotlinCompileTask = kotlinTaskProvider.get()
@@ -48,11 +47,11 @@ internal class KaptGenerateStubsConfig : BaseKotlinCompileConfig<KaptGenerateStu
// We are filtering them to avoid failed UP-TO-DATE checks
val kaptJavaSourcesDir = Kapt3GradleSubplugin.getKaptGeneratedSourcesDir(
project,
compilation.compilationPurpose
compilation.compilationName
)
val kaptKotlinSourcesDir = Kapt3GradleSubplugin.getKaptGeneratedKotlinSourcesDir(
project,
compilation.compilationPurpose
compilation.compilationName
)
val destinationDirectory = task.destinationDirectory
val stubsDir = task.stubsDir
@@ -94,7 +93,8 @@ internal class KaptGenerateStubsConfig : BaseKotlinCompileConfig<KaptGenerateStu
}
}
private fun isIncludeCompileClasspath(kaptExtension: KaptExtension) = kaptExtension.includeCompileClasspath ?: project.isIncludeCompileClasspath()
private fun isIncludeCompileClasspath(kaptExtension: KaptExtension) =
kaptExtension.includeCompileClasspath ?: project.isIncludeCompileClasspath()
private fun buildOptions(kaptExtension: KaptExtension, task: KaptGenerateStubsTask): Provider<CompilerPluginOptions> {
val javacOptions = project.provider { kaptExtension.getJavacOptions() }
@@ -5,12 +5,8 @@
package org.jetbrains.kotlin.gradle.tasks.configuration
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.isMainCompilationData
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationProjection
import org.jetbrains.kotlin.gradle.targets.js.ir.*
import org.jetbrains.kotlin.gradle.targets.js.ir.PRODUCE_JS
import org.jetbrains.kotlin.gradle.targets.js.ir.PRODUCE_UNZIPPED_KLIB
import org.jetbrains.kotlin.gradle.targets.js.ir.PRODUCE_ZIPPED_KLIB
import org.jetbrains.kotlin.gradle.tasks.Kotlin2JsCompile
import org.jetbrains.kotlin.gradle.utils.klibModuleName
import java.io.File
@@ -18,7 +14,7 @@ import java.io.File
internal typealias Kotlin2JsCompileConfig = BaseKotlin2JsCompileConfig<Kotlin2JsCompile>
internal open class BaseKotlin2JsCompileConfig<TASK : Kotlin2JsCompile>(
compilation: KotlinCompilationData<*>
compilation: KotlinCompilationProjection
) : AbstractKotlinCompileConfig<TASK>(compilation) {
init {
@@ -75,7 +71,7 @@ internal open class BaseKotlin2JsCompileConfig<TASK : Kotlin2JsCompile>(
protected open fun configureAdditionalFreeCompilerArguments(
task: TASK,
compilation: KotlinCompilationData<*>
compilation: KotlinCompilationProjection
) {
task.enhancedFreeCompilerArgs.value(
task.compilerOptions.freeCompilerArgs.map { freeArgs ->
@@ -87,7 +83,7 @@ internal open class BaseKotlin2JsCompileConfig<TASK : Kotlin2JsCompile>(
}
protected fun MutableList<String>.commonJsAdditionalCompilerFlags(
compilation: KotlinCompilationData<*>
compilation: KotlinCompilationProjection
) {
if (contains(DISABLE_PRE_IR) &&
!contains(PRODUCE_UNZIPPED_KLIB) &&
@@ -101,10 +97,10 @@ internal open class BaseKotlin2JsCompileConfig<TASK : Kotlin2JsCompile>(
contains(PRODUCE_ZIPPED_KLIB)
) {
// Configure FQ module name to avoid cyclic dependencies in klib manifests (see KT-36721).
val baseName = if (compilation.isMainCompilationData()) {
val baseName = if (compilation.isMain) {
project.name
} else {
"${project.name}_${compilation.compilationPurpose}"
"${project.name}_${compilation.compilationName}"
}
if (none { it.startsWith(KLIB_MODULE_NAME) }) {
add("$KLIB_MODULE_NAME=${project.klibModuleName(baseName)}")
@@ -7,25 +7,24 @@ package org.jetbrains.kotlin.gradle.tasks.configuration
import org.gradle.api.Project
import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationProjection
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet
import org.jetbrains.kotlin.gradle.plugin.KotlinTarget
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinCommonCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.AbstractKotlinFragmentMetadataCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinMetadataCompilationData
import org.jetbrains.kotlin.gradle.plugin.sources.internal
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileCommon
import java.io.File
internal class KotlinCompileCommonConfig(
private val compilation: KotlinCompilationData<*>,
) : AbstractKotlinCompileConfig<KotlinCompileCommon>(compilation) {
private val compilationProjection: KotlinCompilationProjection,
) : AbstractKotlinCompileConfig<KotlinCompileCommon>(compilationProjection) {
init {
configureTask { task ->
task.expectActualLinker.value(
providers.provider {
(compilation as? KotlinCommonCompilation)?.isKlibCompilation == true || compilation is KotlinMetadataCompilationData
(compilationProjection.origin as? KotlinCommonCompilation)?.isKlibCompilation == true ||
compilationProjection.origin is KotlinMetadataCompilationData<*>
}
).disallowChanges()
task.refinesMetadataPaths.from(getRefinesMetadataPaths(project)).disallowChanges()
@@ -34,25 +33,26 @@ internal class KotlinCompileCommonConfig(
private fun getRefinesMetadataPaths(project: Project): Provider<Iterable<File>> {
return project.provider {
when (compilation) {
is KotlinCompilation<*> -> {
val defaultKotlinSourceSet: KotlinSourceSet = compilation.defaultSourceSet
val metadataTarget = compilation.owner as KotlinTarget
when (compilationProjection) {
is KotlinCompilationProjection.TCS -> {
val defaultKotlinSourceSet: KotlinSourceSet = compilationProjection.compilation.defaultSourceSet
val metadataTarget = compilationProjection.compilation.target
defaultKotlinSourceSet.internal.dependsOnClosure
.mapNotNull { sourceSet -> metadataTarget.compilations.findByName(sourceSet.name)?.output?.classesDirs }
.flatten()
}
is AbstractKotlinFragmentMetadataCompilationData -> {
val fragment = compilation.fragment
is KotlinCompilationProjection.KPM -> {
val compilationData = compilationProjection.compilationData as AbstractKotlinFragmentMetadataCompilationData<*>
val fragment = compilationData.fragment
project.files(
fragment.refinesClosure.minus(fragment).map {
val compilation = compilation.metadataCompilationRegistry.getForFragmentOrNull(it)
val compilation = compilationData.metadataCompilationRegistry.getForFragmentOrNull(it)
?: return@map project.files()
compilation.output.classesDirs
}
)
}
else -> error("unexpected compilation type")
}
}
}
@@ -8,14 +8,15 @@ package org.jetbrains.kotlin.gradle.tasks.configuration
import org.gradle.api.Project
import org.gradle.api.attributes.Attribute
import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.CompilerJvmOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension
import org.jetbrains.kotlin.gradle.internal.transforms.ClasspathEntrySnapshotTransform
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationProjection
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmAndroidCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinJvmCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.plugin.tcsOrNull
import org.jetbrains.kotlin.gradle.report.BuildMetricsService
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.project.model.LanguageSettings
@@ -60,8 +61,8 @@ internal open class BaseKotlinCompileConfig<TASK : KotlinCompile> : AbstractKotl
}
}
constructor(compilation: KotlinCompilationData<*>) : super(compilation) {
val javaTaskProvider = when (compilation) {
constructor(compilationProjection: KotlinCompilationProjection) : super(compilationProjection) {
val javaTaskProvider = when (val compilation = compilationProjection.tcsOrNull?.compilation) {
is KotlinJvmCompilation -> compilation.compileJavaTaskProvider
is KotlinJvmAndroidCompilation -> compilation.compileJavaTaskProvider
is KotlinWithJavaCompilation<*, *> -> compilation.compileJavaTaskProvider
@@ -76,12 +77,13 @@ internal open class BaseKotlinCompileConfig<TASK : KotlinCompile> : AbstractKotl
task.associatedJavaCompileTaskName.value(javaTaskProvider.name)
}
task.ownModuleName.value(
(compilation.compilerOptions.options as KotlinJvmCompilerOptions).moduleName.convention(compilation.ownModuleName)
(compilationProjection.compilerOptions.options as CompilerJvmOptions).moduleName.convention(compilationProjection.ownModuleName)
)
}
}
}
constructor(project: Project, ext: KotlinTopLevelExtension) : super(
project, ext, languageSettings = getDefaultLangSetting(project, ext)
)
@@ -6,8 +6,8 @@
package org.jetbrains.kotlin.gradle.tasks.configuration
import org.gradle.api.InvalidUserDataException
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationProjection
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsBinaryMode
import org.jetbrains.kotlin.gradle.targets.js.ir.*
import org.jetbrains.kotlin.gradle.targets.js.npm.NpmProject
@@ -15,7 +15,7 @@ import org.jetbrains.kotlin.gradle.targets.js.npm.npmProject
internal open class KotlinJsIrLinkConfig(
private val binary: JsIrBinary
) : BaseKotlin2JsCompileConfig<KotlinJsIrLink>(binary.compilation) {
) : BaseKotlin2JsCompileConfig<KotlinJsIrLink>(KotlinCompilationProjection(binary.compilation)) {
private val compilation
get() = binary.compilation
@@ -49,7 +49,7 @@ internal open class KotlinJsIrLinkConfig(
override fun configureAdditionalFreeCompilerArguments(
task: KotlinJsIrLink,
compilation: KotlinCompilationData<*>
compilation: KotlinCompilationProjection
) {
task.enhancedFreeCompilerArgs.value(
task.compilerOptions.freeCompilerArgs.zip(task.modeProperty) { freeArgs, mode ->
@@ -85,7 +85,7 @@ internal open class KotlinJsIrLinkConfig(
}
private fun MutableList<String>.configureOptions(
compilation: KotlinCompilationData<*>,
compilation: KotlinCompilationProjection,
vararg additionalCompilerArgs: String
) {
additionalCompilerArgs.forEach { arg ->
@@ -83,12 +83,12 @@ internal fun <PropType : Any?, T : ListProperty<PropType>> T.chainedFinalizeValu
finalizeValueOnRead()
}
internal fun <PropType : Any?, T: Property<PropType>> T.chainedFinalizeValue(): T =
internal fun <PropType : Any?, T : Property<PropType>> T.chainedFinalizeValue(): T =
apply {
finalizeValue()
}
internal fun <PropType : Any?, T: Property<PropType>> T.chainedDisallowChanges(): T =
internal fun <PropType : Any?, T : Property<PropType>> T.chainedDisallowChanges(): T =
apply {
disallowChanges()
}
@@ -6,29 +6,34 @@
package org.jetbrains.kotlin.gradle
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.internal.KotlinCompilationsModuleGroups
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.InternalKotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.KotlinCompilationModuleManager
import org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.kotlinCompilationModuleManager
import org.jetbrains.kotlin.gradle.plugin.mpp.internal
import org.junit.Test
import kotlin.test.assertEquals
class KotlinCompilationsModuleGroupsTest {
private val project = buildProjectWithMPP()
private val kotlin = project.multiplatformExtension
private val instance: KotlinCompilationsModuleGroups = KotlinCompilationsModuleGroups()
private val instance: KotlinCompilationModuleManager = project.kotlinCompilationModuleManager
private fun compilation(name: String): AbstractKotlinCompilation<*> =
private fun compilation(name: String): InternalKotlinCompilation<*> =
kotlin.jvm().compilations.maybeCreate(name)
private fun KotlinCompilationModuleManager.unionModules(first: InternalKotlinCompilation<*>, second: InternalKotlinCompilation<*>) {
unionModules(first.compilationModule, second.compilationModule)
}
@Test
fun testIdentityAsModuleLeaderForNewCompilation() {
val a = compilation("a")
assertEquals(a, instance.getModuleLeader(a))
assertEquals(a.internal.compilationModule, instance.getModuleLeader(a.compilationModule))
}
private fun assertLeader(leader: KotlinCompilationData<*>, vararg ofCompilations: KotlinCompilationData<*>) {
val leadersForModules = ofCompilations.map { instance.getModuleLeader(it) }
assertEquals(leadersForModules.map { leader }, leadersForModules)
private fun assertLeader(leader: InternalKotlinCompilation<*>, vararg ofCompilations: InternalKotlinCompilation<*>) {
val leadersForModules = ofCompilations.map { instance.getModuleLeader(it.compilationModule) }
assertEquals(leadersForModules.map { leader.compilationModule }, leadersForModules)
}
@Test