[Gradle] Update compile tasks to use properties and clean up code

Update AbstractKotlinCompile, KotlinCompile, and Kotlin2JsCompile to
use Gradle properties, and introduce Configurator classes that are
using configuration-time data to configure task. Also, introduce
TaskConfigurator interface that should be implemented by classes that
are used to configure tasks.
This commit is contained in:
Ivan Gavrilovic
2021-04-26 17:20:00 +01:00
committed by teamcityserver
parent 56cad96718
commit 571c9c10d4
2 changed files with 149 additions and 195 deletions
@@ -0,0 +1,13 @@
/*
* Copyright 2010-2021 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.internal.tasks
import org.gradle.api.Task
/** Classes that participate in task configuration should implement this interface. */
interface TaskConfigurator<T : Task> {
fun configure(task: T)
}
@@ -8,9 +8,13 @@ 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.ConfigurableFileCollection import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileCollection import org.gradle.api.file.FileCollection
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.logging.Logger import org.gradle.api.logging.Logger
import org.gradle.api.model.ObjectFactory import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider import org.gradle.api.provider.Provider
import org.gradle.api.tasks.* import org.gradle.api.tasks.*
import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.AbstractCompile
@@ -35,19 +39,20 @@ import org.jetbrains.kotlin.gradle.incremental.ChangedFiles
import org.jetbrains.kotlin.gradle.incremental.IncrementalModuleInfoBuildService import org.jetbrains.kotlin.gradle.incremental.IncrementalModuleInfoBuildService
import org.jetbrains.kotlin.gradle.incremental.IncrementalModuleInfoProvider import org.jetbrains.kotlin.gradle.incremental.IncrementalModuleInfoProvider
import org.jetbrains.kotlin.gradle.internal.* import org.jetbrains.kotlin.gradle.internal.*
import org.jetbrains.kotlin.gradle.internal.tasks.TaskConfigurator
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.GradleKotlinLogger import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger
import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
import org.jetbrains.kotlin.gradle.logging.kotlinDebug import org.jetbrains.kotlin.gradle.logging.kotlinDebug
import org.jetbrains.kotlin.gradle.logging.kotlinWarn
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithTransitiveClosure
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinCompilationData
import org.jetbrains.kotlin.gradle.report.ReportingSettings import org.jetbrains.kotlin.gradle.report.ReportingSettings
import org.jetbrains.kotlin.gradle.targets.js.ir.isProduceUnzippedKlib import org.jetbrains.kotlin.gradle.targets.js.ir.isProduceUnzippedKlib
import org.jetbrains.kotlin.gradle.utils.* import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.gradle.utils.isParentOf import org.jetbrains.kotlin.gradle.utils.isParentOf
import org.jetbrains.kotlin.gradle.utils.pathsAsStringRelativeTo import org.jetbrains.kotlin.gradle.utils.pathsAsStringRelativeTo
import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray
import org.jetbrains.kotlin.incremental.ChangedFiles import org.jetbrains.kotlin.incremental.ChangedFiles
import org.jetbrains.kotlin.library.impl.isKotlinLibrary import org.jetbrains.kotlin.library.impl.isKotlinLibrary
import org.jetbrains.kotlin.utils.JsLibraryUtils import org.jetbrains.kotlin.utils.JsLibraryUtils
@@ -93,11 +98,6 @@ abstract class AbstractKotlinCompileTool<T : CommonToolArguments>
} }
}) })
// a hack to remove compiler jar from the cp, will be dropped when compilerJarFile will be removed
private val classpathWithCompilerJar
get() = project.objects.fileCollection()
.from(compilerJarFile, defaultCompilerClasspath.filter { !it.nameWithoutExtension.startsWith("kotlin-compiler") })
protected abstract fun findKotlinCompilerClasspath(project: Project): List<File> protected abstract fun findKotlinCompilerClasspath(project: Project): List<File>
init { init {
@@ -109,53 +109,74 @@ abstract class AbstractKotlinCompileTool<T : CommonToolArguments>
} }
} }
public class GradleCompileTaskProvider { class GradleCompileTaskProvider(task: Task) {
constructor(task: Task) { val path: String = task.path
buildDir = task.project.buildDir val logger: Logger = task.logger
projectDir = task.project.rootProject.projectDir val buildDir: File = task.project.buildDir
rootDir = task.project.rootProject.rootDir val projectDir: File = task.project.rootProject.projectDir
sessionsDir = GradleCompilerRunner.sessionsDir(task.project) val rootDir: File = task.project.rootProject.rootDir
projectName = task.project.rootProject.name.normalizeForFlagFile() val sessionsDir: File = GradleCompilerRunner.sessionsDir(task.project)
val projectName: String = task.project.rootProject.name.normalizeForFlagFile()
val buildModulesInfo: Provider<out IncrementalModuleInfoProvider> = run {
val modulesInfo = GradleCompilerRunner.buildModulesInfo(task.project.gradle) val modulesInfo = GradleCompilerRunner.buildModulesInfo(task.project.gradle)
buildModulesInfo = task.project.gradle.sharedServices.registerIfAbsent( task.project.gradle.sharedServices.registerIfAbsent(
IncrementalModuleInfoBuildService.getServiceName(), IncrementalModuleInfoBuildService::class.java IncrementalModuleInfoBuildService.getServiceName(), IncrementalModuleInfoBuildService::class.java
) { ) {
it.parameters.info.set(modulesInfo) it.parameters.info.set(modulesInfo)
} }
path = task.path
logger = task.logger
} }
val path: String
val logger: Logger
val buildDir: File /*= project.buildDir*/
val projectDir: File /*= project.rootProject.projectDir*/
val rootDir: File /*= project.rootProject.rootDir*/
val sessionsDir: File/* = GradleCompilerRunner.sessionsDir(project)*/
val projectName: String /*= project.rootProject.name.normalizeForFlagFile()*/
val buildModulesInfo: Provider<out IncrementalModuleInfoProvider> /*= GradleCompilerRunner.buildModulesInfo(project.gradle)*/
} }
abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotlinCompileTool<T>(), UsesKotlinJavaToolchain { abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotlinCompileTool<T>(), UsesKotlinJavaToolchain {
open class Configurator<T : AbstractKotlinCompile<*>>(protected val compilation: KotlinCompilationData<*>) : TaskConfigurator<T> {
override fun configure(task: T) {
val project = task.project
task.friendPaths.from(project.provider { compilation.friendPaths })
if (compilation is KotlinCompilation<*>) {
task.friendSourceSets.set(project.provider { compilation.associateWithTransitiveClosure.map { it.name } })
// FIXME support compiler plugins with PM20
task.pluginClasspath.from(project.configurations.getByName(compilation.pluginConfigurationName))
}
task.moduleName.set(project.provider { compilation.moduleName })
task.sourceSetName.set(project.provider { compilation.compilationPurpose })
task.coroutines.value(
project.provider {
project.extensions.findByType(KotlinTopLevelExtension::class.java)!!.experimental.coroutines
?: PropertiesProvider(project).coroutines
?: Coroutines.DEFAULT
}
).disallowChanges()
task.multiPlatformEnabled.value(
project.provider {
project.plugins.any { it is KotlinPlatformPluginBase || it is KotlinMultiplatformPluginWrapper || it is KotlinPm20PluginWrapper }
}
).disallowChanges()
task.taskBuildDirectory.value(
project.layout.buildDirectory.dir("$KOTLIN_BUILD_DIR_NAME/${task.name}")
).disallowChanges()
task.localStateDirectories.from(task.taskBuildDirectory).disallowChanges()
}
}
init { init {
cacheOnlyIfEnabledForKotlin() cacheOnlyIfEnabledForKotlin()
} }
private val layout = project.layout private val layout = project.layout
@get:Internal
protected val objects: ObjectFactory = project.objects
// avoid creating directory in getter: this can lead to failure in parallel build // avoid creating directory in getter: this can lead to failure in parallel build
@get:LocalState @get:LocalState
internal val taskBuildDirectory: File by layout.buildDirectory.dir(KOTLIN_BUILD_DIR_NAME).map { it.file(name).asFile } internal val taskBuildDirectory: DirectoryProperty = objects.directoryProperty()
@get:Internal @get:Internal
internal val projectObjects = project.objects internal val buildHistoryFile
get() = taskBuildDirectory.file("build-history.bin")
private val localStateDirectoriesProvider: FileCollection = projectObjects.fileCollection().from({ taskBuildDirectory })
override fun localStateDirectories(): FileCollection = localStateDirectoriesProvider
// indicates that task should compile kotlin incrementally if possible // indicates that task should compile kotlin incrementally if possible
// it's not possible when IncrementalTaskInputs#isIncremental returns false (i.e first build) // it's not possible when IncrementalTaskInputs#isIncremental returns false (i.e first build)
@@ -163,7 +184,6 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotl
// don't rely on it to check if IC is enabled, use isIncrementalCompilationEnabled instead // don't rely on it to check if IC is enabled, use isIncrementalCompilationEnabled instead
@get:Internal @get:Internal
var incremental: Boolean = false var incremental: Boolean = false
get() = field
set(value) { set(value) {
field = value field = value
logger.kotlinDebug { "Set $this.incremental=$value" } logger.kotlinDebug { "Set $this.incremental=$value" }
@@ -176,117 +196,45 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotl
@get:Internal @get:Internal
internal var reportingSettings = ReportingSettings() internal var reportingSettings = ReportingSettings()
@get:Internal
internal val taskData: KotlinCompileTaskData = KotlinCompileTaskData.get(project, name)
@get:Input @get:Input
internal open var useModuleDetection: Boolean internal val useModuleDetection: Property<Boolean> = objects.property(Boolean::class.java).value(false)
get() = taskData.useModuleDetection.get()
set(value) {
taskData.useModuleDetection.set(value)
}
@get:Internal @get:Internal
protected val multiModuleICSettings: MultiModuleICSettings protected val multiModuleICSettings: MultiModuleICSettings
get() = MultiModuleICSettings(taskData.buildHistoryFile, useModuleDetection) get() = MultiModuleICSettings(buildHistoryFile.get().asFile, useModuleDetection.get())
@get:InputFiles @get:InputFiles
@get:Classpath @get:Classpath
open val pluginClasspath: FileCollection by project.provider { open val pluginClasspath: ConfigurableFileCollection = objects.fileCollection()
// FIXME support compiler plugins with PM20
(taskData.compilation as? KotlinCompilation<*>?)?.pluginConfigurationName?.let(project.configurations::getByName)
?: project.files()
}
@get:Internal @get:Internal
internal val pluginOptions = CompilerPluginOptions() internal val pluginOptions = CompilerPluginOptions()
@get:Classpath
@get:InputFiles
protected val additionalClasspath = arrayListOf<File>()
@get:Internal
internal val objects = project.objects
// Store this file collection before it is filtered by File::exists to ensure that Gradle Instant execution doesn't serialize the
// filtered files, losing those that don't exist yet and will only be created during build
private val compileClasspathImpl by project.provider {
classpath + objects.fileCollection().from(additionalClasspath)
}
@get:Internal // classpath already participates in the checks
internal val compileClasspath: Iterable<File>
get() = compileClasspathImpl
@field:Transient
private val sourceFilesExtensionsSources: MutableList<Iterable<String>> = mutableListOf()
@get:Input @get:Input
val sourceFilesExtensions: List<String> by project.provider { val sourceFilesExtensions: ListProperty<String> = objects.listProperty(String::class.java).value(DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS)
DEFAULT_KOTLIN_SOURCE_FILES_EXTENSIONS + sourceFilesExtensionsSources.flatten()
}
internal fun sourceFilesExtensions(extensions: Iterable<String>) {
sourceFilesExtensionsSources.add(extensions)
}
@get:Internal
@field:Transient
internal val kotlinExtProvider: KotlinTopLevelExtension = project.extensions.findByType(KotlinTopLevelExtension::class.java)!!
override fun getDestinationDir(): File =
taskData.destinationDir.get()
override fun setDestinationDir(provider: Provider<File>) {
taskData.destinationDir.set(provider)
}
fun setDestinationDir(provider: () -> File) {
taskData.destinationDir.set(project.provider(provider))
}
override fun setDestinationDir(destinationDir: File) {
taskData.destinationDir.set(destinationDir)
}
@get:Internal
internal var coroutinesFromGradleProperties: Coroutines? = null
// Input is needed to force rebuild even if source files are not changed // Input is needed to force rebuild even if source files are not changed
@get:Input @get:Input
internal val coroutinesStr: Provider<String> = project.provider { coroutines.get().name } internal val coroutines: Property<Coroutines> = objects.property(Coroutines::class.java)
@get:Input
internal val coroutines: Provider<Coroutines> = project.provider {
kotlinExtProvider.experimental.coroutines
?: coroutinesFromGradleProperties
?: Coroutines.DEFAULT
}
@get:Internal @get:Internal
internal var javaOutputDir: File? internal val javaOutputDir: DirectoryProperty = objects.directoryProperty()
get() = taskData.javaOutputDir
set(value) {
taskData.javaOutputDir = value
}
@get:Internal @get:Internal
internal val sourceSetName: String internal val sourceSetName: Property<String> = objects.property(String::class.java)
get() = taskData.compilation.compilationPurpose
@get:InputFiles @get:InputFiles
@get:PathSensitive(PathSensitivity.RELATIVE) @get:PathSensitive(PathSensitivity.RELATIVE)
internal var commonSourceSet: FileCollection = project.files() //TODO internal val commonSourceSet: ConfigurableFileCollection = objects.fileCollection()
@get:Input @get:Input
internal val moduleName: String by project.provider { internal val moduleName: Property<String> = objects.property(String::class.java)
taskData.compilation.moduleName
} @get:Internal
internal val friendSourceSets = objects.listProperty(String::class.java)
@get:Internal // takes part in the compiler arguments @get:Internal // takes part in the compiler arguments
val friendPaths: FileCollection = project.files( val friendPaths: ConfigurableFileCollection = objects.fileCollection()
project.provider { taskData.compilation.friendPaths }
)
private val kotlinLogger by lazy { GradleKotlinLogger(logger) } private val kotlinLogger by lazy { GradleKotlinLogger(logger) }
@@ -376,7 +324,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotl
sourceRoots.log(this.name, logger) sourceRoots.log(this.name, logger)
val args = prepareCompilerArguments() val args = prepareCompilerArguments()
taskBuildDirectory.mkdirs() taskBuildDirectory.get().asFile.mkdirs()
callCompilerAsync(args, sourceRoots, ChangedFiles(inputs)) callCompilerAsync(args, sourceRoots, ChangedFiles(inputs))
} }
@@ -390,9 +338,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotl
internal abstract fun callCompilerAsync(args: T, sourceRoots: SourceRoots, changedFiles: ChangedFiles) internal abstract fun callCompilerAsync(args: T, sourceRoots: SourceRoots, changedFiles: ChangedFiles)
@get:Input @get:Input
internal val isMultiplatform: Boolean by lazy { internal val multiPlatformEnabled: Property<Boolean> = objects.property(Boolean::class.java)
project.plugins.any { it is KotlinPlatformPluginBase || it is KotlinMultiplatformPluginWrapper || it is KotlinPm20PluginWrapper }
}
@get:Internal @get:Internal
internal val abstractKotlinCompileArgumentsContributor by lazy { internal val abstractKotlinCompileArgumentsContributor by lazy {
@@ -408,74 +354,59 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments> : AbstractKotl
) )
} }
internal fun setupPlugins(compilerArgs: T) {
compilerArgs.pluginClasspaths = pluginClasspath.toSortedPathsArray()
compilerArgs.pluginOptions = pluginOptions.arguments.toTypedArray()
}
protected fun hasFilesInTaskBuildDirectory(): Boolean { protected fun hasFilesInTaskBuildDirectory(): Boolean {
val taskBuildDir = taskBuildDirectory val taskBuildDir = taskBuildDirectory.get().asFile
return taskBuildDir.walk().any { it != taskBuildDir && it.isFile } return taskBuildDir.walk().any { it != taskBuildDir && it.isFile }
} }
} }
open class KotlinCompileArgumentsProvider<T : AbstractKotlinCompile<out CommonCompilerArguments>>(taskProvider: T) { open class KotlinCompileArgumentsProvider<T : AbstractKotlinCompile<out CommonCompilerArguments>>(taskProvider: T) {
val coroutines: Provider<Coroutines> val coroutines: Provider<Coroutines> = taskProvider.coroutines
val logger: Logger val logger: Logger = taskProvider.logger
val isMultiplatform: Boolean val isMultiplatform: Boolean = taskProvider.multiPlatformEnabled.get()
val pluginClasspath: FileCollection val pluginClasspath: FileCollection = taskProvider.pluginClasspath
val pluginOptions: CompilerPluginOptions val pluginOptions: CompilerPluginOptions = taskProvider.pluginOptions
init {
coroutines = taskProvider.coroutines
logger = taskProvider.logger
isMultiplatform = taskProvider.isMultiplatform
pluginClasspath = taskProvider.pluginClasspath
pluginOptions = taskProvider.pluginOptions
}
} }
class KotlinJvmCompilerArgumentsProvider class KotlinJvmCompilerArgumentsProvider
(taskProvider: KotlinCompile) : KotlinCompileArgumentsProvider<KotlinCompile>(taskProvider) { (taskProvider: KotlinCompile) : KotlinCompileArgumentsProvider<KotlinCompile>(taskProvider) {
val moduleName: String = taskProvider.moduleName.get()
val moduleName: String val friendPaths: FileCollection = taskProvider.friendPaths
val friendPaths: FileCollection val compileClasspath: Iterable<File> = taskProvider.classpath
val compileClasspath: Iterable<File> val destinationDir: File = taskProvider.destinationDir
val destinationDir: File internal val kotlinOptions: List<KotlinJvmOptionsImpl?> = listOfNotNull(
internal val kotlinOptions: List<KotlinJvmOptionsImpl?> taskProvider.parentKotlinOptionsImpl.orNull as? KotlinJvmOptionsImpl,
taskProvider.kotlinOptions as KotlinJvmOptionsImpl
init { )
// super(taskProvider)
moduleName = taskProvider.moduleName
friendPaths = taskProvider.friendPaths
compileClasspath = taskProvider.compileClasspath
destinationDir = taskProvider.destinationDir
kotlinOptions = listOfNotNull(
taskProvider.parentKotlinOptionsImpl,
taskProvider.kotlinOptions as KotlinJvmOptionsImpl
)
}
} }
internal inline val <reified T : Task> T.thisTaskProvider: TaskProvider<out T> internal inline val <reified T : Task> T.thisTaskProvider: TaskProvider<out T>
get() = checkNotNull(project.locateTask<T>(name)) get() = checkNotNull(project.locateTask<T>(name))
@CacheableTask @CacheableTask
open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), KotlinJvmCompile { abstract class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), KotlinJvmCompile {
@get:Internal
internal var parentKotlinOptionsImpl: KotlinJvmOptionsImpl? = null
override val kotlinOptions: KotlinJvmOptions class Configurator(kotlinCompilation: KotlinCompilationData<*>) : AbstractKotlinCompile.Configurator<KotlinCompile>(kotlinCompilation) {
get() = taskData.compilation.kotlinOptions as KotlinJvmOptions override fun configure(task: KotlinCompile) {
super.configure(task)
task.kotlinOptionsProperty.set(compilation.kotlinOptions as KotlinJvmOptions)
}
}
@get:Internal
internal val parentKotlinOptionsImpl: Property<KotlinJvmOptions> = objects.property(KotlinJvmOptions::class.java)
override val kotlinOptionsProperty: Property<KotlinJvmOptions> = objects.property(KotlinJvmOptions::class.java)
@get:Internal @get:Internal
@field:Transient @field:Transient
internal open val sourceRootsContainer = FilteringSourceRootsContainer(project.objects) internal open val sourceRootsContainer = FilteringSourceRootsContainer(objects)
private val jvmSourceRoots by project.provider { private val jvmSourceRoots by project.provider {
// serialize in the task state for configuration caching; avoid building anew in task execution, as it may access the project model // serialize in the task state for configuration caching; avoid building anew in task execution, as it may access the project model
SourceRoots.ForJvm.create(source, sourceRootsContainer, sourceFilesExtensions) SourceRoots.ForJvm.create(source, sourceRootsContainer, sourceFilesExtensions.get())
} }
/** A package prefix that is used for locating Java sources in a directory structure with non-full-depth packages. /** A package prefix that is used for locating Java sources in a directory structure with non-full-depth packages.
@@ -530,7 +461,7 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
logger.info(USING_JVM_INCREMENTAL_COMPILATION_MESSAGE) logger.info(USING_JVM_INCREMENTAL_COMPILATION_MESSAGE)
IncrementalCompilationEnvironment( IncrementalCompilationEnvironment(
if (hasFilesInTaskBuildDirectory()) changedFiles else ChangedFiles.Unknown(), if (hasFilesInTaskBuildDirectory()) changedFiles else ChangedFiles.Unknown(),
taskBuildDirectory, taskBuildDirectory.get().asFile,
usePreciseJavaTracking = usePreciseJavaTracking, usePreciseJavaTracking = usePreciseJavaTracking,
disableMultiModuleIC = disableMultiModuleIC, disableMultiModuleIC = disableMultiModuleIC,
multiModuleICSettings = multiModuleICSettings multiModuleICSettings = multiModuleICSettings
@@ -542,7 +473,7 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
outputFiles = allOutputFiles(), outputFiles = allOutputFiles(),
reportingSettings = reportingSettings, reportingSettings = reportingSettings,
incrementalCompilationEnvironment = icEnv, incrementalCompilationEnvironment = icEnv,
kotlinScriptExtensions = sourceFilesExtensions.toTypedArray() kotlinScriptExtensions = sourceFilesExtensions.get().toTypedArray()
) )
compilerRunner.runJvmCompilerAsync( compilerRunner.runJvmCompilerAsync(
sourceRoots.kotlinSourceFiles, sourceRoots.kotlinSourceFiles,
@@ -556,7 +487,7 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
@get:Input @get:Input
val disableMultiModuleIC: Boolean by lazy { val disableMultiModuleIC: Boolean by lazy {
if (!isIncrementalCompilationEnabled() || javaOutputDir == null) { if (!isIncrementalCompilationEnabled() || !javaOutputDir.isPresent) {
false false
} else { } else {
@@ -565,7 +496,7 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
if (it is AbstractCompile && if (it is AbstractCompile &&
it !is JavaCompile && it !is JavaCompile &&
it !is AbstractKotlinCompile<*> && it !is AbstractKotlinCompile<*> &&
javaOutputDir!!.isParentOf(it.destinationDir) javaOutputDir.get().asFile.isParentOf(it.destinationDir)
) { ) {
illegalTaskOrNull = illegalTaskOrNull ?: it illegalTaskOrNull = illegalTaskOrNull ?: it
} }
@@ -596,7 +527,7 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
} }
@CacheableTask @CacheableTask
internal open class KotlinCompileWithWorkers @Inject constructor( internal abstract class KotlinCompileWithWorkers @Inject constructor(
private val workerExecutor: WorkerExecutor private val workerExecutor: WorkerExecutor
) : KotlinCompile() { ) : KotlinCompile() {
@@ -612,7 +543,7 @@ internal open class KotlinCompileWithWorkers @Inject constructor(
} }
@CacheableTask @CacheableTask
internal open class Kotlin2JsCompileWithWorkers @Inject constructor( internal abstract class Kotlin2JsCompileWithWorkers @Inject constructor(
objectFactory: ObjectFactory, objectFactory: ObjectFactory,
private val workerExecutor: WorkerExecutor private val workerExecutor: WorkerExecutor
) : Kotlin2JsCompile(objectFactory) { ) : Kotlin2JsCompile(objectFactory) {
@@ -629,7 +560,7 @@ internal open class Kotlin2JsCompileWithWorkers @Inject constructor(
} }
@CacheableTask @CacheableTask
internal open class KotlinCompileCommonWithWorkers @Inject constructor( internal abstract class KotlinCompileCommonWithWorkers @Inject constructor(
private val workerExecutor: WorkerExecutor private val workerExecutor: WorkerExecutor
) : KotlinCompileCommon() { ) : KotlinCompileCommon() {
override fun compilerRunner( override fun compilerRunner(
@@ -644,7 +575,7 @@ internal open class KotlinCompileCommonWithWorkers @Inject constructor(
} }
@CacheableTask @CacheableTask
open class Kotlin2JsCompile @Inject constructor( abstract class Kotlin2JsCompile @Inject constructor(
objectFactory: ObjectFactory objectFactory: ObjectFactory
) : AbstractKotlinCompile<K2JSCompilerArguments>(), KotlinJsCompile { ) : AbstractKotlinCompile<K2JSCompilerArguments>(), KotlinJsCompile {
@@ -652,11 +583,28 @@ open class Kotlin2JsCompile @Inject constructor(
incremental = true incremental = true
} }
override val kotlinOptions = taskData.compilation.kotlinOptions as KotlinJsOptions open class Configurator<T : Kotlin2JsCompile>(compilation: KotlinCompilationData<*>) : AbstractKotlinCompile.Configurator<T>(compilation) {
@get:Internal override fun configure(task: T) {
protected val defaultOutputFile: File super.configure(task)
get() = File(destinationDir, "${taskData.compilation.ownModuleName}.js")
task.kotlinOptionsProperty.set(compilation.kotlinOptions as KotlinJsOptions)
task.outputFile.value(
task.kotlinOptionsProperty.map {
it.outputFile?.let(::File)
?: task.destinationDirectory.locationOnly.get().asFile.resolve("${compilation.ownModuleName}.js")
}
).disallowChanges()
task.optionalOutputFile.fileProvider(
task.kotlinOptionsProperty.flatMap { jsOptions ->
task.outputFile.takeIf { !jsOptions.isProduceUnzippedKlib() }
?: task.project.objects.fileProperty().asFile
}
).disallowChanges()
}
}
override val kotlinOptionsProperty: Property<KotlinJsOptions> = objectFactory.property(KotlinJsOptions::class.java)
@get:Input @get:Input
internal var incrementalJsKlib: Boolean = true internal var incrementalJsKlib: Boolean = true
@@ -669,20 +617,13 @@ open class Kotlin2JsCompile @Inject constructor(
else -> incremental else -> incremental
} }
// This can be file or directory
@get:Internal @get:Internal
val outputFile: File abstract val outputFile: Property<File>
get() = kotlinOptions.outputFile?.let(::File) ?: defaultOutputFile
@get:OutputFile @get:OutputFile
@get:Optional @get:Optional
val outputFileOrNull: File? abstract val optionalOutputFile: RegularFileProperty
get() = outputFile.let { file ->
if (!kotlinOptions.isProduceUnzippedKlib()) {
file
} else {
null
}
}
override fun findKotlinCompilerClasspath(project: Project): List<File> = override fun findKotlinCompilerClasspath(project: Project): List<File> =
findKotlinJsCompilerClasspath(project) findKotlinJsCompilerClasspath(project)
@@ -695,20 +636,20 @@ open class Kotlin2JsCompile @Inject constructor(
super.setupCompilerArgs(args, defaultsOnly = defaultsOnly, ignoreClasspathResolutionErrors = ignoreClasspathResolutionErrors) super.setupCompilerArgs(args, defaultsOnly = defaultsOnly, ignoreClasspathResolutionErrors = ignoreClasspathResolutionErrors)
try { try {
outputFile.canonicalPath outputFile.get().canonicalPath
} catch (ex: Throwable) { } catch (ex: Throwable) {
logger.warn("IO EXCEPTION: outputFile: ${outputFile.path}") logger.warn("IO EXCEPTION: outputFile: ${outputFile.get().path}")
throw ex throw ex
} }
args.outputFile = outputFile.absoluteFile.normalize().absolutePath args.outputFile = outputFile.get().absoluteFile.normalize().absolutePath
if (defaultsOnly) return if (defaultsOnly) return
(kotlinOptions as KotlinJsOptionsImpl).updateArguments(args) (kotlinOptions as KotlinJsOptionsImpl).updateArguments(args)
} }
override fun getSourceRoots() = SourceRoots.KotlinOnly.create(getSource(), sourceFilesExtensions) override fun getSourceRoots() = SourceRoots.KotlinOnly.create(getSource(), sourceFilesExtensions.get())
@get:InputFiles @get:InputFiles
@get:Optional @get:Optional
@@ -776,7 +717,7 @@ open class Kotlin2JsCompile @Inject constructor(
logger.info(USING_JS_IR_BACKEND_MESSAGE) logger.info(USING_JS_IR_BACKEND_MESSAGE)
} }
val dependencies = compileClasspath val dependencies = classpath
.filter { it.exists() && libraryFilter(it) } .filter { it.exists() && libraryFilter(it) }
.map { it.canonicalPath } .map { it.canonicalPath }
@@ -802,7 +743,7 @@ open class Kotlin2JsCompile @Inject constructor(
logger.info(USING_JS_INCREMENTAL_COMPILATION_MESSAGE) logger.info(USING_JS_INCREMENTAL_COMPILATION_MESSAGE)
IncrementalCompilationEnvironment( IncrementalCompilationEnvironment(
if (hasFilesInTaskBuildDirectory()) changedFiles else ChangedFiles.Unknown(), if (hasFilesInTaskBuildDirectory()) changedFiles else ChangedFiles.Unknown(),
taskBuildDirectory, taskBuildDirectory.get().asFile,
multiModuleICSettings = multiModuleICSettings multiModuleICSettings = multiModuleICSettings
) )
} else null } else null