diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildCacheIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildCacheIT.kt index c39157cfdc0..b6ff82643bf 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildCacheIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/BuildCacheIT.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.gradle.testbase.* import org.junit.jupiter.api.DisplayName import kotlin.io.path.ExperimentalPathApi import kotlin.io.path.readText +import kotlin.io.path.relativeTo import kotlin.io.path.writeText @ExperimentalPathApi @@ -147,4 +148,29 @@ class BuildCacheIT : KGPBaseTest() { } } } + + //doesn't work for build history files approach + @DisplayName("Restore from build cache should not break incremental compilation") + @GradleTest + fun testIncrementalCompilationAfterCacheHit(gradleVersion: GradleVersion) { + val withSnapshotProperty = "-Dkotlin.incremental.classpath.snapshot.enabled=true" + project("incrementalMultiproject", gradleVersion) { + enableLocalBuildCache(localBuildCacheDir) + build("assemble", withSnapshotProperty) + build("clean", "assemble", withSnapshotProperty) { + assertTasksFromCache(":lib:compileKotlin") + assertTasksFromCache(":app:compileKotlin") + } + val bKtSourceFile = projectPath.resolve("lib/src/main/kotlin/bar/B.kt") + + bKtSourceFile.modify { it.replace("fun b() {}", "fun b() {}\nfun b2() {}") } + + build("assemble", withSnapshotProperty, buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)) { + assertOutputDoesNotContain("[KOTLIN] [IC] Non-incremental compilation will be performed") + assertCompiledKotlinSources(setOf(bKtSourceFile).map { it.relativeTo(projectPath)}, output) + } + + } + } + } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt index fe7ee4c75a1..3c42fcfad8d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/GradleKotlinCompilerRunner.kt @@ -309,15 +309,6 @@ internal open class GradleCompilerRunner( jarToModule[it] = module } } -// for (target in task.targets) { -// if (target is KotlinWithJavaTarget<*>) { -// val jar = project.tasks.getByName(target.artifactsTaskName) as Jar -// jarToClassListFile[jar.archivePathCompatible.canonicalFile] = target.defaultArtifactClassesListFile.get() -// //configure abiSnapshot mapping for jars -// jarToAbiSnapshot[jar.archivePathCompatible.canonicalFile] = -// target.buildDir.get().file(task.abiSnapshotRelativePath).asFile -// } -// } } else if (task is InspectClassesForMultiModuleIC) { jarToClassListFile[File(task.archivePath.get())] = task.classesListFile } 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 511d9b054ff..eecad7c7e42 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 @@ -199,8 +199,10 @@ abstract class AbstractKotlinCompile : AbstractKotl project.plugins.any { it is KotlinPlatformPluginBase || it is KotlinMultiplatformPluginWrapper || it is KotlinPm20PluginWrapper } } ).disallowChanges() - task.taskBuildDirectory.value(getKotlinBuildDir(task)).disallowChanges() - task.localStateDirectories.from(task.taskBuildDirectory).disallowChanges() + task.taskBuildCacheableOutputDirectory.value(getKotlinBuildDir(task).map { it.dir("cacheable") }).disallowChanges() + task.taskBuildLocalStateDirectory.value(getKotlinBuildDir(task).map { it.dir("localstate") }).disallowChanges() + + task.localStateDirectories.from(task.taskBuildLocalStateDirectory, task.taskBuildCacheableOutputDirectory).disallowChanges() PropertiesProvider(task.project).mapKotlinDaemonProperties(task) } @@ -224,13 +226,17 @@ abstract class AbstractKotlinCompile : AbstractKotl @get:Internal protected val objects: ObjectFactory = project.objects + // avoid creating directory in getter: this can lead to failure in parallel build + @get:OutputDirectory + internal val taskBuildCacheableOutputDirectory: DirectoryProperty = objects.directoryProperty() + // avoid creating directory in getter: this can lead to failure in parallel build @get:LocalState - internal val taskBuildDirectory: DirectoryProperty = objects.directoryProperty() + internal val taskBuildLocalStateDirectory: DirectoryProperty = objects.directoryProperty() @get:Internal internal val buildHistoryFile - get() = taskBuildDirectory.file("build-history.bin") + get() = taskBuildLocalStateDirectory.file("build-history.bin") // indicates that task should compile kotlin incrementally if possible // it's not possible when IncrementalTaskInputs#isIncremental returns false (i.e first build) @@ -300,7 +306,7 @@ abstract class AbstractKotlinCompile : AbstractKotl @get:Internal val abiSnapshotFile - get() = taskBuildDirectory.file(IncrementalCompilerRunner.ABI_SNAPSHOT_FILE_NAME) + get() = taskBuildCacheableOutputDirectory.file(IncrementalCompilerRunner.ABI_SNAPSHOT_FILE_NAME) @get:Input val abiSnapshotRelativePath: Property = objects.property(String::class.java).value( @@ -419,7 +425,8 @@ abstract class AbstractKotlinCompile : AbstractKotl sourceRoots.log(this.name, logger) val args = prepareCompilerArguments() - taskBuildDirectory.get().asFile.mkdirs() + taskBuildCacheableOutputDirectory.get().asFile.mkdirs() + taskBuildLocalStateDirectory.get().asFile.mkdirs() callCompilerAsync( args, sourceRoots, @@ -758,7 +765,7 @@ abstract class KotlinCompile @Inject constructor( IncrementalCompilationEnvironment( changedFiles = getChangedFiles(inputChanges, incrementalProps), classpathChanges = getClasspathChanges(inputChanges), - workingDir = taskBuildDirectory.get().asFile, + workingDir = taskBuildCacheableOutputDirectory.get().asFile, usePreciseJavaTracking = usePreciseJavaTracking, disableMultiModuleIC = disableMultiModuleIC, multiModuleICSettings = multiModuleICSettings @@ -1129,7 +1136,7 @@ abstract class Kotlin2JsCompile @Inject constructor( IncrementalCompilationEnvironment( getChangedFiles(inputChanges, incrementalProps), ClasspathChanges.NotAvailableForJSCompiler, - taskBuildDirectory.get().asFile, + taskBuildCacheableOutputDirectory.get().asFile, multiModuleICSettings = multiModuleICSettings ) } else null