[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:
Hung Nguyen
2023-08-10 11:05:55 +01:00
committed by Space Team
parent 432c9fe592
commit 894ba9ab80
30 changed files with 329 additions and 293 deletions
@@ -70,10 +70,11 @@ class IncrementalCompilationOptions(
val outputFiles: Collection<File>? = null,
val multiModuleICSettings: MultiModuleICSettings? = null,
val modulesInfo: IncrementalModuleInfo? = null,
/**
* Root project directory, used to resolve relative paths
*/
// rootProjectDir and buildDir are used to resolve relative paths
val rootProjectDir: File?,
val buildDir: File?,
kotlinScriptExtensions: Array<String>? = null,
val withAbiSnapshot: Boolean = false,
val preciseCompilationResultsBackup: Boolean = false,
@@ -60,6 +60,7 @@ import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryAndroid
import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryJs
import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryJvm
import org.jetbrains.kotlin.incremental.parsing.classesFqNames
import org.jetbrains.kotlin.incremental.storage.FileLocations
import org.jetbrains.kotlin.load.kotlin.incremental.components.IncrementalCompilationComponents
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
import java.io.File
@@ -612,20 +613,21 @@ abstract class CompileServiceImplBase(
val workingDir = incrementalCompilationOptions.workingDir
val projectRoot = incrementalCompilationOptions.rootProjectDir
val rootProjectDir = incrementalCompilationOptions.rootProjectDir
val buildDir = incrementalCompilationOptions.buildDir
val modulesApiHistory = incrementalCompilationOptions.multiModuleICSettings?.run {
reporter.info { "Use module detection: $useModuleDetection" }
val modulesInfo = incrementalCompilationOptions.modulesInfo
?: error("The build is configured to use the history-file based IC approach, but doesn't provide the modulesInfo")
check(projectRoot != null) {
check(rootProjectDir != null) {
"rootProjectDir is expected to be non null when the history-file based IC approach is used"
}
if (!useModuleDetection) {
ModulesApiHistoryJvm(projectRoot, modulesInfo)
ModulesApiHistoryJvm(rootProjectDir, modulesInfo)
} else {
ModulesApiHistoryAndroid(projectRoot, modulesInfo)
ModulesApiHistoryAndroid(rootProjectDir, modulesInfo)
}
} ?: EmptyModulesApiHistory
@@ -648,7 +650,12 @@ abstract class CompileServiceImplBase(
keepIncrementalCompilationCachesInMemory = incrementalCompilationOptions.keepIncrementalCompilationCachesInMemory,
)
return try {
compiler.compile(allKotlinFiles, k2jvmArgs, compilerMessageCollector, changedFiles, projectRoot)
compiler.compile(
allKotlinFiles, k2jvmArgs, compilerMessageCollector, changedFiles,
fileLocations = if (rootProjectDir != null && buildDir != null) {
FileLocations(rootProjectDir, buildDir)
} else null
)
} finally {
reporter.endMeasureGc()
reporter.flush()