Support Gradle instant execution for Kapt tasks
* In the Kotlin/JVM tasks, move the compiler arguments setup logic to a separate class, so that it can be reused by the Kapt tasks without directly referencing the Kotlin/JVM tasks * In the Kapt tasks, carefully capture the values using the Provider API so that the task can be serialized for Instant Execution and then deserialized and executed without relying on the project model Issue #KT-35181 Fixed
This commit is contained in:
+39
-12
@@ -15,7 +15,7 @@ import kotlin.test.fail
|
||||
|
||||
class InstantExecutionIT : BaseGradleIT() {
|
||||
private val androidGradlePluginVersion: AGPVersion
|
||||
get() = AGPVersion.v4_0_ALPHA_1
|
||||
get() = AGPVersion.v4_0_ALPHA_8
|
||||
|
||||
override fun defaultBuildOptions() =
|
||||
super.defaultBuildOptions().copy(
|
||||
@@ -23,7 +23,7 @@ class InstantExecutionIT : BaseGradleIT() {
|
||||
androidGradlePluginVersion = androidGradlePluginVersion
|
||||
)
|
||||
|
||||
private val minimumGradleVersion = GradleVersionRequired.AtLeast("6.1-milestone-1")
|
||||
private val minimumGradleVersion = GradleVersionRequired.AtLeast("6.1-rc-3")
|
||||
|
||||
@Test
|
||||
fun testSimpleKotlinJvmProject() = with(Project("kotlinProject", minimumGradleVersion)) {
|
||||
@@ -31,14 +31,37 @@ class InstantExecutionIT : BaseGradleIT() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSimpleKotlinAndroidProject() = with(Project("AndroidProject", minimumGradleVersion)) {
|
||||
applyAndroidAndroid40Alpha4KotlinVersionWorkaround()
|
||||
testInstantExecutionOf(":Lib:compileFlavor1DebugKotlin", ":Android:compileFlavor1DebugKotlin")
|
||||
fun testSimpleKotlinAndroidProject() = with(Project("android-dagger", minimumGradleVersion, "kapt2")) {
|
||||
applyAndroid40Alpha4KotlinVersionWorkaround()
|
||||
projectDir.resolve("gradle.properties").appendText("\nkapt.incremental.apt=false")
|
||||
testInstantExecutionOf(":app:compileDebugKotlin", ":app:kaptDebugKotlin", ":app:kaptGenerateStubsDebugKotlin")
|
||||
}
|
||||
|
||||
private fun Project.testInstantExecutionOf(vararg taskNames: String) {
|
||||
@Test
|
||||
fun testIncrementalKaptProject() = with(getIncrementalKaptProject()) {
|
||||
testInstantExecutionOf(
|
||||
":compileKotlin",
|
||||
":kaptKotlin",
|
||||
buildOptions = defaultBuildOptions().copy(
|
||||
incremental = true,
|
||||
kaptOptions = KaptOptions(
|
||||
verbose = true,
|
||||
useWorkers = true,
|
||||
incrementalKapt = true,
|
||||
includeCompileClasspath = false
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun getIncrementalKaptProject() =
|
||||
Project("kaptIncrementalCompilationProject", minimumGradleVersion).apply {
|
||||
setupIncrementalAptProject("AGGREGATING")
|
||||
}
|
||||
|
||||
private fun Project.testInstantExecutionOf(vararg taskNames: String, buildOptions: BuildOptions = defaultBuildOptions()) {
|
||||
// First, run a build that serializes the tasks state for instant execution in further builds
|
||||
instantExecutionOf(*taskNames) {
|
||||
instantExecutionOf(*taskNames, buildOptions = buildOptions) {
|
||||
assertSuccessful()
|
||||
assertTasksExecuted(*taskNames)
|
||||
checkInstantExecutionSucceeded()
|
||||
@@ -49,12 +72,12 @@ class InstantExecutionIT : BaseGradleIT() {
|
||||
}
|
||||
|
||||
// Then run a build where tasks states are deserialized to check that they work correctly in this mode
|
||||
instantExecutionOf(*taskNames) {
|
||||
instantExecutionOf(*taskNames, buildOptions = buildOptions) {
|
||||
assertSuccessful()
|
||||
assertTasksExecuted(*taskNames)
|
||||
}
|
||||
|
||||
instantExecutionOf(*taskNames) {
|
||||
instantExecutionOf(*taskNames, buildOptions = buildOptions) {
|
||||
assertSuccessful()
|
||||
assertTasksUpToDate(*taskNames)
|
||||
}
|
||||
@@ -66,8 +89,12 @@ class InstantExecutionIT : BaseGradleIT() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.instantExecutionOf(vararg tasks: String, check: CompiledProject.() -> Unit) =
|
||||
build("-Dorg.gradle.unsafe.instant-execution=true", *tasks, check = check)
|
||||
private fun Project.instantExecutionOf(
|
||||
vararg tasks: String,
|
||||
buildOptions: BuildOptions = defaultBuildOptions(),
|
||||
check: CompiledProject.() -> Unit
|
||||
) =
|
||||
build("-Dorg.gradle.unsafe.instant-execution=true", *tasks, options = buildOptions, check = check)
|
||||
|
||||
/**
|
||||
* Copies all files from the directory containing the given [htmlReportFile] to a
|
||||
@@ -98,7 +125,7 @@ class InstantExecutionIT : BaseGradleIT() {
|
||||
* test project's repositories, where there's no 'kotlin-eap' repo.
|
||||
* TODO remove this workaround once an Android Gradle plugin version is used that depends on the stable Kotlin version
|
||||
*/
|
||||
private fun Project.applyAndroidAndroid40Alpha4KotlinVersionWorkaround() {
|
||||
private fun Project.applyAndroid40Alpha4KotlinVersionWorkaround() {
|
||||
setupWorkingDir()
|
||||
|
||||
val resolutionStrategyHack = """
|
||||
|
||||
+1
-1
@@ -22,6 +22,6 @@ class AGPVersion private constructor(private val versionNumber: VersionNumber) {
|
||||
val v3_1_0 = fromString("3.1.0")
|
||||
val v3_2_0 = fromString("3.2.0")
|
||||
val v3_3_2 = fromString("3.3.2")
|
||||
val v4_0_ALPHA_1 = fromString("4.0.0-alpha01")
|
||||
val v4_0_ALPHA_8 = fromString("4.0.0-alpha08")
|
||||
}
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.internal
|
||||
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.jetbrains.kotlin.cli.common.arguments.*
|
||||
import org.jetbrains.kotlin.gradle.dsl.*
|
||||
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
||||
import org.jetbrains.kotlin.gradle.tasks.*
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||
import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray
|
||||
import org.jetbrains.kotlin.incremental.classpathAsList
|
||||
import org.jetbrains.kotlin.incremental.destinationAsFile
|
||||
|
||||
internal interface CompilerArgumentsContributor<in T : CommonToolArguments> {
|
||||
fun contributeArguments(
|
||||
args: T,
|
||||
flags: Collection<CompilerArgumentsConfigurationFlag>
|
||||
)
|
||||
}
|
||||
|
||||
internal interface CompilerArgumentsConfigurationFlag
|
||||
|
||||
internal object DefaultsOnly : CompilerArgumentsConfigurationFlag
|
||||
internal object IgnoreClasspathResolutionErrors : CompilerArgumentsConfigurationFlag
|
||||
|
||||
internal fun compilerArgumentsConfigurationFlags(defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) =
|
||||
mutableSetOf<CompilerArgumentsConfigurationFlag>().apply {
|
||||
if (defaultsOnly) add(DefaultsOnly)
|
||||
if (ignoreClasspathResolutionErrors) add(IgnoreClasspathResolutionErrors)
|
||||
}
|
||||
|
||||
/** The primary purpose of this class is to encapsulate compiler arguments setup done by the AbstractKotlinCompiler tasks,
|
||||
* but outside the tasks, so that this state & logic can be reused without referencing the task directly. */
|
||||
internal open class AbstractKotlinCompileArgumentsContributor<T : CommonCompilerArguments>(
|
||||
// Don't save this reference into a property! That would be hostile to Gradle instant execution
|
||||
taskProvider: TaskProvider<out AbstractKotlinCompile<T>>
|
||||
) : CompilerArgumentsContributor<T> {
|
||||
private val coroutines by taskProvider.map { it.coroutines }
|
||||
|
||||
protected val logger by taskProvider.map { it.logger }
|
||||
|
||||
private val isMultiplatform by taskProvider.map { it.isMultiplatform }
|
||||
|
||||
private val pluginClasspath by taskProvider.map { it.pluginClasspath }
|
||||
private val pluginOptions by taskProvider.map { it.pluginOptions }
|
||||
|
||||
override fun contributeArguments(
|
||||
args: T,
|
||||
flags: Collection<CompilerArgumentsConfigurationFlag>
|
||||
) {
|
||||
args.coroutinesState = when (coroutines) {
|
||||
Coroutines.ENABLE -> CommonCompilerArguments.ENABLE
|
||||
Coroutines.WARN -> CommonCompilerArguments.WARN
|
||||
Coroutines.ERROR -> CommonCompilerArguments.ERROR
|
||||
Coroutines.DEFAULT -> CommonCompilerArguments.DEFAULT
|
||||
}
|
||||
|
||||
logger.kotlinDebug { "args.coroutinesState=${args.coroutinesState}" }
|
||||
|
||||
if (logger.isDebugEnabled) {
|
||||
args.verbose = true
|
||||
}
|
||||
|
||||
args.multiPlatform = isMultiplatform
|
||||
|
||||
setupPlugins(args)
|
||||
}
|
||||
|
||||
internal fun setupPlugins(compilerArgs: T) {
|
||||
compilerArgs.pluginClasspaths = pluginClasspath.toSortedPathsArray()
|
||||
compilerArgs.pluginOptions = pluginOptions.arguments.toTypedArray()
|
||||
}
|
||||
}
|
||||
|
||||
internal open class KotlinJvmCompilerArgumentsContributor(
|
||||
// Don't save this reference into a property! That would be hostile to Gradle instant execution. Only map it to the task properties.
|
||||
taskProvider: TaskProvider<out KotlinCompile>
|
||||
) : AbstractKotlinCompileArgumentsContributor<K2JVMCompilerArguments>(taskProvider) {
|
||||
|
||||
private val moduleName by taskProvider.map { it.moduleName }
|
||||
|
||||
private val friendPaths by taskProvider.map { it.friendPaths }
|
||||
|
||||
private val compileClasspath by taskProvider.map { it.compileClasspath }
|
||||
|
||||
private val destinationDir by taskProvider.map { it.destinationDir }
|
||||
|
||||
private val kotlinOptions by taskProvider.map {
|
||||
listOfNotNull(
|
||||
it.parentKotlinOptionsImpl as KotlinJvmOptionsImpl?,
|
||||
it.kotlinOptions as KotlinJvmOptionsImpl
|
||||
)
|
||||
}
|
||||
|
||||
override fun contributeArguments(
|
||||
args: K2JVMCompilerArguments,
|
||||
flags: Collection<CompilerArgumentsConfigurationFlag>
|
||||
) {
|
||||
args.fillDefaultValues()
|
||||
|
||||
super.contributeArguments(args, flags)
|
||||
|
||||
args.moduleName = moduleName
|
||||
logger.kotlinDebug { "args.moduleName = ${args.moduleName}" }
|
||||
|
||||
args.friendPaths = friendPaths
|
||||
logger.kotlinDebug { "args.friendPaths = ${args.friendPaths?.joinToString() ?: "[]"}" }
|
||||
|
||||
if (DefaultsOnly in flags) return
|
||||
|
||||
args.allowNoSourceFiles = true
|
||||
args.classpathAsList = try {
|
||||
compileClasspath.toList().filter { it.exists() }
|
||||
} catch (e: Exception) {
|
||||
if (IgnoreClasspathResolutionErrors in flags) emptyList() else throw(e)
|
||||
}
|
||||
args.destinationAsFile = destinationDir
|
||||
|
||||
kotlinOptions.forEach { it.updateArguments(args) }
|
||||
}
|
||||
}
|
||||
+20
-11
@@ -19,15 +19,12 @@ package org.jetbrains.kotlin.gradle.internal
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
|
||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||
import org.jetbrains.kotlin.gradle.incremental.ChangedFiles
|
||||
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
||||
import org.jetbrains.kotlin.gradle.tasks.FilteringSourceRootsContainer
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.SourceRoots
|
||||
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||
import org.jetbrains.kotlin.gradle.utils.isParentOf
|
||||
import org.jetbrains.kotlin.gradle.utils.pathsAsStringRelativeTo
|
||||
import org.jetbrains.kotlin.incremental.classpathAsList
|
||||
import org.jetbrains.kotlin.incremental.destinationAsFile
|
||||
import java.io.File
|
||||
@@ -37,6 +34,7 @@ open class KaptGenerateStubsTask : KotlinCompile() {
|
||||
override val sourceRootsContainer = FilteringSourceRootsContainer(emptyList(), { isSourceRootAllowed(it) })
|
||||
|
||||
@get:Internal
|
||||
@field:Transient // can't serialize task references in Gradle instant execution state
|
||||
internal lateinit var kotlinCompileTask: KotlinCompile
|
||||
|
||||
@get:OutputDirectory
|
||||
@@ -48,7 +46,7 @@ open class KaptGenerateStubsTask : KotlinCompile() {
|
||||
@get:Classpath
|
||||
@get:InputFiles
|
||||
val kaptClasspath: FileCollection
|
||||
get() = project.files(*kaptClasspathConfigurations.toTypedArray())
|
||||
get() = project.files(kaptClasspathConfigurations)
|
||||
|
||||
@get:Internal
|
||||
internal lateinit var kaptClasspathConfigurations: List<Configuration>
|
||||
@@ -56,8 +54,9 @@ open class KaptGenerateStubsTask : KotlinCompile() {
|
||||
@get:Classpath
|
||||
@get:InputFiles
|
||||
@Suppress("unused")
|
||||
internal val kotlinTaskPluginClasspath
|
||||
get() = kotlinCompileTask.pluginClasspath
|
||||
internal val kotlinTaskPluginClasspath by project.provider {
|
||||
kotlinCompileTask.pluginClasspath
|
||||
}
|
||||
|
||||
@get:Input
|
||||
override var useModuleDetection: Boolean
|
||||
@@ -66,11 +65,11 @@ open class KaptGenerateStubsTask : KotlinCompile() {
|
||||
error("KaptGenerateStubsTask.useModuleDetection setter should not be called!")
|
||||
}
|
||||
|
||||
override fun source(vararg sources: Any?): SourceTask? {
|
||||
override fun source(vararg sources: Any): SourceTask {
|
||||
return super.source(sourceRootsContainer.add(sources))
|
||||
}
|
||||
|
||||
override fun setSource(sources: Any?) {
|
||||
override fun setSource(sources: Any) {
|
||||
super.setSource(sourceRootsContainer.set(sources))
|
||||
}
|
||||
|
||||
@@ -79,8 +78,15 @@ open class KaptGenerateStubsTask : KotlinCompile() {
|
||||
!stubsDir.isParentOf(source) &&
|
||||
!generatedSourcesDir.isParentOf(source)
|
||||
|
||||
private val compileKotlinArgumentsContributor by project.provider {
|
||||
kotlinCompileTask.compilerArgumentsContributor
|
||||
}
|
||||
|
||||
override fun setupCompilerArgs(args: K2JVMCompilerArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) {
|
||||
kotlinCompileTask.setupCompilerArgs(args, ignoreClasspathResolutionErrors = ignoreClasspathResolutionErrors)
|
||||
compileKotlinArgumentsContributor.contributeArguments(args, compilerArgumentsConfigurationFlags(
|
||||
defaultsOnly,
|
||||
ignoreClasspathResolutionErrors
|
||||
))
|
||||
|
||||
val pluginOptionsWithKapt = pluginOptions.withWrappedKaptOptions(withApClasspath = kaptClasspath)
|
||||
args.pluginOptions = (pluginOptionsWithKapt.arguments + args.pluginOptions!!).toTypedArray()
|
||||
@@ -90,10 +96,13 @@ open class KaptGenerateStubsTask : KotlinCompile() {
|
||||
args.destinationAsFile = this.destinationDir
|
||||
}
|
||||
|
||||
override fun getSourceRoots(): SourceRoots.ForJvm =
|
||||
private val sourceRoots by project.provider {
|
||||
kotlinCompileTask.getSourceRoots().let {
|
||||
val javaSourceRoots = it.javaSourceRoots.filterTo(HashSet()) { isSourceRootAllowed(it) }
|
||||
val kotlinSourceFiles = it.kotlinSourceFiles
|
||||
SourceRoots.ForJvm(kotlinSourceFiles, javaSourceRoots)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSourceRoots(): SourceRoots.ForJvm = sourceRoots
|
||||
}
|
||||
+25
-13
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.gradle.internal.tasks.TaskWithLocalState
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.cacheOnlyIfEnabledForKotlin
|
||||
import org.jetbrains.kotlin.gradle.tasks.clearLocalState
|
||||
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||
import org.jetbrains.kotlin.gradle.utils.isJavaFile
|
||||
import java.io.File
|
||||
import java.util.jar.JarFile
|
||||
@@ -30,6 +31,7 @@ abstract class KaptTask : ConventionTask(), TaskWithLocalState {
|
||||
override fun localStateDirectories(): FileCollection = project.files()
|
||||
|
||||
@get:Internal
|
||||
@field:Transient
|
||||
internal lateinit var kotlinCompileTask: KotlinCompile
|
||||
|
||||
@get:Internal
|
||||
@@ -38,12 +40,13 @@ abstract class KaptTask : ConventionTask(), TaskWithLocalState {
|
||||
@get:Classpath
|
||||
@get:InputFiles
|
||||
val kaptClasspath: FileCollection
|
||||
get() = project.files(*kaptClasspathConfigurations.toTypedArray())
|
||||
get() = project.files(kaptClasspathConfigurations)
|
||||
|
||||
@get:Classpath
|
||||
@get:InputFiles
|
||||
val compilerClasspath: List<File>
|
||||
get() = kotlinCompileTask.computedCompilerClasspath
|
||||
val compilerClasspath: List<File> by project.provider {
|
||||
kotlinCompileTask.computedCompilerClasspath
|
||||
}
|
||||
|
||||
@get:Internal
|
||||
internal lateinit var kaptClasspathConfigurations: List<Configuration>
|
||||
@@ -82,8 +85,9 @@ abstract class KaptTask : ConventionTask(), TaskWithLocalState {
|
||||
|
||||
// @Internal because _abiClasspath and _nonAbiClasspath are used for actual checks
|
||||
@get:Internal
|
||||
val classpath: FileCollection
|
||||
get() = kotlinCompileTask.classpath
|
||||
val classpath: FileCollection by project.provider {
|
||||
kotlinCompileTask.classpath
|
||||
}
|
||||
|
||||
@Suppress("unused", "DeprecatedCallableAddReplaceWith")
|
||||
@Deprecated(
|
||||
@@ -92,8 +96,9 @@ abstract class KaptTask : ConventionTask(), TaskWithLocalState {
|
||||
)
|
||||
@get:CompileClasspath
|
||||
@get:InputFiles
|
||||
internal val internalAbiClasspath: FileCollection
|
||||
get() = if (includeCompileClasspath) project.files() else kotlinCompileTask.classpath
|
||||
internal val internalAbiClasspath: FileCollection by project.provider {
|
||||
if (includeCompileClasspath) project.files() else kotlinCompileTask.classpath
|
||||
}
|
||||
|
||||
|
||||
@Suppress("unused", "DeprecatedCallableAddReplaceWith")
|
||||
@@ -103,8 +108,9 @@ abstract class KaptTask : ConventionTask(), TaskWithLocalState {
|
||||
)
|
||||
@get:Classpath
|
||||
@get:InputFiles
|
||||
internal val internalNonAbiClasspath: FileCollection
|
||||
get() = if (includeCompileClasspath) kotlinCompileTask.classpath else project.files()
|
||||
internal val internalNonAbiClasspath: FileCollection by project.provider {
|
||||
if (includeCompileClasspath) kotlinCompileTask.classpath else project.files()
|
||||
}
|
||||
|
||||
@get:Internal
|
||||
var useBuildCache: Boolean = false
|
||||
@@ -120,10 +126,14 @@ abstract class KaptTask : ConventionTask(), TaskWithLocalState {
|
||||
return result
|
||||
}
|
||||
|
||||
// store the files before filtering, so that Gradle doesn't serialize the filtered collection for instant execution state and reuse it
|
||||
private val unfilteredJavaSourceRoots by project.provider {
|
||||
(kotlinCompileTask.sourceRootsContainer.sourceRoots + stubsDir)
|
||||
}
|
||||
|
||||
@get:Internal
|
||||
protected val javaSourceRoots: Set<File>
|
||||
get() = (kotlinCompileTask.sourceRootsContainer.sourceRoots + stubsDir)
|
||||
.filterTo(HashSet(), ::isRootAllowed)
|
||||
get() = unfilteredJavaSourceRoots.filterTo(HashSet(), ::isRootAllowed)
|
||||
|
||||
private fun isRootAllowed(file: File): Boolean =
|
||||
file.exists() &&
|
||||
@@ -163,8 +173,10 @@ abstract class KaptTask : ConventionTask(), TaskWithLocalState {
|
||||
}
|
||||
|
||||
// TODO(gavra): Here we assume that kotlinc and javac output is available for incremental runs. We should insert some checks.
|
||||
@Internal
|
||||
protected fun getCompiledSources() = listOfNotNull(kotlinCompileTask.destinationDir, kotlinCompileTask.javaOutputDir)
|
||||
@get:Internal
|
||||
internal val compiledSources by project.provider {
|
||||
listOfNotNull(kotlinCompileTask.destinationDir, kotlinCompileTask.javaOutputDir)
|
||||
}
|
||||
|
||||
protected fun getIncrementalChanges(inputs: IncrementalTaskInputs): KaptIncrementalChanges {
|
||||
return if (isIncremental) {
|
||||
|
||||
+16
-4
@@ -23,6 +23,8 @@ import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger
|
||||
import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
|
||||
import org.jetbrains.kotlin.gradle.plugin.PLUGIN_CLASSPATH_CONFIGURATION_NAME
|
||||
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
|
||||
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||
import org.jetbrains.kotlin.gradle.utils.optionalProvider
|
||||
import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray
|
||||
import java.io.File
|
||||
|
||||
@@ -43,8 +45,15 @@ open class KaptWithKotlincTask : KaptTask(), CompilerArgumentAwareWithInput<K2JV
|
||||
|
||||
override fun createCompilerArgs(): K2JVMCompilerArguments = K2JVMCompilerArguments()
|
||||
|
||||
private val compileKotlinArgumentsContributor by project.provider {
|
||||
kotlinCompileTask.compilerArgumentsContributor
|
||||
}
|
||||
|
||||
override fun setupCompilerArgs(args: K2JVMCompilerArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) {
|
||||
kotlinCompileTask.setupCompilerArgs(args, ignoreClasspathResolutionErrors = ignoreClasspathResolutionErrors)
|
||||
compileKotlinArgumentsContributor.contributeArguments(args, compilerArgumentsConfigurationFlags(
|
||||
defaultsOnly,
|
||||
ignoreClasspathResolutionErrors
|
||||
))
|
||||
|
||||
args.pluginClasspaths = pluginClasspath.toSortedPathsArray()
|
||||
|
||||
@@ -52,7 +61,7 @@ open class KaptWithKotlincTask : KaptTask(), CompilerArgumentAwareWithInput<K2JV
|
||||
withApClasspath = kaptClasspath,
|
||||
changedFiles = changedFiles,
|
||||
classpathChanges = classpathChanges,
|
||||
compiledSourcesDir = getCompiledSources(),
|
||||
compiledSourcesDir = compiledSources,
|
||||
processIncrementally = processIncrementally
|
||||
)
|
||||
|
||||
@@ -69,6 +78,9 @@ open class KaptWithKotlincTask : KaptTask(), CompilerArgumentAwareWithInput<K2JV
|
||||
private var classpathChanges: List<String> = emptyList()
|
||||
private var processIncrementally = false
|
||||
|
||||
private val javaPackagePrefix by project.optionalProvider { kotlinCompileTask.javaPackagePrefix }
|
||||
private val buildReportMode by project.optionalProvider { kotlinCompileTask.buildReportMode }
|
||||
|
||||
@TaskAction
|
||||
fun compile(inputs: IncrementalTaskInputs) {
|
||||
logger.debug("Running kapt annotation processing using the Kotlin compiler")
|
||||
@@ -87,7 +99,7 @@ open class KaptWithKotlincTask : KaptTask(), CompilerArgumentAwareWithInput<K2JV
|
||||
val outputItemCollector = OutputItemsCollectorImpl()
|
||||
val environment = GradleCompilerEnvironment(
|
||||
compilerClasspath, messageCollector, outputItemCollector,
|
||||
buildReportMode = kotlinCompileTask.buildReportMode,
|
||||
buildReportMode = buildReportMode,
|
||||
outputFiles = allOutputFiles()
|
||||
)
|
||||
if (environment.toolsJar == null && !isAtLeastJava9) {
|
||||
@@ -99,7 +111,7 @@ open class KaptWithKotlincTask : KaptTask(), CompilerArgumentAwareWithInput<K2JV
|
||||
sourcesToCompile = emptyList(),
|
||||
commonSources = emptyList(),
|
||||
javaSourceRoots = javaSourceRoots,
|
||||
javaPackagePrefix = kotlinCompileTask.javaPackagePrefix,
|
||||
javaPackagePrefix = javaPackagePrefix,
|
||||
args = args,
|
||||
environment = environment
|
||||
)
|
||||
|
||||
+5
-3
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
||||
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
|
||||
import org.jetbrains.kotlin.gradle.tasks.findKotlinStdlibClasspath
|
||||
import org.jetbrains.kotlin.gradle.tasks.findToolsJar
|
||||
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||
import org.jetbrains.kotlin.utils.PathUtil
|
||||
import java.io.File
|
||||
import java.io.Serializable
|
||||
@@ -28,8 +29,9 @@ open class KaptWithoutKotlincTask @Inject constructor(private val workerExecutor
|
||||
@get:InputFiles
|
||||
@get:Classpath
|
||||
@Suppress("unused")
|
||||
val kaptJars: Collection<File>
|
||||
get() = project.configurations.getByName(KAPT_WORKER_DEPENDENCIES_CONFIGURATION_NAME).resolve()
|
||||
val kaptJars: Collection<File> by project.provider {
|
||||
project.configurations.getByName(KAPT_WORKER_DEPENDENCIES_CONFIGURATION_NAME).resolve()
|
||||
}
|
||||
|
||||
@get:Input
|
||||
var isVerbose: Boolean = false
|
||||
@@ -85,7 +87,7 @@ open class KaptWithoutKotlincTask @Inject constructor(private val workerExecutor
|
||||
javaSourceRoots.toList(),
|
||||
|
||||
changedFiles,
|
||||
getCompiledSources(),
|
||||
compiledSources,
|
||||
incAptCache,
|
||||
classpathChanges.toList(),
|
||||
|
||||
|
||||
+24
-47
@@ -10,7 +10,6 @@ import org.gradle.api.Task
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.Optional
|
||||
import org.gradle.api.tasks.compile.AbstractCompile
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.gradle.api.tasks.incremental.IncrementalTaskInputs
|
||||
@@ -24,7 +23,7 @@ import org.jetbrains.kotlin.compilerRunner.*
|
||||
import org.jetbrains.kotlin.daemon.common.MultiModuleICSettings
|
||||
import org.jetbrains.kotlin.gradle.dsl.*
|
||||
import org.jetbrains.kotlin.gradle.incremental.ChangedFiles
|
||||
import org.jetbrains.kotlin.gradle.internal.CompilerArgumentAwareWithInput
|
||||
import org.jetbrains.kotlin.gradle.internal.*
|
||||
import org.jetbrains.kotlin.gradle.internal.prepareCompilerArguments
|
||||
import org.jetbrains.kotlin.gradle.internal.tasks.TaskWithLocalState
|
||||
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
|
||||
@@ -38,8 +37,6 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.ownModuleName
|
||||
import org.jetbrains.kotlin.gradle.report.BuildReportMode
|
||||
import org.jetbrains.kotlin.gradle.utils.*
|
||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||
import org.jetbrains.kotlin.incremental.classpathAsList
|
||||
import org.jetbrains.kotlin.incremental.destinationAsFile
|
||||
import org.jetbrains.kotlin.utils.LibraryUtils
|
||||
import java.io.File
|
||||
import javax.inject.Inject
|
||||
@@ -174,12 +171,12 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
||||
// 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 + additionalClasspath
|
||||
classpath + project.files(additionalClasspath)
|
||||
}
|
||||
|
||||
@get:Internal // classpath already participates in the checks
|
||||
internal val compileClasspath: Iterable<File>
|
||||
get() = compileClasspathImpl.filter { it.exists() }
|
||||
get() = compileClasspathImpl
|
||||
|
||||
@field:Transient
|
||||
private val sourceFilesExtensionsSources: MutableList<Iterable<String>> = mutableListOf()
|
||||
@@ -218,7 +215,8 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
||||
internal val coroutinesStr: String
|
||||
get() = coroutines.name
|
||||
|
||||
private val coroutines: Coroutines by project.provider {
|
||||
@get:Internal
|
||||
internal val coroutines: Coroutines by project.provider {
|
||||
kotlinExt.experimental.coroutines
|
||||
?: coroutinesFromGradleProperties
|
||||
?: Coroutines.DEFAULT
|
||||
@@ -317,27 +315,16 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
||||
*/
|
||||
internal abstract fun callCompilerAsync(args: T, sourceRoots: SourceRoots, changedFiles: ChangedFiles)
|
||||
|
||||
private val isMultiplatform: Boolean by project.provider {
|
||||
@get:Internal
|
||||
internal val isMultiplatform: Boolean by project.provider {
|
||||
project.plugins.any { it is KotlinPlatformPluginBase || it is KotlinMultiplatformPluginWrapper }
|
||||
}
|
||||
|
||||
override fun setupCompilerArgs(args: T, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) {
|
||||
args.coroutinesState = when (coroutines) {
|
||||
Coroutines.ENABLE -> CommonCompilerArguments.ENABLE
|
||||
Coroutines.WARN -> CommonCompilerArguments.WARN
|
||||
Coroutines.ERROR -> CommonCompilerArguments.ERROR
|
||||
Coroutines.DEFAULT -> CommonCompilerArguments.DEFAULT
|
||||
}
|
||||
|
||||
logger.kotlinDebug { "args.coroutinesState=${args.coroutinesState}" }
|
||||
|
||||
if (logger.isDebugEnabled) {
|
||||
args.verbose = true
|
||||
}
|
||||
|
||||
args.multiPlatform = isMultiplatform
|
||||
|
||||
setupPlugins(args)
|
||||
AbstractKotlinCompileArgumentsContributor(thisTaskProvider).contributeArguments(
|
||||
args,
|
||||
compilerArgumentsConfigurationFlags(defaultsOnly, ignoreClasspathResolutionErrors)
|
||||
)
|
||||
}
|
||||
|
||||
internal fun setupPlugins(compilerArgs: T) {
|
||||
@@ -351,6 +338,9 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
||||
}
|
||||
}
|
||||
|
||||
internal inline val <reified T : Task> T.thisTaskProvider: TaskProvider<out T>
|
||||
get() = checkNotNull(project.locateTask<T>(name))
|
||||
|
||||
@CacheableTask
|
||||
open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), KotlinJvmCompile {
|
||||
@get:Internal
|
||||
@@ -390,28 +380,15 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
||||
K2JVMCompilerArguments()
|
||||
|
||||
override fun setupCompilerArgs(args: K2JVMCompilerArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) {
|
||||
args.apply { fillDefaultValues() }
|
||||
super.setupCompilerArgs(args, defaultsOnly = defaultsOnly, ignoreClasspathResolutionErrors = ignoreClasspathResolutionErrors)
|
||||
compilerArgumentsContributor.contributeArguments(args, compilerArgumentsConfigurationFlags(
|
||||
defaultsOnly,
|
||||
ignoreClasspathResolutionErrors
|
||||
))
|
||||
}
|
||||
|
||||
args.moduleName = moduleName
|
||||
logger.kotlinDebug { "args.moduleName = ${args.moduleName}" }
|
||||
|
||||
args.friendPaths = friendPaths
|
||||
logger.kotlinDebug { "args.friendPaths = ${args.friendPaths?.joinToString() ?: "[]"}" }
|
||||
|
||||
if (defaultsOnly) return
|
||||
|
||||
args.allowNoSourceFiles = true
|
||||
args.classpathAsList = try {
|
||||
compileClasspath.toList()
|
||||
} catch (e: Exception) {
|
||||
if (ignoreClasspathResolutionErrors) emptyList() else throw(e)
|
||||
}
|
||||
args.destinationAsFile = destinationDir
|
||||
parentKotlinOptionsImpl?.updateArguments(args)
|
||||
kotlinOptionsImpl.updateArguments(args)
|
||||
|
||||
logger.kotlinDebug { "$name destinationDir = $destinationDir" }
|
||||
@get:Internal
|
||||
internal val compilerArgumentsContributor: CompilerArgumentsContributor<K2JVMCompilerArguments> by project.provider {
|
||||
KotlinJvmCompilerArgumentsContributor(thisTaskProvider)
|
||||
}
|
||||
|
||||
@Internal
|
||||
@@ -488,13 +465,13 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
||||
}
|
||||
|
||||
// override setSource to track source directory sets and files (for generated android folders)
|
||||
override fun setSource(sources: Any?) {
|
||||
override fun setSource(sources: Any) {
|
||||
sourceRootsContainer.set(sources)
|
||||
super.setSource(sources)
|
||||
}
|
||||
|
||||
// override source to track source directory sets and files (for generated android folders)
|
||||
override fun source(vararg sources: Any?): SourceTask? {
|
||||
override fun source(vararg sources: Any): SourceTask {
|
||||
sourceRootsContainer.add(*sources)
|
||||
return super.source(*sources)
|
||||
}
|
||||
|
||||
+12
-1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.utils
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.Provider
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
internal operator fun <T> Provider<T>.getValue(thisRef: Any?, property: KProperty<*>) = get()
|
||||
@@ -22,4 +23,14 @@ internal fun <T : Any> Project.newProperty(initialize: (() -> T)? = null): Prope
|
||||
(project.objects.property(Any::class.java) as Property<T>).apply {
|
||||
if (initialize != null)
|
||||
set(provider(initialize))
|
||||
}
|
||||
}
|
||||
|
||||
private class OptionalProviderDelegate<T>(private val provider: Provider<T?>) : ReadOnlyProperty<Any?, T?> {
|
||||
override fun getValue(thisRef: Any?, property: KProperty<*>): T? =
|
||||
if (provider.isPresent)
|
||||
provider.get()
|
||||
else null
|
||||
}
|
||||
|
||||
internal fun <T> Project.optionalProvider(initialize: () -> T?): ReadOnlyProperty<Any?, T?> =
|
||||
OptionalProviderDelegate(provider(initialize))
|
||||
Reference in New Issue
Block a user