diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptGenerateStubsTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptGenerateStubsTask.kt index 5d5e7212eaf..713b4d7fff4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptGenerateStubsTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptGenerateStubsTask.kt @@ -38,7 +38,9 @@ import javax.inject.Inject open class KaptGenerateStubsTask @Inject constructor( objectFactory: ObjectFactory ) : KotlinCompile() { - override val sourceRootsContainer = FilteringSourceRootsContainer(emptyList(), { isSourceRootAllowed(it) }) + + @field:Transient + override val sourceRootsContainer = FilteringSourceRootsContainer(objectFactory, { isSourceRootAllowed(it) }) override val kotlinOptions: KotlinJvmOptions = KotlinJvmOptionsImpl() @@ -109,10 +111,11 @@ open class KaptGenerateStubsTask @Inject constructor( } private val sourceRoots by project.provider { - kotlinCompileTask.getSourceRoots().let { - val javaSourceRoots = it.javaSourceRoots.filterTo(HashSet()) { isSourceRootAllowed(it) } - val kotlinSourceFiles = it.kotlinSourceFiles.filterTo(ArrayList()) { isSourceRootAllowed(it) } - SourceRoots.ForJvm(kotlinSourceFiles, javaSourceRoots) + kotlinCompileTask.getSourceRoots().let { compileTaskSourceRoots -> + SourceRoots.ForJvm( + compileTaskSourceRoots.kotlinSourceFiles.filterTo(mutableListOf()) { isSourceRootAllowed(it) }, + javaSourceRootsProvider = { compileTaskSourceRoots.javaSourceRoots.filterTo(mutableSetOf()) { isSourceRootAllowed(it) } } + ) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptTask.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptTask.kt index 8506a386f52..b6a384990d3 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptTask.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/internal/kapt/KaptTask.kt @@ -132,12 +132,16 @@ abstract class KaptTask @Inject constructor( @get:Internal var useBuildCache: Boolean = false + private val sourceRootsFromKotlinTask by project.provider { + kotlinCompileTask.sourceRootsContainer.sourceRoots + } + @get:InputFiles @get:PathSensitive(PathSensitivity.RELATIVE) val source: FileCollection = objectFactory .fileCollection() .from( - { kotlinCompileTask.sourceRootsContainer.sourceRoots }, + { sourceRootsFromKotlinTask }, stubsDir ) .asFileTree diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index 7d1ae3ea2c0..dcce793e5fa 100755 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -15,6 +15,7 @@ import org.gradle.api.artifacts.maven.MavenResolver import org.gradle.api.attributes.Usage import org.gradle.api.file.ConfigurableFileTree import org.gradle.api.file.FileCollection +import org.gradle.api.file.SourceDirectorySet import org.gradle.api.logging.Logging import org.gradle.api.plugins.InvalidPluginException import org.gradle.api.plugins.JavaPlugin @@ -146,11 +147,11 @@ internal abstract class KotlinSourceSetProcessor>( java.allSource.srcDirs(kotlinSrcDirsToAdd) } - private fun filterOutJavaSrcDirsIfPossible(sourceDirectories: FileCollection): FileCollection { + private fun filterOutJavaSrcDirsIfPossible(sourceDirectories: SourceDirectorySet): FileCollection { val java = javaSourceSet ?: return sourceDirectories // Build a lazily-resolved file collection that filters out Java sources from sources of this sourceDirectorySet - return sourceDirectories.minus(java.java.sourceDirectories) + return sourceDirectories.sourceDirectories.minus(java.java.sourceDirectories) } private fun createAdditionalClassesTaskForIdeRunner() { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt index 79d71020174..e52aa0668cc 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/KotlinMultiplatformPlugin.kt @@ -43,6 +43,7 @@ import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.KonanTarget.* import org.jetbrains.kotlin.konan.target.presetName import org.jetbrains.kotlin.statistics.metrics.StringMetrics +import java.io.File class KotlinMultiplatformPlugin : Plugin { @@ -294,7 +295,7 @@ internal fun sourcesJarTask(compilation: KotlinCompilation<*>, componentName: St internal fun sourcesJarTask( project: Project, - sourceSets: Lazy>, + sourceSets: Lazy>>, componentName: String?, artifactNameAppendix: String ): TaskProvider = sourcesJarTaskNamed(lowerCamelCaseName(componentName, "sourcesJar"), project, sourceSets, artifactNameAppendix) @@ -302,7 +303,7 @@ internal fun sourcesJarTask( internal fun sourcesJarTaskNamed( taskName: String, project: Project, - sourceSets: Lazy>, + sourceSets: Lazy>>, artifactNameAppendix: String ): TaskProvider { project.locateTask(taskName)?.let { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt index 904cb12011d..bc3ed119411 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt @@ -307,7 +307,7 @@ internal fun addCommonSourcesToKotlinCompileTask( project: Project, taskName: String, sourceFileExtensions: Iterable, - sources: () -> Iterable + sources: () -> Any ) = addSourcesToKotlinCompileTask(project, taskName, sourceFileExtensions, lazyOf(true), sources) // FIXME this function dangerously ignores an incorrect type of the task (e.g. if the actual task is a K/N one); consider reporting a failure @@ -316,13 +316,18 @@ internal fun addSourcesToKotlinCompileTask( taskName: String, sourceFileExtensions: Iterable, addAsCommonSources: Lazy = lazyOf(false), - sources: () -> Iterable + /** Evaluated as project.files(...) */ + sources: () -> Any ) { fun AbstractKotlinCompile<*>.configureAction() { - source(project.files(Callable { sources() })) + // In this call, the super-implementation of `source` adds the directories files to the roots of the union file tree, + // so it's OK to pass just the source roots. + source(Callable(sources)) sourceFilesExtensions(sourceFileExtensions) - commonSourceSet += project.files(Callable { - if (addAsCommonSources.value) sources() else emptyList() + + // The `commonSourceSet` is passed to the compiler as-is, converted with toList + commonSourceSet += project.files(Callable { + if (addAsCommonSources.value) sources else emptyList() }) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/FragmentSourcesProvider.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/FragmentSourcesProvider.kt index aefe9a5915a..a492734858f 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/FragmentSourcesProvider.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/FragmentSourcesProvider.kt @@ -7,37 +7,47 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.pm20 import org.gradle.api.Project import org.gradle.api.file.FileCollection +import org.gradle.api.provider.Provider import org.gradle.language.base.plugins.LifecycleBasePlugin import org.jetbrains.kotlin.project.model.utils.variantsContainingFragment +import java.io.File +typealias SourceRoots = Iterable +typealias SourceRootsProvider = Provider +typealias MultipleSourceRootsProvider = Provider> +typealias SourceRootsProvidersByFragment = Map + +/** Note: the API is [Provider]-based rather than FileCollection-based because FileCollection API erases the internal structure of the + * file sets, and this internal structure is currently needed for correctly inferring Java source roots from the sources added to the + * JVM compilations (it is important to pass sources in SourceDirectorySets) */ open class FragmentSourcesProvider { protected open fun getSourcesFromFragmentsAsMap( fragments: Iterable - ): Map = - fragments.associateWith { it.project.files(it.project.provider { it.kotlinSourceRoots }) } + ): SourceRootsProvidersByFragment = + fragments.associateWith { it.project.provider { it.kotlinSourceRoots } } - open fun getFragmentOwnSources(fragment: KotlinGradleFragment): FileCollection = + open fun getFragmentOwnSources(fragment: KotlinGradleFragment): SourceRootsProvider = getSourcesFromFragmentsAsMap(listOf(fragment)).values.single() - open fun getAllFragmentSourcesAsMap(module: KotlinGradleModule): Map = + open fun getAllFragmentSourcesAsMap(module: KotlinGradleModule): SourceRootsProvidersByFragment = getSourcesFromFragmentsAsMap(module.fragments) - open fun getSourcesFromRefinesClosureAsMap(fragment: KotlinGradleFragment): Map = + open fun getSourcesFromRefinesClosureAsMap(fragment: KotlinGradleFragment): SourceRootsProvidersByFragment = getSourcesFromFragmentsAsMap(fragment.refinesClosure) - open fun getSourcesFromRefinesClosure(fragment: KotlinGradleFragment): FileCollection = - fragment.project.files(fragment.project.provider { getSourcesFromRefinesClosureAsMap(fragment).values }) + open fun getSourcesFromRefinesClosure(fragment: KotlinGradleFragment): MultipleSourceRootsProvider = + fragment.project.provider { getSourcesFromRefinesClosureAsMap(fragment).values } - open fun getCommonSourcesFromRefinesClosure(fragment: KotlinGradleFragment): FileCollection { + open fun getCommonSourcesFromRefinesClosure(fragment: KotlinGradleFragment): MultipleSourceRootsProvider { val containingModule = fragment.containingModule val project = containingModule.project getSourcesFromRefinesClosureAsMap(fragment) - return project.files(project.provider { + return project.provider { fragment.refinesClosure.filter { // Every fragment refined by some other fragment should be considered common, even if it is included in just one variant containingModule.variantsContainingFragment(it).toSet() != setOf(it) - }.map { it.kotlinSourceRoots } - }) + }.map { project.provider { it.kotlinSourceRoots } } + } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinCompilationTaskConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinCompilationTaskConfigurator.kt index b49d6678bee..e2d0addb119 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinCompilationTaskConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/KotlinCompilationTaskConfigurator.kt @@ -22,10 +22,10 @@ open class KotlinCompilationTaskConfigurator( ) { open val fragmentSourcesProvider: FragmentSourcesProvider = FragmentSourcesProvider() - open fun getSourcesForFragmentCompilation(fragment: KotlinGradleFragment) = + open fun getSourcesForFragmentCompilation(fragment: KotlinGradleFragment): MultipleSourceRootsProvider = fragmentSourcesProvider.getSourcesFromRefinesClosure(fragment) - open fun getCommonSourcesForFragmentCompilation(fragment: KotlinGradleFragment) = + open fun getCommonSourcesForFragmentCompilation(fragment: KotlinGradleFragment): MultipleSourceRootsProvider = fragmentSourcesProvider.getCommonSourcesFromRefinesClosure(fragment) fun createKotlinJvmCompilationTask( diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/abstractVariantFactories.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/abstractVariantFactories.kt index 68ec8fcaadf..618d8091da5 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/abstractVariantFactories.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/abstractVariantFactories.kt @@ -51,7 +51,7 @@ abstract class AbstractKotlinGradleVariantFactory( sourcesJarTaskNamed( fragment.sourceArchiveTaskName, project, - lazy { FragmentSourcesProvider().getSourcesFromRefinesClosureAsMap(fragment).mapKeys { it.key.fragmentName } }, + lazy { FragmentSourcesProvider().getSourcesFromRefinesClosureAsMap(fragment).entries.associate { it.key.fragmentName to it.value.get() } }, fragment.name ) } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/fragmentsMetadataCompilation.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/fragmentsMetadataCompilation.kt index edcb09278a3..a01f4d9d140 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/fragmentsMetadataCompilation.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/pm20/fragmentsMetadataCompilation.kt @@ -9,6 +9,7 @@ import org.gradle.api.DefaultTask import org.gradle.api.Project import org.gradle.api.attributes.Usage import org.gradle.api.file.FileCollection +import org.gradle.api.provider.Provider import org.gradle.api.tasks.TaskProvider import org.gradle.jvm.tasks.Jar import org.jetbrains.kotlin.gradle.dsl.pm20Extension @@ -27,6 +28,7 @@ import org.jetbrains.kotlin.gradle.utils.dashSeparatedName import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName import org.jetbrains.kotlin.library.KLIB_FILE_EXTENSION import org.jetbrains.kotlin.project.model.KotlinModuleFragment +import java.io.File import java.util.concurrent.Callable internal fun configureMetadataResolutionAndBuild(module: KotlinGradleModule) { @@ -65,7 +67,7 @@ internal fun configureMetadataExposure(module: KotlinGradleModule) { val sourcesArtifact = sourcesJarTaskNamed( module.disambiguateName("allSourcesJar"), project, - lazy { FragmentSourcesProvider().getAllFragmentSourcesAsMap(module).mapKeys { it.key.fragmentName } }, + lazy { FragmentSourcesProvider().getAllFragmentSourcesAsMap(module).entries.associate { it.key.fragmentName to it.value.get() } }, sourcesArtifactAppendix ) DocumentationVariantConfigurator().createSourcesElementsConfiguration( @@ -222,12 +224,12 @@ private class MetadataCompilationTasksConfigurator(project: Project) : KotlinCom addCommonSourcesToKotlinCompileTask(project, compilationData.compileKotlinTaskName, emptyList()) { commonSources } } - override fun getSourcesForFragmentCompilation(fragment: KotlinGradleFragment): FileCollection { - return fragmentSourcesProvider.getFragmentOwnSources(fragment) + override fun getSourcesForFragmentCompilation(fragment: KotlinGradleFragment): MultipleSourceRootsProvider { + return project.provider { listOf(fragmentSourcesProvider.getFragmentOwnSources(fragment)) } } - override fun getCommonSourcesForFragmentCompilation(fragment: KotlinGradleFragment): FileCollection { - return fragmentSourcesProvider.getFragmentOwnSources(fragment) + override fun getCommonSourcesForFragmentCompilation(fragment: KotlinGradleFragment): MultipleSourceRootsProvider { + return project.provider { listOf(fragmentSourcesProvider.getFragmentOwnSources(fragment)) } } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SourceRoots.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SourceRoots.kt index b7fe8724d01..c22970c3463 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SourceRoots.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/SourceRoots.kt @@ -1,14 +1,18 @@ package org.jetbrains.kotlin.gradle.tasks +import org.gradle.api.file.FileCollection import org.gradle.api.file.FileTree import org.gradle.api.file.SourceDirectorySet import org.gradle.api.logging.Logger +import org.gradle.api.model.ObjectFactory +import org.gradle.api.provider.Provider import org.jetbrains.kotlin.gradle.logging.kotlinDebug import org.jetbrains.kotlin.gradle.utils.isJavaFile import org.jetbrains.kotlin.gradle.utils.isKotlinFile import org.jetbrains.kotlin.gradle.utils.isParentOf import java.io.File import java.util.* +import java.util.concurrent.Callable internal sealed class SourceRoots(val kotlinSourceFiles: List) { private companion object { @@ -20,14 +24,21 @@ internal sealed class SourceRoots(val kotlinSourceFiles: List) { logger.kotlinDebug { "$taskName source roots: ${dumpPaths(kotlinSourceFiles)}" } } - class ForJvm(kotlinSourceFiles: List, val javaSourceRoots: Set) : SourceRoots(kotlinSourceFiles) { + class ForJvm constructor( + kotlinSourceFiles: List, + private val javaSourceRootsProvider: () -> Set + ) : SourceRoots(kotlinSourceFiles) { + val javaSourceRoots: Set + get() = javaSourceRootsProvider() + + constructor(kotlinSourceFiles: List, allSourceRoots: FileCollection, taskSource: FileCollection) : this(kotlinSourceFiles, { + findRootsForSources(allSourceRoots, taskSource.filter(File::isJavaFile)).toSet() + }) + companion object { fun create(taskSource: FileTree, sourceRoots: FilteringSourceRootsContainer, sourceFilesExtensions: List): ForJvm { val kotlinSourceFiles = (taskSource as Iterable).filter { it.isKotlinFile(sourceFilesExtensions) } - val javaSourceRoots = findRootsForSources( - sourceRoots.sourceRoots, taskSource.filter(File::isJavaFile) - ) - return ForJvm(kotlinSourceFiles, javaSourceRoots) + return ForJvm(kotlinSourceFiles, sourceRoots.sourceRoots, taskSource) } private fun findRootsForSources(allSourceRoots: Iterable, sources: Iterable): Set { @@ -60,33 +71,43 @@ internal sealed class SourceRoots(val kotlinSourceFiles: List) { } } -internal class FilteringSourceRootsContainer(roots: List = emptyList(), val filter: (File) -> Boolean = { true }) { - private val mutableSourceRoots = roots.filterTo(mutableListOf(), filter) +internal class FilteringSourceRootsContainer( + private val objectFactory: ObjectFactory, + val filter: (File) -> Boolean = { true } +) { + private val sourceContainers: MutableList = mutableListOf() - val sourceRoots: List - get() = mutableSourceRoots + private fun getFilteredSourceRootsFrom(any: Any) = objectFactory.fileCollection().from(Callable { + val resultItems = mutableListOf() + fun getRootsFrom(item: Any?) { + when (item) { + is SourceDirectorySet -> resultItems.add(item.sourceDirectories) + is Callable<*> -> getRootsFrom(item.call()) + is Provider<*> -> if (item.isPresent) getRootsFrom(item.get()) + is FileCollection -> resultItems.add(item) + is Iterable<*> -> item.forEach { getRootsFrom(it) } + is Array<*> -> item.forEach { getRootsFrom(it) } + is Any /* not null */ -> resultItems.add(item) + } + } + getRootsFrom(any) + resultItems + }).filter(filter) + + val sourceRoots: FileCollection + get() = getFilteredSourceRootsFrom(sourceContainers) fun clear() { - mutableSourceRoots.clear() + sourceContainers.clear() } - fun set(source: Any?): List { + fun set(source: Any): FileCollection { clear() return add(source) } - fun add(vararg sources: Any?): List { - val filteredDirs = mutableListOf() - for (source in sources) { - when (source) { - is SourceDirectorySet -> filteredDirs += source.srcDirs.filter { filter(it) } - is File -> if (filter(source)) filteredDirs.add(source) - is Collection<*> -> source.forEach { filteredDirs += add(it) } - is Array<*> -> source.forEach { filteredDirs += add(it) } - } - } - - mutableSourceRoots += filteredDirs - return filteredDirs + fun add(vararg sources: Any): FileCollection { + sourceContainers.addAll(sources.toList()) + return getFilteredSourceRootsFrom(sources) } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt index 054c92f8da5..3d96b8af7f6 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/Tasks.kt @@ -471,7 +471,13 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl get() = taskData.compilation.kotlinOptions as KotlinJvmOptions @get:Internal - internal open val sourceRootsContainer = FilteringSourceRootsContainer() + @field:Transient + internal open val sourceRootsContainer = FilteringSourceRootsContainer(project.objects) + + 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 + SourceRoots.ForJvm.create(source, sourceRootsContainer, sourceFilesExtensions) + } /** A package prefix that is used for locating Java sources in a directory structure with non-full-depth packages. * @@ -512,8 +518,7 @@ open class KotlinCompile : AbstractKotlinCompile(), Kotl KotlinJvmCompilerArgumentsContributor(KotlinJvmCompilerArgumentsProvider(this)) } - @Internal - override fun getSourceRoots() = SourceRoots.ForJvm.create(getSource(), sourceRootsContainer, sourceFilesExtensions) + override fun getSourceRoots(): SourceRoots.ForJvm = jvmSourceRoots override fun callCompilerAsync(args: K2JVMCompilerArguments, sourceRoots: SourceRoots, changedFiles: ChangedFiles) { sourceRoots as SourceRoots.ForJvm