Extract members from Kotlin tasks, don't iterate over them (KT-31713)

Refactor: move some properties from the Kotlin tasks to the
new task data model, so they can be accessed without forcing the
tasks to instantiate.

Don't iterate over Kotlin tasks of all projects in the IC-related code;
instead, inspect the model.

Issue #KT-31713 Fixed
This commit is contained in:
Sergey Igushkin
2019-07-12 18:37:34 +03:00
parent 80fa591f10
commit cbb8bf2deb
12 changed files with 216 additions and 87 deletions
@@ -21,7 +21,7 @@ import org.junit.Assume
sealed class GradleVersionRequired(val minVersion: String, val maxVersion: String?) { sealed class GradleVersionRequired(val minVersion: String, val maxVersion: String?) {
companion object { companion object {
const val OLDEST_SUPPORTED = "4.1" const val OLDEST_SUPPORTED = "4.3"
} }
class Exact(version: String) : GradleVersionRequired(version, version) class Exact(version: String) : GradleVersionRequired(version, version)
@@ -29,18 +29,19 @@ import org.jetbrains.kotlin.cli.common.arguments.K2MetadataCompilerArguments
import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.daemon.client.CompileServiceSession import org.jetbrains.kotlin.daemon.client.CompileServiceSession
import org.jetbrains.kotlin.daemon.common.* import org.jetbrains.kotlin.daemon.common.*
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension import org.jetbrains.kotlin.gradle.dsl.kotlinExtensionOrNull
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtensionOrNull
import org.jetbrains.kotlin.gradle.logging.kotlinDebug import org.jetbrains.kotlin.gradle.logging.kotlinDebug
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.tasks.* import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileTaskData
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget
import org.jetbrains.kotlin.gradle.utils.archivePathCompatible
import org.jetbrains.kotlin.gradle.utils.newTmpFile import org.jetbrains.kotlin.gradle.utils.newTmpFile
import org.jetbrains.kotlin.gradle.utils.relativeToRoot import org.jetbrains.kotlin.gradle.utils.relativeToRoot
import org.jetbrains.kotlin.incremental.IncrementalModuleInfo import org.jetbrains.kotlin.incremental.IncrementalModuleInfo
import org.jetbrains.kotlin.incremental.IncrementalModuleEntry import org.jetbrains.kotlin.incremental.IncrementalModuleEntry
import org.jetbrains.kotlin.incremental.classpathAsList
import org.jetbrains.kotlin.incremental.destinationAsFile
import org.jetbrains.kotlin.incremental.makeModuleFile
import java.io.File import java.io.File
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
@@ -180,38 +181,44 @@ internal open class GradleCompilerRunner(protected val task: Task) {
val jarToModule = HashMap<File, IncrementalModuleEntry>() val jarToModule = HashMap<File, IncrementalModuleEntry>()
for (project in gradle.rootProject.allprojects) { for (project in gradle.rootProject.allprojects) {
project.tasks.withType(AbstractKotlinCompile::class.java).toList().forEach { task ->
if (project.kotlinExtensionOrNull == null)
continue
val isMultiplatformProject = project.multiplatformExtensionOrNull != null
KotlinCompileTaskData.getTaskDataContainer(project).forEach { taskData ->
val compilation = taskData.compilation
val target = taskData.compilation.target
val module = IncrementalModuleEntry( val module = IncrementalModuleEntry(
project.path, project.path,
task.moduleName, compilation.moduleName,
project.buildDir, project.buildDir,
task.buildHistoryFile taskData.buildHistoryFile
) )
dirToModule[task.destinationDir] = module @Suppress("UnstableApiUsage")
task.javaOutputDir?.let { dirToModule[it] = module } dirToModule[taskData.destinationDir.get()] = module
taskData.javaOutputDir?.let { dirToModule[it] = module }
nameToModules.getOrPut(module.name) { HashSet() }.add(module) nameToModules.getOrPut(module.name) { HashSet() }.add(module)
if (task is Kotlin2JsCompile) { if (compilation.platformType == KotlinPlatformType.js) {
jarForSourceSet(project, task.sourceSetName)?.let { jarForSourceSet(project, compilation.name)?.let {
jarToModule[it] = module jarToModule[it] = module
} }
} }
}
project.tasks.withType(InspectClassesForMultiModuleIC::class.java).forEach { task -> if (compilation.name == KotlinCompilation.MAIN_COMPILATION_NAME) {
jarToClassListFile[File(task.archivePath)] = task.classesListFile if (isMultiplatformProject) {
} (project.tasks.findByName(target.artifactsTaskName) as? AbstractArchiveTask)?.let { jarTask ->
project.extensions.findByType(KotlinMultiplatformExtension::class.java)?.let { kotlinExt -> jarToModule[jarTask.archivePathCompatible.canonicalFile] = module
for (target in kotlinExt.targets) { }
val mainCompilation = target.compilations.findByName(KotlinCompilation.MAIN_COMPILATION_NAME) ?: continue } else {
val kotlinTask = mainCompilation.compileKotlinTask as? AbstractKotlinCompile<*> ?: continue if (target is KotlinWithJavaTarget<*>) {
val module = IncrementalModuleEntry( val jar = project.tasks.getByName(target.artifactsTaskName) as Jar
project.path, jarToClassListFile[jar.archivePathCompatible.canonicalFile] = target.defaultArtifactClassesListFile
kotlinTask.moduleName, }
project.buildDir, }
kotlinTask.buildHistoryFile
)
val jarTask = project.tasks.findByName(target.artifactsTaskName) as? AbstractArchiveTask ?: continue
jarToModule[jarTask.archivePath] = module
} }
} }
} }
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.gradle.internal.kapt.incremental.StructureArtifactTr
import org.jetbrains.kotlin.gradle.model.builder.KaptModelBuilder import org.jetbrains.kotlin.gradle.model.builder.KaptModelBuilder
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileTaskData
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.tasks.isWorkerAPISupported import org.jetbrains.kotlin.gradle.tasks.isWorkerAPISupported
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
@@ -469,17 +470,23 @@ class Kapt3KotlinGradleSubplugin : KotlinGradleSubplugin<KotlinCompile> {
} }
private fun Kapt3SubpluginContext.createKaptGenerateStubsTask(): KaptGenerateStubsTask { private fun Kapt3SubpluginContext.createKaptGenerateStubsTask(): KaptGenerateStubsTask {
val kaptTaskName = getKaptTaskName("kaptGenerateStubs")
KotlinCompileTaskData.register(kaptTaskName, KotlinCompileTaskData.get(project, kotlinCompile.name).compilation).apply {
@Suppress("UnstableApiUsage")
useModuleDetection.set(KotlinCompileTaskData.get(project, kotlinCompile.name).useModuleDetection)
}
val kaptTask = project.tasks.create( val kaptTask = project.tasks.create(
getKaptTaskName("kaptGenerateStubs"), kaptTaskName,
KaptGenerateStubsTask::class.java KaptGenerateStubsTask::class.java
) )
kaptTask.sourceSetName = sourceSetName
kaptTask.kotlinCompileTask = kotlinCompile kaptTask.kotlinCompileTask = kotlinCompile
kotlinToKaptGenerateStubsTasksMap[kotlinCompile] = kaptTask kotlinToKaptGenerateStubsTasksMap[kotlinCompile] = kaptTask
kaptTask.stubsDir = getKaptStubsDir() kaptTask.stubsDir = getKaptStubsDir()
kaptTask.destinationDir = getKaptIncrementalDataDir() kaptTask.setDestinationDir { getKaptIncrementalDataDir() }
kaptTask.mapClasspath { kotlinCompile.classpath } kaptTask.mapClasspath { kotlinCompile.classpath }
kaptTask.generatedSourcesDir = sourcesOutputDir kaptTask.generatedSourcesDir = sourcesOutputDir
PropertiesProvider(project).mapKotlinTaskProperties(kaptTask) PropertiesProvider(project).mapKotlinTaskProperties(kaptTask)
@@ -61,7 +61,7 @@ open class KaptGenerateStubsTask : KotlinCompile() {
@get:Input @get:Input
override var useModuleDetection: Boolean override var useModuleDetection: Boolean
get() = kotlinCompileTask.useModuleDetection get() = super.useModuleDetection
set(_) { set(_) {
error("KaptGenerateStubsTask.useModuleDetection setter should not be called!") error("KaptGenerateStubsTask.useModuleDetection setter should not be called!")
} }
@@ -58,7 +58,7 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
val project: Project, val project: Project,
val tasksProvider: KotlinTasksProvider, val tasksProvider: KotlinTasksProvider,
val taskDescription: String, val taskDescription: String,
val kotlinCompilation: KotlinCompilation<*> val kotlinCompilation: AbstractKotlinCompilation<*>
) { ) {
protected abstract fun doTargetSpecificProcessing() protected abstract fun doTargetSpecificProcessing()
protected val logger = Logging.getLogger(this.javaClass)!! protected val logger = Logging.getLogger(this.javaClass)!!
@@ -83,13 +83,17 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
private fun registerKotlinCompileTask(): TaskHolder<out T> { private fun registerKotlinCompileTask(): TaskHolder<out T> {
val name = kotlinCompilation.compileKotlinTaskName val name = kotlinCompilation.compileKotlinTaskName
logger.kotlinDebug("Creating kotlin compile task $name") logger.kotlinDebug("Creating kotlin compile task $name")
val kotlinCompile = doRegisterTask(project, name) {
KotlinCompileTaskData.register(name, kotlinCompilation).apply {
@Suppress("UnstableApiUsage")
destinationDir.set(project.provider { defaultKotlinDestinationDir })
}
return doRegisterTask(project, name) {
it.description = taskDescription it.description = taskDescription
it.mapClasspath { kotlinCompilation.compileDependencyFiles } it.mapClasspath { kotlinCompilation.compileDependencyFiles }
it.setDestinationDir { defaultKotlinDestinationDir }
kotlinCompilation.output.addClassesDir { project.files(kotlinTask.doGetTask().destinationDir).builtBy(kotlinTask.doGetTask()) } kotlinCompilation.output.addClassesDir { project.files(kotlinTask.doGetTask().destinationDir).builtBy(kotlinTask.doGetTask()) }
} }
return kotlinCompile
} }
open fun run() { open fun run() {
@@ -162,7 +166,7 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
internal class Kotlin2JvmSourceSetProcessor( internal class Kotlin2JvmSourceSetProcessor(
project: Project, project: Project,
tasksProvider: KotlinTasksProvider, tasksProvider: KotlinTasksProvider,
kotlinCompilation: KotlinCompilation<*>, kotlinCompilation: AbstractKotlinCompilation<*>,
private val kotlinPluginVersion: String private val kotlinPluginVersion: String
) : KotlinSourceSetProcessor<KotlinCompile>( ) : KotlinSourceSetProcessor<KotlinCompile>(
project, tasksProvider, "Compiles the $kotlinCompilation.", kotlinCompilation project, tasksProvider, "Compiles the $kotlinCompilation.", kotlinCompilation
@@ -236,7 +240,7 @@ internal fun KotlinCompilationOutput.addClassesDir(classesDirProvider: () -> Fil
internal class Kotlin2JsSourceSetProcessor( internal class Kotlin2JsSourceSetProcessor(
project: Project, project: Project,
tasksProvider: KotlinTasksProvider, tasksProvider: KotlinTasksProvider,
kotlinCompilation: KotlinCompilation<*>, kotlinCompilation: AbstractKotlinCompilation<*>,
private val kotlinPluginVersion: String private val kotlinPluginVersion: String
) : KotlinSourceSetProcessor<Kotlin2JsCompile>( ) : KotlinSourceSetProcessor<Kotlin2JsCompile>(
project, tasksProvider, taskDescription = "Compiles the Kotlin sources in $kotlinCompilation to JavaScript.", project, tasksProvider, taskDescription = "Compiles the Kotlin sources in $kotlinCompilation to JavaScript.",
@@ -299,7 +303,7 @@ internal class Kotlin2JsSourceSetProcessor(
internal class KotlinCommonSourceSetProcessor( internal class KotlinCommonSourceSetProcessor(
project: Project, project: Project,
compilation: KotlinCompilation<*>, compilation: AbstractKotlinCompilation<*>,
tasksProvider: KotlinTasksProvider, tasksProvider: KotlinTasksProvider,
private val kotlinPluginVersion: String private val kotlinPluginVersion: String
) : KotlinSourceSetProcessor<KotlinCompileCommon>( ) : KotlinSourceSetProcessor<KotlinCompileCommon>(
@@ -338,7 +342,7 @@ internal abstract class AbstractKotlinPlugin(
internal abstract fun buildSourceSetProcessor( internal abstract fun buildSourceSetProcessor(
project: Project, project: Project,
compilation: KotlinCompilation<*>, compilation: AbstractKotlinCompilation<*>,
kotlinPluginVersion: String kotlinPluginVersion: String
): KotlinSourceSetProcessor<*> ): KotlinSourceSetProcessor<*>
@@ -403,7 +407,7 @@ internal abstract class AbstractKotlinPlugin(
fun configureTarget( fun configureTarget(
target: KotlinWithJavaTarget<*>, target: KotlinWithJavaTarget<*>,
buildSourceSetProcessor: (KotlinCompilation<*>) -> KotlinSourceSetProcessor<*> buildSourceSetProcessor: (AbstractKotlinCompilation<*>) -> KotlinSourceSetProcessor<*>
) { ) {
setUpJavaSourceSets(target) setUpJavaSourceSets(target)
configureSourceSetDefaults(target, buildSourceSetProcessor) configureSourceSetDefaults(target, buildSourceSetProcessor)
@@ -517,8 +521,8 @@ internal abstract class AbstractKotlinPlugin(
} }
private fun configureSourceSetDefaults( private fun configureSourceSetDefaults(
kotlinTarget: KotlinTarget, kotlinTarget: KotlinWithJavaTarget<*>,
buildSourceSetProcessor: (KotlinCompilation<*>) -> KotlinSourceSetProcessor<*> buildSourceSetProcessor: (AbstractKotlinCompilation<*>) -> KotlinSourceSetProcessor<*>
) { ) {
kotlinTarget.compilations.all { compilation -> kotlinTarget.compilations.all { compilation ->
buildSourceSetProcessor(compilation).run() buildSourceSetProcessor(compilation).run()
@@ -566,7 +570,7 @@ internal open class KotlinPlugin(
private const val targetName = "" // use empty suffix for the task names private const val targetName = "" // use empty suffix for the task names
} }
override fun buildSourceSetProcessor(project: Project, compilation: KotlinCompilation<*>, kotlinPluginVersion: String) = override fun buildSourceSetProcessor(project: Project, compilation: AbstractKotlinCompilation<*>, kotlinPluginVersion: String) =
Kotlin2JvmSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion) Kotlin2JvmSourceSetProcessor(project, tasksProvider, compilation, kotlinPluginVersion)
override fun apply(project: Project) { override fun apply(project: Project) {
@@ -592,7 +596,7 @@ internal open class KotlinCommonPlugin(
override fun buildSourceSetProcessor( override fun buildSourceSetProcessor(
project: Project, project: Project,
compilation: KotlinCompilation<*>, compilation: AbstractKotlinCompilation<*>,
kotlinPluginVersion: String kotlinPluginVersion: String
): KotlinSourceSetProcessor<*> = ): KotlinSourceSetProcessor<*> =
KotlinCommonSourceSetProcessor(project, compilation, tasksProvider, kotlinPluginVersion) KotlinCommonSourceSetProcessor(project, compilation, tasksProvider, kotlinPluginVersion)
@@ -616,7 +620,7 @@ internal open class Kotlin2JsPlugin(
override fun buildSourceSetProcessor( override fun buildSourceSetProcessor(
project: Project, project: Project,
compilation: KotlinCompilation<*>, compilation: AbstractKotlinCompilation<*>,
kotlinPluginVersion: String kotlinPluginVersion: String
): KotlinSourceSetProcessor<*> = ): KotlinSourceSetProcessor<*> =
Kotlin2JsSourceSetProcessor( Kotlin2JsSourceSetProcessor(
@@ -914,11 +918,15 @@ abstract class AbstractAndroidProjectHandler<V>(private val kotlinConfigurationT
val kotlinTaskName = compilation.compileKotlinTaskName val kotlinTaskName = compilation.compileKotlinTaskName
KotlinCompileTaskData.register(kotlinTaskName, compilation).apply {
// store kotlin classes in separate directory. They will serve as class-path to java compiler
@Suppress("UnstableApiUsage")
destinationDir.set(project.provider { File(project.buildDir, "tmp/kotlin-classes/$variantDataName") })
}
tasksProvider.registerKotlinJVMTask(project, kotlinTaskName, compilation) { tasksProvider.registerKotlinJVMTask(project, kotlinTaskName, compilation) {
it.parentKotlinOptionsImpl = rootKotlinOptions it.parentKotlinOptionsImpl = rootKotlinOptions
// store kotlin classes in separate directory. They will serve as class-path to java compiler
it.destinationDir = File(project.buildDir, "tmp/kotlin-classes/$variantDataName")
it.description = "Compiles the $variantDataName kotlin." it.description = "Compiles the $variantDataName kotlin."
} }
@@ -9,6 +9,7 @@ import groovy.lang.Closure
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.attributes.AttributeContainer import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.api.plugins.BasePluginConvention
import org.gradle.util.ConfigureUtil import org.gradle.util.ConfigureUtil
import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.dsl.*
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
@@ -183,6 +184,15 @@ abstract class AbstractKotlinCompilation<T : KotlinCommonOptions>(
dependencies f@{ ConfigureUtil.configure(configureClosure, this@f) } dependencies f@{ ConfigureUtil.configure(configureClosure, this@f) }
override fun toString(): String = "compilation '$compilationName' ($target)" override fun toString(): String = "compilation '$compilationName' ($target)"
internal val moduleName: String
get() {
val project = target.project
val baseName = project.convention.findPlugin(BasePluginConvention::class.java)?.archivesBaseName
?: project.name
val suffix = if (compilationName == KotlinCompilation.MAIN_COMPILATION_NAME) "" else "_$compilationName"
return filterModuleName("$baseName$suffix")
}
} }
abstract class AbstractKotlinCompilationToRunnableFiles<T : KotlinCommonOptions>( abstract class AbstractKotlinCompilationToRunnableFiles<T : KotlinCommonOptions>(
@@ -263,3 +273,8 @@ internal object CompilationSourceSetUtil {
sourceSet.name.takeIf { compilations.size > 1 } sourceSet.name.takeIf { compilations.size > 1 }
} }
} }
private val invalidModuleNameCharactersRegex = """[\\/\r\n\t]""".toRegex()
private fun filterModuleName(moduleName: String): String =
moduleName.replace(invalidModuleNameCharactersRegex, "_")
@@ -10,8 +10,11 @@ import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.artifacts.Dependency import org.gradle.api.artifacts.Dependency
import org.gradle.api.plugins.JavaPlugin import org.gradle.api.plugins.JavaPlugin
import org.gradle.jvm.tasks.Jar
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.tasks.KOTLIN_BUILD_DIR_NAME
import java.io.File
open class KotlinWithJavaTarget<KotlinOptionsType : KotlinCommonOptions>( open class KotlinWithJavaTarget<KotlinOptionsType : KotlinCommonOptions>(
project: Project, project: Project,
@@ -39,4 +42,12 @@ open class KotlinWithJavaTarget<KotlinOptionsType : KotlinCommonOptions>(
KotlinWithJavaCompilation::class.java as Class<KotlinWithJavaCompilation<KotlinOptionsType>>, KotlinWithJavaCompilation::class.java as Class<KotlinWithJavaCompilation<KotlinOptionsType>>,
KotlinWithJavaCompilationFactory(project, this) KotlinWithJavaCompilationFactory(project, this)
) )
}
internal val defaultArtifactClassesListFile: File
get() {
val jarTask = project.tasks.getByName(artifactsTaskName) as Jar
return File(File(project.buildDir, KOTLIN_BUILD_DIR_NAME), "${sanitizeFileName(jarTask.archiveName)}-classes.txt")
}
}
private fun sanitizeFileName(candidate: String): String = candidate.filter { it.isLetterOrDigit() }
@@ -9,7 +9,11 @@ import org.gradle.api.DefaultTask
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.api.plugins.JavaPluginConvention import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.* import org.gradle.api.tasks.*
import org.gradle.api.tasks.bundling.AbstractArchiveTask
import org.gradle.jvm.tasks.Jar import org.gradle.jvm.tasks.Jar
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleJavaTargetExtension
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.utils.archivePathCompatible
import java.io.File import java.io.File
internal open class InspectClassesForMultiModuleIC : DefaultTask() { internal open class InspectClassesForMultiModuleIC : DefaultTask() {
@@ -22,7 +26,7 @@ internal open class InspectClassesForMultiModuleIC : DefaultTask() {
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
@get:OutputFile @get:OutputFile
internal val classesListFile: File internal val classesListFile: File
get() = File(File(project.buildDir, KOTLIN_BUILD_DIR_NAME), "${sanitizeFileName(jarTask.archiveName)}-classes.txt") get() = (project.kotlinExtension as KotlinSingleJavaTargetExtension).target.defaultArtifactClassesListFile
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
@get:InputFiles @get:InputFiles
@@ -37,7 +41,7 @@ internal open class InspectClassesForMultiModuleIC : DefaultTask() {
@get:Input @get:Input
internal val archivePath: String internal val archivePath: String
get() = jarTask.archivePath.canonicalPath get() = jarTask.archivePathCompatible.canonicalPath
@TaskAction @TaskAction
fun run() { fun run() {
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.gradle.tasks
import org.gradle.api.Project import org.gradle.api.Project
import org.gradle.api.Task import org.gradle.api.Task
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.api.plugins.BasePluginConvention import org.gradle.api.provider.Provider
import org.gradle.api.tasks.* import org.gradle.api.tasks.*
import org.gradle.api.tasks.Optional import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.AbstractCompile
@@ -29,10 +29,8 @@ import org.jetbrains.kotlin.gradle.internal.prepareCompilerArguments
import org.jetbrains.kotlin.gradle.internal.tasks.TaskWithLocalState import org.jetbrains.kotlin.gradle.internal.tasks.TaskWithLocalState
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
import org.jetbrains.kotlin.gradle.logging.* import org.jetbrains.kotlin.gradle.logging.*
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.COMPILER_CLASSPATH_CONFIGURATION_NAME import org.jetbrains.kotlin.gradle.plugin.COMPILER_CLASSPATH_CONFIGURATION_NAME
import org.jetbrains.kotlin.gradle.plugin.KotlinMultiplatformPluginWrapper
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformPluginBase
import org.jetbrains.kotlin.gradle.plugin.PLUGIN_CLASSPATH_CONFIGURATION_NAME
import org.jetbrains.kotlin.gradle.report.BuildReportMode import org.jetbrains.kotlin.gradle.report.BuildReportMode
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
import org.jetbrains.kotlin.gradle.utils.isParentOf import org.jetbrains.kotlin.gradle.utils.isParentOf
@@ -45,7 +43,6 @@ import org.jetbrains.kotlin.utils.LibraryUtils
import java.io.File import java.io.File
import java.util.* import java.util.*
import javax.inject.Inject import javax.inject.Inject
import kotlin.properties.Delegates
const val KOTLIN_BUILD_DIR_NAME = "kotlin" const val KOTLIN_BUILD_DIR_NAME = "kotlin"
const val USING_JVM_INCREMENTAL_COMPILATION_MESSAGE = "Using Kotlin/JVM incremental compilation" const val USING_JVM_INCREMENTAL_COMPILATION_MESSAGE = "Using Kotlin/JVM incremental compilation"
@@ -142,16 +139,20 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
@get:Internal @get:Internal
internal var buildReportMode: BuildReportMode? = null internal var buildReportMode: BuildReportMode? = null
@get:Internal private val taskData: KotlinCompileTaskData
internal val buildHistoryFile: File get() = KotlinCompileTaskData.get(project, name)
get() = File(taskBuildDirectory, "build-history.bin")
@Suppress("UnstableApiUsage")
@get:Input @get:Input
internal open var useModuleDetection: Boolean = false internal open var useModuleDetection: Boolean
get() = taskData.useModuleDetection.get()
set(value) {
taskData.useModuleDetection.set(value)
}
@get:Internal @get:Internal
protected val multiModuleICSettings: MultiModuleICSettings protected val multiModuleICSettings: MultiModuleICSettings
get() = MultiModuleICSettings(buildHistoryFile, useModuleDetection) get() = MultiModuleICSettings(taskData.buildHistoryFile, useModuleDetection)
@get:Classpath @get:Classpath
@get:InputFiles @get:InputFiles
@@ -183,18 +184,23 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
private val kotlinExt: KotlinProjectExtension private val kotlinExt: KotlinProjectExtension
get() = project.extensions.findByType(KotlinProjectExtension::class.java)!! get() = project.extensions.findByType(KotlinProjectExtension::class.java)!!
private lateinit var destinationDirProvider: Lazy<File> override fun getDestinationDir(): File =
@Suppress("UnstableApiUsage")
taskData.destinationDir.get()
override fun getDestinationDir(): File { @Suppress("UnstableApiUsage")
return destinationDirProvider.value override fun setDestinationDir(provider: Provider<File>) {
taskData.destinationDir.set(provider)
} }
fun setDestinationDir(provider: () -> File) { fun setDestinationDir(provider: () -> File) {
destinationDirProvider = lazy(provider) @Suppress("UnstableApiUsage")
taskData.destinationDir.set(project.provider(provider))
} }
override fun setDestinationDir(destinationDir: File) { override fun setDestinationDir(destinationDir: File) {
destinationDirProvider = lazyOf(destinationDir) @Suppress("UnstableApiUsage")
taskData.destinationDir.set(destinationDir)
} }
@get:Internal @get:Internal
@@ -213,10 +219,13 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
internal var friendTaskName: String? = null internal var friendTaskName: String? = null
@get:Internal @get:Internal
internal var javaOutputDir: File? = null internal var javaOutputDir: File?
get() = taskData.javaOutputDir
set(value) { taskData.javaOutputDir = value }
@get:Internal @get:Internal
internal var sourceSetName: String by Delegates.notNull() internal val sourceSetName: String
get() = taskData.compilation.name
@get:InputFiles @get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE) @get:PathSensitive(PathSensitivity.RELATIVE)
@@ -224,12 +233,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
@get:Input @get:Input
internal val moduleName: String internal val moduleName: String
get() { get() = taskData.compilation.moduleName
val baseName = project.convention.findPlugin(BasePluginConvention::class.java)?.archivesBaseName
?: project.name
val suffix = if (sourceSetName == "main") "" else "_$sourceSetName"
return filterModuleName("${baseName}$suffix")
}
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@get:Internal @get:Internal
@@ -635,8 +639,3 @@ open class Kotlin2JsCompile : AbstractKotlinCompile<K2JSCompilerArguments>(), Ko
compilerRunner.runJsCompilerAsync(sourceRoots.kotlinSourceFiles, commonSourceSet.toList(), args, environment) compilerRunner.runJsCompilerAsync(sourceRoots.kotlinSourceFiles, commonSourceSet.toList(), args, environment)
} }
} }
private val invalidModuleNameCharactersRegex = """[\\/\r\n\t]""".toRegex()
private fun filterModuleName(moduleName: String): String =
moduleName.replace(invalidModuleNameCharactersRegex, "_")
@@ -21,6 +21,7 @@ import org.gradle.api.Task
import org.gradle.api.UnknownTaskException import org.gradle.api.UnknownTaskException
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.defaultSourceSetName import org.jetbrains.kotlin.gradle.plugin.mpp.defaultSourceSetName
import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinTask import org.jetbrains.kotlin.gradle.plugin.sources.applyLanguageSettingsToKotlinTask
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
@@ -99,7 +100,7 @@ internal open class KotlinTasksProvider(val targetName: String) {
open fun registerKotlinJVMTask( open fun registerKotlinJVMTask(
project: Project, project: Project,
name: String, name: String,
compilation: KotlinCompilation<*>, compilation: AbstractKotlinCompilation<*>,
configureAction: (KotlinCompile) -> (Unit) configureAction: (KotlinCompile) -> (Unit)
): TaskHolder<out KotlinCompile> { ): TaskHolder<out KotlinCompile> {
val properties = PropertiesProvider(project) val properties = PropertiesProvider(project)
@@ -114,7 +115,7 @@ internal open class KotlinTasksProvider(val targetName: String) {
fun registerKotlinJSTask( fun registerKotlinJSTask(
project: Project, project: Project,
name: String, name: String,
compilation: KotlinCompilation<*>, compilation: AbstractKotlinCompilation<*>,
configureAction: (Kotlin2JsCompile) -> Unit configureAction: (Kotlin2JsCompile) -> Unit
): TaskHolder<Kotlin2JsCompile> { ): TaskHolder<Kotlin2JsCompile> {
val properties = PropertiesProvider(project) val properties = PropertiesProvider(project)
@@ -129,7 +130,7 @@ internal open class KotlinTasksProvider(val targetName: String) {
fun registerKotlinCommonTask( fun registerKotlinCommonTask(
project: Project, project: Project,
name: String, name: String,
compilation: KotlinCompilation<*>, compilation: AbstractKotlinCompilation<*>,
configureAction: (KotlinCompileCommon) -> (Unit) configureAction: (KotlinCompileCommon) -> (Unit)
): TaskHolder<KotlinCompileCommon> { ): TaskHolder<KotlinCompileCommon> {
val properties = PropertiesProvider(project) val properties = PropertiesProvider(project)
@@ -145,7 +146,7 @@ internal open class KotlinTasksProvider(val targetName: String) {
kotlinTaskHolder: TaskHolder<AbstractKotlinCompile<*>>, kotlinTaskHolder: TaskHolder<AbstractKotlinCompile<*>>,
project: Project, project: Project,
propertiesProvider: PropertiesProvider, propertiesProvider: PropertiesProvider,
compilation: KotlinCompilation<*> compilation: AbstractKotlinCompilation<*>
) { ) {
val configureAfterEvaluated = RunOnceAfterEvaluated("TaskProvider.configure") { val configureAfterEvaluated = RunOnceAfterEvaluated("TaskProvider.configure") {
val languageSettings = project.kotlinExtension.sourceSets.findByName(compilation.defaultSourceSetName)?.languageSettings val languageSettings = project.kotlinExtension.sourceSets.findByName(compilation.defaultSourceSetName)?.languageSettings
@@ -156,7 +157,6 @@ internal open class KotlinTasksProvider(val targetName: String) {
applyLanguageSettingsToKotlinTask(languageSettings, kotlinTask) applyLanguageSettingsToKotlinTask(languageSettings, kotlinTask)
} }
kotlinTaskHolder.configure { kotlinTaskHolder.configure {
it.sourceSetName = compilation.name
it.friendTaskName = taskToFriendTaskMapper[it] it.friendTaskName = taskToFriendTaskMapper[it]
propertiesProvider.mapKotlinTaskProperties(it) propertiesProvider.mapKotlinTaskProperties(it)
configureAfterEvaluated.onConfigure() configureAfterEvaluated.onConfigure()
@@ -179,7 +179,7 @@ internal class AndroidTasksProvider(targetName: String) : KotlinTasksProvider(ta
kotlinTaskHolder: TaskHolder<AbstractKotlinCompile<*>>, kotlinTaskHolder: TaskHolder<AbstractKotlinCompile<*>>,
project: Project, project: Project,
propertiesProvider: PropertiesProvider, propertiesProvider: PropertiesProvider,
compilation: KotlinCompilation<*> compilation: AbstractKotlinCompilation<*>
) { ) {
super.configure(kotlinTaskHolder, project, propertiesProvider, compilation) super.configure(kotlinTaskHolder, project, propertiesProvider, compilation)
kotlinTaskHolder.configure { kotlinTaskHolder.configure {
@@ -0,0 +1,67 @@
/*
* Copyright 2010-2019 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.tasks
import org.gradle.api.Project
import org.gradle.api.plugins.ExtraPropertiesExtension
import org.gradle.api.provider.Property
import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinCompilation
import java.io.File
internal open class KotlinCompileTaskData(
val taskName: String,
val compilation: AbstractKotlinCompilation<*>,
@Suppress("UnstableApiUsage")
val destinationDir: Property<File>,
@Suppress("UnstableApiUsage")
val useModuleDetection: Property<Boolean>
) {
private val taskBuildDirectory: File
get() = File(File(compilation.target.project.buildDir, KOTLIN_BUILD_DIR_NAME), taskName)
val buildHistoryFile: File
get() = File(taskBuildDirectory, "build-history.bin")
var javaOutputDir: File? = null
companion object {
fun get(project: Project, taskName: String): KotlinCompileTaskData = project.getTaskDataMap().getValue(taskName)
fun getTaskDataContainer(project: Project): Iterable<KotlinCompileTaskData> =
project.getTaskDataMap().values.toSet()
fun register(
taskName: String,
compilation: AbstractKotlinCompilation<*>
): KotlinCompileTaskData {
val project = compilation.target.project
val container = project.getTaskDataMap()
@Suppress("UnstableApiUsage")
return KotlinCompileTaskData(
taskName,
compilation,
project.objects.property(File::class.java).apply {
set(project.provider { error("destinationDir was not set for task ${project.path}$taskName") })
},
project.objects.property(Boolean::class.javaObjectType).apply { set(false) }
).also {
container[taskName] = it
}
}
private fun Project.getTaskDataMap(): MutableMap</* taskName: */ String, KotlinCompileTaskData> {
val ext = project.extensions.getByType(ExtraPropertiesExtension::class.java)
if (!ext.has(EXT_NAME)) {
ext.set(EXT_NAME, mutableMapOf<String, KotlinCompileTaskData>())
}
@Suppress("UNCHECKED_CAST")
return ext.get(EXT_NAME) as MutableMap<String, KotlinCompileTaskData>
}
private const val EXT_NAME = "kotlin.incremental.taskdata"
}
}
@@ -25,6 +25,7 @@ import org.gradle.api.tasks.TaskInputs
import org.gradle.api.tasks.TaskOutputs import org.gradle.api.tasks.TaskOutputs
import org.gradle.api.tasks.bundling.AbstractArchiveTask import org.gradle.api.tasks.bundling.AbstractArchiveTask
import org.gradle.util.GradleVersion import org.gradle.util.GradleVersion
import java.io.File
internal val Task.inputsCompatible: TaskInputs get() = inputs internal val Task.inputsCompatible: TaskInputs get() = inputs
@@ -50,7 +51,7 @@ internal fun TaskInputs.dirCompatible(dirPath: Any) {
inputsDirMethod(this, dirPath) inputsDirMethod(this, dirPath)
} }
internal fun checkGradleCompatibility(minSupportedVersion: GradleVersion = GradleVersion.version("4.1")) { internal fun checkGradleCompatibility(minSupportedVersion: GradleVersion = GradleVersion.version("4.3")) {
val currentVersion = GradleVersion.current() val currentVersion = GradleVersion.current()
if (currentVersion < minSupportedVersion) { if (currentVersion < minSupportedVersion) {
throw GradleException( throw GradleException(
@@ -69,6 +70,16 @@ internal fun AbstractArchiveTask.setArchiveAppendixCompatible(appendixProvider:
} }
} }
internal val AbstractArchiveTask.archivePathCompatible: File
get() =
if (isGradleVersionAtLeast(5, 1)) {
@Suppress("UnstableApiUsage")
archiveFile.get().asFile
} else {
@Suppress("DEPRECATION")
archivePath
}
internal fun AbstractArchiveTask.setArchiveClassifierCompatible(classifierProvider: () -> String) { internal fun AbstractArchiveTask.setArchiveClassifierCompatible(classifierProvider: () -> String) {
if (isGradleVersionAtLeast(5, 2)) { if (isGradleVersionAtLeast(5, 2)) {
archiveClassifier.set(project.provider { classifierProvider() }) archiveClassifier.set(project.provider { classifierProvider() })