[IC] Relocatable IC caches for projects with custom buildDir
IC caches often contain file paths. To make them relocatable, we need
to convert these file paths into relative paths, relative to a base
directory.
- If the file paths are source files, we can use the root project
directory as base.
- If the file paths are class files, we should use the classes
directory as base (before this commit, we used the root project
directory in both cases, that's why we hit KT-58547).
The key changes in this commit include:
- RelocatableFileToPathConverter: converts paths to relative paths
- IncrementalCompilationContext: contains 2 different path converters,
one for source files and one for class files
- SourceToOutputFilesMap: maps source files to class files using the
above path converters
- IncrementalCompilerRunner: creates the path converters based on file
locations
Test: RelocatableFileToPathConverterTest unit test
SourceToOutputFilesMapTest unit test
BuildCacheRelocationIT.testCustomBuildDirectory integration test
^KT-58547 Fixed
This commit is contained in:
+28
-1
@@ -17,13 +17,15 @@
|
||||
package org.jetbrains.kotlin.gradle
|
||||
|
||||
import org.gradle.api.logging.LogLevel
|
||||
import org.gradle.api.logging.configuration.WarningMode
|
||||
import org.gradle.testkit.runner.BuildResult
|
||||
import org.gradle.util.GradleVersion
|
||||
import org.jetbrains.kotlin.gradle.testbase.*
|
||||
import org.junit.jupiter.api.DisplayName
|
||||
import java.io.File
|
||||
import kotlin.io.path.createDirectory
|
||||
import kotlin.io.path.isRegularFile
|
||||
import kotlin.io.path.readText
|
||||
import kotlin.io.path.walk
|
||||
|
||||
@DisplayName("Build cache relocation")
|
||||
class BuildCacheRelocationIT : KGPBaseTest() {
|
||||
@@ -400,4 +402,29 @@ class BuildCacheRelocationIT : KGPBaseTest() {
|
||||
assertTasksFromCache(":app:kaptGenerateStubsKotlin", ":app:kaptKotlin")
|
||||
}
|
||||
}
|
||||
|
||||
@JvmGradlePluginTests
|
||||
@DisplayName("test relocatability for projects using custom build directory") // Regression test for KT-58547
|
||||
@GradleTest
|
||||
fun testCustomBuildDirectory(gradleVersion: GradleVersion) {
|
||||
val (firstProject, secondProject) = prepareTestProjects("buildCacheSimple", gradleVersion)
|
||||
firstProject.buildGradle.append("buildDir = \"../BUILD_DIR_1\"")
|
||||
secondProject.buildGradle.append("buildDir = \"../BUILD_DIR_2\"")
|
||||
|
||||
firstProject.build(":compileKotlin")
|
||||
|
||||
val outputFilesContainingNonRelocatablePaths =
|
||||
firstProject.projectPath.resolve("../BUILD_DIR_1/kotlin/compileKotlin").walk()
|
||||
.filter {
|
||||
// Use readText() even for binary files as we don't have a better way for now
|
||||
it.isRegularFile() && it.readText().contains("BUILD_DIR_1")
|
||||
}.toList()
|
||||
assert(outputFilesContainingNonRelocatablePaths.isEmpty()) {
|
||||
"The following output files contain non-relocatable paths:\n" + outputFilesContainingNonRelocatablePaths.joinToString("\n")
|
||||
}
|
||||
|
||||
secondProject.build(":compileKotlin") {
|
||||
assertTasksFromCache(":compileKotlin")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-6
@@ -7,6 +7,8 @@ package org.jetbrains.kotlin.compilerRunner
|
||||
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.jetbrains.kotlin.build.report.metrics.*
|
||||
import org.jetbrains.kotlin.build.report.statistics.StatTag
|
||||
import org.jetbrains.kotlin.buildtools.api.KotlinLogger
|
||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.config.Services
|
||||
@@ -15,13 +17,8 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
|
||||
import org.jetbrains.kotlin.gradle.logging.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
|
||||
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers
|
||||
import org.jetbrains.kotlin.build.report.statistics.StatTag
|
||||
import org.jetbrains.kotlin.buildtools.api.KotlinLogger
|
||||
import org.jetbrains.kotlin.gradle.report.*
|
||||
import org.jetbrains.kotlin.gradle.tasks.*
|
||||
import org.jetbrains.kotlin.gradle.tasks.OOMErrorException
|
||||
import org.jetbrains.kotlin.gradle.tasks.cleanOutputsAndLocalState
|
||||
import org.jetbrains.kotlin.gradle.tasks.kotlinDaemonOOMHelperMessage
|
||||
import org.jetbrains.kotlin.gradle.utils.stackTraceAsString
|
||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||
import org.jetbrains.kotlin.incremental.ClasspathChanges
|
||||
@@ -38,7 +35,6 @@ import java.util.*
|
||||
import java.util.concurrent.Callable
|
||||
import java.util.concurrent.Executors
|
||||
import javax.inject.Inject
|
||||
import kotlin.collections.HashSet
|
||||
|
||||
internal class ProjectFilesForCompilation(
|
||||
val projectRootFile: File,
|
||||
@@ -331,6 +327,7 @@ internal class GradleKotlinCompilerWork @Inject constructor(
|
||||
multiModuleICSettings = icEnv.multiModuleICSettings,
|
||||
modulesInfo = incrementalModuleInfo!!,
|
||||
rootProjectDir = icEnv.rootProjectDir,
|
||||
buildDir = icEnv.buildDir,
|
||||
kotlinScriptExtensions = kotlinScriptExtensions,
|
||||
withAbiSnapshot = icEnv.withAbiSnapshot,
|
||||
preciseCompilationResultsBackup = icEnv.preciseCompilationResultsBackup,
|
||||
|
||||
+1
@@ -16,6 +16,7 @@ internal class IncrementalCompilationEnvironment(
|
||||
val classpathChanges: ClasspathChanges,
|
||||
val workingDir: File,
|
||||
val rootProjectDir: File,
|
||||
val buildDir: File,
|
||||
val usePreciseJavaTracking: Boolean = false,
|
||||
val disableMultiModuleIC: Boolean = false,
|
||||
val multiModuleICSettings: MultiModuleICSettings,
|
||||
|
||||
+2
-1
@@ -96,7 +96,8 @@ internal abstract class BuildToolsApiCompilationWork : WorkAction<BuildToolsApiC
|
||||
val classpathChanges = icEnv?.classpathChanges
|
||||
if (classpathChanges is ClasspathChanges.ClasspathSnapshotEnabled) {
|
||||
val classpathSnapshotsConfig = jvmCompilationConfig.makeClasspathSnapshotBasedIncrementalCompilationConfiguration()
|
||||
.useProjectDir(icEnv.rootProjectDir)
|
||||
.setRootProjectDir(icEnv.rootProjectDir)
|
||||
.setBuildDir(icEnv.buildDir)
|
||||
.usePreciseJavaTracking(icEnv.usePreciseJavaTracking)
|
||||
.usePreciseCompilationResultsBackup(icEnv.preciseCompilationResultsBackup)
|
||||
.keepIncrementalCompilationCachesInMemory(icEnv.keepIncrementalCompilationCachesInMemory)
|
||||
|
||||
+6
-4
@@ -328,7 +328,8 @@ abstract class Kotlin2JsCompile @Inject constructor(
|
||||
getChangedFiles(inputChanges, incrementalProps),
|
||||
ClasspathChanges.NotAvailableForJSCompiler,
|
||||
taskBuildCacheableOutputDirectory.get().asFile,
|
||||
projectRootDir,
|
||||
rootProjectDir = rootProjectDir,
|
||||
buildDir = buildDir,
|
||||
multiModuleICSettings = multiModuleICSettings,
|
||||
preciseCompilationResultsBackup = preciseCompilationResultsBackup.get(),
|
||||
keepIncrementalCompilationCachesInMemory = keepIncrementalCompilationCachesInMemory.get(),
|
||||
@@ -351,16 +352,17 @@ abstract class Kotlin2JsCompile @Inject constructor(
|
||||
|
||||
}
|
||||
|
||||
private val projectRootDir = project.rootDir
|
||||
private val rootProjectDir = project.rootDir
|
||||
private val buildDir = project.buildDir
|
||||
|
||||
private fun validateOutputDirectory() {
|
||||
val outputFile = outputFileProperty.get()
|
||||
val outputDir = outputFile.parentFile
|
||||
|
||||
if (outputDir.isParentOf(projectRootDir)) {
|
||||
if (outputDir.isParentOf(rootProjectDir)) {
|
||||
throw InvalidUserDataException(
|
||||
"The output directory '$outputDir' (defined by outputFile of ':$name') contains or " +
|
||||
"matches the project root directory '${projectRootDir}'.\n" +
|
||||
"matches the project root directory '${rootProjectDir}'.\n" +
|
||||
"Gradle will not be able to build the project because of the root directory lock.\n" +
|
||||
"To fix this, consider using the default outputFile location instead of providing it explicitly."
|
||||
)
|
||||
|
||||
+5
-4
@@ -28,9 +28,7 @@ import org.jetbrains.kotlin.compilerRunner.IncrementalCompilationEnvironment
|
||||
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.gradle.dsl.*
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompilerOptionsHelper
|
||||
import org.jetbrains.kotlin.gradle.dsl.jvm.JvmTargetValidationMode
|
||||
import org.jetbrains.kotlin.gradle.dsl.usesK2
|
||||
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
|
||||
import org.jetbrains.kotlin.gradle.logging.GradleErrorMessageCollector
|
||||
import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
|
||||
@@ -44,10 +42,11 @@ import org.jetbrains.kotlin.gradle.report.BuildReportMode
|
||||
import org.jetbrains.kotlin.gradle.tasks.internal.KotlinJvmOptionsCompat
|
||||
import org.jetbrains.kotlin.gradle.utils.*
|
||||
import org.jetbrains.kotlin.incremental.ClasspathChanges
|
||||
import org.jetbrains.kotlin.incremental.ClasspathChanges.*
|
||||
import org.jetbrains.kotlin.incremental.ClasspathChanges.ClasspathSnapshotEnabled.*
|
||||
import org.jetbrains.kotlin.incremental.ClasspathChanges.ClasspathSnapshotDisabled
|
||||
import org.jetbrains.kotlin.incremental.ClasspathChanges.ClasspathSnapshotEnabled.IncrementalRun.NoChanges
|
||||
import org.jetbrains.kotlin.incremental.ClasspathChanges.ClasspathSnapshotEnabled.IncrementalRun.ToBeComputedByIncrementalCompiler
|
||||
import org.jetbrains.kotlin.incremental.ClasspathChanges.ClasspathSnapshotEnabled.NotAvailableDueToMissingClasspathSnapshot
|
||||
import org.jetbrains.kotlin.incremental.ClasspathChanges.ClasspathSnapshotEnabled.NotAvailableForNonIncrementalRun
|
||||
import org.jetbrains.kotlin.incremental.ClasspathSnapshotFiles
|
||||
import org.jetbrains.kotlin.incremental.classpathAsList
|
||||
import org.jetbrains.kotlin.incremental.destinationAsFile
|
||||
@@ -302,6 +301,7 @@ abstract class KotlinCompile @Inject constructor(
|
||||
}
|
||||
|
||||
private val projectRootDir = project.rootDir
|
||||
private val buildDir = project.buildDir
|
||||
|
||||
override fun callCompilerAsync(
|
||||
args: K2JVMCompilerArguments,
|
||||
@@ -325,6 +325,7 @@ abstract class KotlinCompile @Inject constructor(
|
||||
classpathChanges = getClasspathChanges(inputChanges),
|
||||
workingDir = taskBuildCacheableOutputDirectory.get().asFile,
|
||||
rootProjectDir = projectRootDir,
|
||||
buildDir = buildDir,
|
||||
usePreciseJavaTracking = usePreciseJavaTracking,
|
||||
disableMultiModuleIC = disableMultiModuleIC,
|
||||
multiModuleICSettings = multiModuleICSettings,
|
||||
|
||||
Reference in New Issue
Block a user