[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:
Generated
+1
@@ -4,6 +4,7 @@
|
|||||||
<w>externalizers</w>
|
<w>externalizers</w>
|
||||||
<w>granularities</w>
|
<w>granularities</w>
|
||||||
<w>multifile</w>
|
<w>multifile</w>
|
||||||
|
<w>relocatability</w>
|
||||||
<w>shrinker</w>
|
<w>shrinker</w>
|
||||||
<w>snapshotter</w>
|
<w>snapshotter</w>
|
||||||
<w>snapshotter's</w>
|
<w>snapshotter's</w>
|
||||||
|
|||||||
@@ -7,14 +7,13 @@ package org.jetbrains.kotlin.incremental
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.build.report.DoNothingICReporter
|
import org.jetbrains.kotlin.build.report.DoNothingICReporter
|
||||||
import org.jetbrains.kotlin.build.report.ICReporter
|
import org.jetbrains.kotlin.build.report.ICReporter
|
||||||
|
import org.jetbrains.kotlin.incremental.storage.FileToAbsolutePathConverter
|
||||||
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
|
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
|
||||||
import org.jetbrains.kotlin.incremental.storage.IncrementalFileToPathConverter
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
private fun createDefaultPathConverter(rootProjectDir: File?) = IncrementalFileToPathConverter(rootProjectDir)
|
|
||||||
|
|
||||||
class IncrementalCompilationContext(
|
class IncrementalCompilationContext(
|
||||||
val pathConverter: FileToPathConverter,
|
// The root directories of source files and class files are different, so we may need different `FileToPathConverter`s
|
||||||
|
val pathConverterForSourceFiles: FileToPathConverter = FileToAbsolutePathConverter,
|
||||||
|
val pathConverterForOutputFiles: FileToPathConverter = FileToAbsolutePathConverter,
|
||||||
val storeFullFqNamesInLookupCache: Boolean = false,
|
val storeFullFqNamesInLookupCache: Boolean = false,
|
||||||
val transaction: CompilationTransaction = NonRecoverableCompilationTransaction(),
|
val transaction: CompilationTransaction = NonRecoverableCompilationTransaction(),
|
||||||
val reporter: ICReporter = DoNothingICReporter,
|
val reporter: ICReporter = DoNothingICReporter,
|
||||||
@@ -29,19 +28,7 @@ class IncrementalCompilationContext(
|
|||||||
*/
|
*/
|
||||||
val keepIncrementalCompilationCachesInMemory: Boolean = false,
|
val keepIncrementalCompilationCachesInMemory: Boolean = false,
|
||||||
) {
|
) {
|
||||||
constructor(
|
// FIXME: Remove `pathConverter` and require its users to decide whether to use `pathConverterForSourceFiles` or
|
||||||
rootProjectDir: File?,
|
// `pathConverterForClassFiles`
|
||||||
storeFullFqNamesInLookupCache: Boolean = false,
|
val pathConverter = pathConverterForSourceFiles
|
||||||
transaction: CompilationTransaction = NonRecoverableCompilationTransaction(),
|
|
||||||
reporter: ICReporter = DoNothingICReporter,
|
|
||||||
trackChangesInLookupCache: Boolean = false,
|
|
||||||
keepIncrementalCompilationCachesInMemory: Boolean = false,
|
|
||||||
) : this(
|
|
||||||
createDefaultPathConverter(rootProjectDir),
|
|
||||||
storeFullFqNamesInLookupCache,
|
|
||||||
transaction,
|
|
||||||
reporter,
|
|
||||||
trackChangesInLookupCache,
|
|
||||||
keepIncrementalCompilationCachesInMemory
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.incremental.storage
|
|||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
/** Converts a [File] to a path of type [String] to store in IC caches, and vice versa. */
|
||||||
interface FileToPathConverter {
|
interface FileToPathConverter {
|
||||||
fun toPath(file: File): String
|
fun toPath(file: File): String
|
||||||
fun toFile(path: String): File
|
fun toFile(path: String): File
|
||||||
|
|||||||
-34
@@ -1,34 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.incremental.storage
|
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
open class IncrementalFileToPathConverter(val rootProjectDir: File?) : FileToPathConverter {
|
|
||||||
//project root dir
|
|
||||||
private val projectDirPath = rootProjectDir?.normalize()?.absolutePath
|
|
||||||
|
|
||||||
override fun toPath(file: File): String {
|
|
||||||
val path = file.normalize().absolutePath
|
|
||||||
return when {
|
|
||||||
projectDirPath == null || !path.startsWith(projectDirPath) -> path
|
|
||||||
else -> PROJECT_DIR_PLACEHOLDER + path.substring(projectDirPath.length)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toFile(path: String): File =
|
|
||||||
when {
|
|
||||||
rootProjectDir != null && path.startsWith(PROJECT_DIR_PLACEHOLDER) -> rootProjectDir.resolve(path.substring(PATH_PREFIX.length))
|
|
||||||
else -> File(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
private companion object {
|
|
||||||
private const val PROJECT_DIR_PLACEHOLDER = "${'$'}PROJECT_DIR$"
|
|
||||||
//use only for prefix length because it OS dependent
|
|
||||||
private const val PATH_PREFIX = "$PROJECT_DIR_PLACEHOLDER/"
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -16,7 +16,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.incremental.storage
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
interface LazyStorage<K, V> {
|
import java.io.Closeable
|
||||||
|
|
||||||
|
interface LazyStorage<K, V> : Closeable {
|
||||||
val keys: Collection<K>
|
val keys: Collection<K>
|
||||||
operator fun contains(key: K): Boolean
|
operator fun contains(key: K): Boolean
|
||||||
operator fun get(key: K): V?
|
operator fun get(key: K): V?
|
||||||
@@ -24,7 +26,7 @@ interface LazyStorage<K, V> {
|
|||||||
fun remove(key: K)
|
fun remove(key: K)
|
||||||
fun clean()
|
fun clean()
|
||||||
fun flush(memoryCachesOnly: Boolean)
|
fun flush(memoryCachesOnly: Boolean)
|
||||||
fun close()
|
override fun close()
|
||||||
}
|
}
|
||||||
|
|
||||||
interface AppendableLazyStorage<K, V> : LazyStorage<K, V> {
|
interface AppendableLazyStorage<K, V> : LazyStorage<K, V> {
|
||||||
|
|||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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.incremental.storage
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [FileToPathConverter] which converts a [File] to a Unix-style relative path, which is relative to a base directory ([baseDir]), and vice
|
||||||
|
* versa.
|
||||||
|
*
|
||||||
|
* This is to support build cache relocatability
|
||||||
|
* (https://docs.gradle.org/current/userguide/build_cache_concepts.html#relocatability).
|
||||||
|
*/
|
||||||
|
class RelocatableFileToPathConverter(private val baseDir: File) : FileToPathConverter {
|
||||||
|
|
||||||
|
private val unixStyleBaseDirPathPrefix = "${baseDir.invariantSeparatorsPath}/"
|
||||||
|
|
||||||
|
override fun toPath(file: File): String {
|
||||||
|
check(file.invariantSeparatorsPath.startsWith(unixStyleBaseDirPathPrefix)) {
|
||||||
|
"The given file '${file.path}' is located outside the base directory '${baseDir.path}'"
|
||||||
|
}
|
||||||
|
return file.relativeTo(baseDir).invariantSeparatorsPath
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toFile(path: String): File {
|
||||||
|
// Note: The given path is Unix-style but baseDir could be Windows-style; call normalize() so that the style of the returned file's
|
||||||
|
// path is consistent with baseDir.
|
||||||
|
return baseDir.resolve(path).normalize()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File locations to support build cache relocatability (see [RelocatableFileToPathConverter]).
|
||||||
|
*
|
||||||
|
* These are the root directories of
|
||||||
|
* - Source files
|
||||||
|
* - Output files, which include .class files and possibly additional output files such as `.java` stub files for KaptGenerateStubs tasks.
|
||||||
|
*
|
||||||
|
* Ideally, they should be the most specific root directories (e.g., `/path/to/MyApplication/app/src/main/kotlin` for source files and
|
||||||
|
* `/path/to/MyApplication/app/build/tmp/kotlin-classes/debug` for output .class files). However, for simplicity we are using the root
|
||||||
|
* project directory ([rootProjectDir]) for source files and ([buildDir]) for output files.
|
||||||
|
*/
|
||||||
|
class FileLocations(
|
||||||
|
val rootProjectDir: File,
|
||||||
|
val buildDir: File,
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun getRelocatablePathConverterForSourceFiles() = RelocatableFileToPathConverter(rootProjectDir)
|
||||||
|
|
||||||
|
fun getRelocatablePathConverterForOutputFiles() = RelocatableFileToPathConverter(buildDir)
|
||||||
|
}
|
||||||
+1
-1
@@ -125,7 +125,7 @@ class InMemoryStorageWrapperTest {
|
|||||||
val storageFile = storageRoot.resolve("lookup").toFile()
|
val storageFile = storageRoot.resolve("lookup").toFile()
|
||||||
val fileToPathConverter = RelativeFileToPathConverter(storageFile)
|
val fileToPathConverter = RelativeFileToPathConverter(storageFile)
|
||||||
val icContext = IncrementalCompilationContext(
|
val icContext = IncrementalCompilationContext(
|
||||||
pathConverter = fileToPathConverter,
|
pathConverterForSourceFiles = fileToPathConverter,
|
||||||
keepIncrementalCompilationCachesInMemory = useInMemoryWrapper
|
keepIncrementalCompilationCachesInMemory = useInMemoryWrapper
|
||||||
)
|
)
|
||||||
icContext.transaction.runWithin { transaction ->
|
icContext.transaction.runWithin { transaction ->
|
||||||
|
|||||||
-62
@@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.incremental.storage
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.TestWithWorkingDir
|
|
||||||
import org.junit.Test
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
internal class IncrementalFileToPathConverterTest : TestWithWorkingDir() {
|
|
||||||
val separator: String = File.separator
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testPathTransform() {
|
|
||||||
val relativeFilePath = "testFile.txt"
|
|
||||||
val transformedPath = testPathTransformation(workingDir.resolve("testDir"), relativeFilePath)
|
|
||||||
|
|
||||||
assertEquals("${'$'}PROJECT_DIR${'$'}$separator$relativeFilePath", transformedPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testComplicatedProjectRootPath() {
|
|
||||||
val relativeFilePath = "testFile.txt"
|
|
||||||
val transformedPath = testPathTransformation(workingDir.resolve("first$separator..${separator}testDir"), relativeFilePath)
|
|
||||||
|
|
||||||
assertEquals("${'$'}PROJECT_DIR${'$'}$separator$relativeFilePath", transformedPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testInccorectProjectRootPath() {
|
|
||||||
val relativeFilePath = "testFile.txt"
|
|
||||||
val transformedPath = testPathTransformation(workingDir.resolve("testDir$separator"), relativeFilePath)
|
|
||||||
|
|
||||||
assertEquals("${'$'}PROJECT_DIR${'$'}$separator$relativeFilePath", transformedPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testFileOutOfProject() {
|
|
||||||
val relativeFilePath = "..${separator}testFile.txt"
|
|
||||||
val transformedPath = testPathTransformation(workingDir.resolve("testDir"), relativeFilePath)
|
|
||||||
|
|
||||||
assertEquals("${workingDir.absolutePath}${separator}testFile.txt", transformedPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testFileWithExtraSlash() {
|
|
||||||
val relativeFilePath = "testFile.txt$separator"
|
|
||||||
val transformedPath = testPathTransformation(workingDir.resolve("testDir"), relativeFilePath)
|
|
||||||
|
|
||||||
assertEquals("${'$'}PROJECT_DIR${'$'}${separator}testFile.txt", transformedPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun testPathTransformation(projectRoot: File, relativeFilePath: String): String {
|
|
||||||
val pathConverter = IncrementalFileToPathConverter(projectRoot)
|
|
||||||
val testFile = projectRoot.resolve(relativeFilePath)
|
|
||||||
val transformedPath = pathConverter.toPath(testFile)
|
|
||||||
assertEquals(testFile.normalize().absolutePath, pathConverter.toFile(transformedPath).normalize().absolutePath)
|
|
||||||
return transformedPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,8 +7,6 @@ package org.jetbrains.kotlin.incremental.storage
|
|||||||
|
|
||||||
import com.intellij.util.containers.MultiMap
|
import com.intellij.util.containers.MultiMap
|
||||||
import org.jetbrains.kotlin.TestWithWorkingDir
|
import org.jetbrains.kotlin.TestWithWorkingDir
|
||||||
import org.jetbrains.kotlin.cli.common.CompilerSystemProperties
|
|
||||||
import org.jetbrains.kotlin.cli.common.toBooleanLenient
|
|
||||||
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.jetbrains.kotlin.incremental.LookupStorage
|
import org.jetbrains.kotlin.incremental.LookupStorage
|
||||||
import org.jetbrains.kotlin.incremental.LookupSymbol
|
import org.jetbrains.kotlin.incremental.LookupSymbol
|
||||||
@@ -52,7 +50,7 @@ class RelocatableCachesTest : TestWithWorkingDir() {
|
|||||||
val storageRoot = projectRoot.storageRoot
|
val storageRoot = projectRoot.storageRoot
|
||||||
val fileToPathConverter = RelativeFileToPathConverter(projectRoot)
|
val fileToPathConverter = RelativeFileToPathConverter(projectRoot)
|
||||||
val icContext = IncrementalCompilationContext(
|
val icContext = IncrementalCompilationContext(
|
||||||
pathConverter = fileToPathConverter,
|
pathConverterForSourceFiles = fileToPathConverter,
|
||||||
storeFullFqNamesInLookupCache = storeFullFqNames,
|
storeFullFqNamesInLookupCache = storeFullFqNames,
|
||||||
)
|
)
|
||||||
val lookupStorage = LookupStorage(storageRoot, icContext)
|
val lookupStorage = LookupStorage(storageRoot, icContext)
|
||||||
|
|||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 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.incremental.storage
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.TestWithWorkingDir
|
||||||
|
import org.junit.Test
|
||||||
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
|
class RelocatableFileToPathConverterTest : TestWithWorkingDir() {
|
||||||
|
|
||||||
|
private lateinit var pathConverter: RelocatableFileToPathConverter
|
||||||
|
|
||||||
|
override fun setUp() {
|
||||||
|
super.setUp()
|
||||||
|
pathConverter = RelocatableFileToPathConverter(workingDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testToPath() {
|
||||||
|
assertEquals("com/example/Foo.kt", pathConverter.toPath(workingDir.resolve("com/example/Foo.kt")))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testToPathFails() {
|
||||||
|
assertFailsWith(IllegalStateException::class) {
|
||||||
|
pathConverter.toPath(workingDir.resolve("../outsideWorkingDir/com/example/Foo.kt").normalize())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testToFile() {
|
||||||
|
assertEquals(workingDir.resolve("com/example/Foo.kt"), pathConverter.toFile("com/example/Foo.kt"))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -113,10 +113,11 @@ public abstract interface class org/jetbrains/kotlin/buildtools/api/jvm/Classpat
|
|||||||
public abstract fun forceNonIncrementalMode (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration;
|
public abstract fun forceNonIncrementalMode (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration;
|
||||||
public abstract fun getAssuredNoClasspathSnapshotsChanges ()Z
|
public abstract fun getAssuredNoClasspathSnapshotsChanges ()Z
|
||||||
public abstract fun keepIncrementalCompilationCachesInMemory (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration;
|
public abstract fun keepIncrementalCompilationCachesInMemory (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration;
|
||||||
|
public abstract fun setBuildDir (Ljava/io/File;)Lorg/jetbrains/kotlin/buildtools/api/jvm/ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration;
|
||||||
|
public abstract fun setRootProjectDir (Ljava/io/File;)Lorg/jetbrains/kotlin/buildtools/api/jvm/ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration;
|
||||||
public abstract fun useOutputDirs (Ljava/util/Collection;)Lorg/jetbrains/kotlin/buildtools/api/jvm/ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration;
|
public abstract fun useOutputDirs (Ljava/util/Collection;)Lorg/jetbrains/kotlin/buildtools/api/jvm/ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration;
|
||||||
public abstract fun usePreciseCompilationResultsBackup (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration;
|
public abstract fun usePreciseCompilationResultsBackup (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration;
|
||||||
public abstract fun usePreciseJavaTracking (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration;
|
public abstract fun usePreciseJavaTracking (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration;
|
||||||
public abstract fun useProjectDir (Ljava/io/File;)Lorg/jetbrains/kotlin/buildtools/api/jvm/ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract interface class org/jetbrains/kotlin/buildtools/api/jvm/InaccessibleClassSnapshot : org/jetbrains/kotlin/buildtools/api/jvm/ClassSnapshot {
|
public abstract interface class org/jetbrains/kotlin/buildtools/api/jvm/InaccessibleClassSnapshot : org/jetbrains/kotlin/buildtools/api/jvm/ClassSnapshot {
|
||||||
@@ -128,17 +129,19 @@ public abstract interface class org/jetbrains/kotlin/buildtools/api/jvm/Incremen
|
|||||||
public abstract interface class org/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration {
|
public abstract interface class org/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration {
|
||||||
public abstract fun forceNonIncrementalMode (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;
|
public abstract fun forceNonIncrementalMode (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;
|
||||||
public static synthetic fun forceNonIncrementalMode$default (Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;ZILjava/lang/Object;)Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;
|
public static synthetic fun forceNonIncrementalMode$default (Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;ZILjava/lang/Object;)Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;
|
||||||
|
public abstract fun getBuildDir ()Ljava/io/File;
|
||||||
public abstract fun getForcedNonIncrementalMode ()Z
|
public abstract fun getForcedNonIncrementalMode ()Z
|
||||||
public abstract fun getIncrementalCompilationCachesKeptInMemory ()Z
|
public abstract fun getIncrementalCompilationCachesKeptInMemory ()Z
|
||||||
public abstract fun getOutputDirs ()Ljava/util/Set;
|
public abstract fun getOutputDirs ()Ljava/util/Set;
|
||||||
public abstract fun getPreciseCompilationResultsBackupEnabled ()Z
|
public abstract fun getPreciseCompilationResultsBackupEnabled ()Z
|
||||||
public abstract fun getPreciseJavaTrackingEnabled ()Z
|
public abstract fun getPreciseJavaTrackingEnabled ()Z
|
||||||
public abstract fun getProjectDir ()Ljava/io/File;
|
public abstract fun getRootProjectDir ()Ljava/io/File;
|
||||||
public abstract fun keepIncrementalCompilationCachesInMemory (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;
|
public abstract fun keepIncrementalCompilationCachesInMemory (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;
|
||||||
|
public abstract fun setBuildDir (Ljava/io/File;)Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;
|
||||||
|
public abstract fun setRootProjectDir (Ljava/io/File;)Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;
|
||||||
public abstract fun useOutputDirs (Ljava/util/Collection;)Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;
|
public abstract fun useOutputDirs (Ljava/util/Collection;)Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;
|
||||||
public abstract fun usePreciseCompilationResultsBackup (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;
|
public abstract fun usePreciseCompilationResultsBackup (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;
|
||||||
public abstract fun usePreciseJavaTracking (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;
|
public abstract fun usePreciseJavaTracking (Z)Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;
|
||||||
public abstract fun useProjectDir (Ljava/io/File;)Lorg/jetbrains/kotlin/buildtools/api/jvm/IncrementalJvmCompilationConfiguration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract interface class org/jetbrains/kotlin/buildtools/api/jvm/JvmCompilationConfiguration {
|
public abstract interface class org/jetbrains/kotlin/buildtools/api/jvm/JvmCompilationConfiguration {
|
||||||
|
|||||||
+30
-12
@@ -78,20 +78,36 @@ public interface JvmCompilationConfiguration {
|
|||||||
*/
|
*/
|
||||||
@ExperimentalBuildToolsApi
|
@ExperimentalBuildToolsApi
|
||||||
public interface IncrementalJvmCompilationConfiguration<P : IncrementalCompilationApproachParameters> {
|
public interface IncrementalJvmCompilationConfiguration<P : IncrementalCompilationApproachParameters> {
|
||||||
/**
|
|
||||||
* A directory used as a base path for computing relative paths in the incremental compilation caches.
|
|
||||||
*
|
|
||||||
* If is not specified, incremental compilation caches will be non-relocatable
|
|
||||||
*
|
|
||||||
* Managed by [useProjectDir]
|
|
||||||
* Default values is `null`
|
|
||||||
*/
|
|
||||||
public val projectDir: File?
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see [IncrementalJvmCompilationConfiguration.projectDir]
|
* The root project directory, used for computing relative paths in the incremental compilation caches.
|
||||||
|
*
|
||||||
|
* If it is not specified, incremental compilation caches will be non-relocatable.
|
||||||
|
*
|
||||||
|
* Managed by [setRootProjectDir]
|
||||||
|
* Default value is `null`
|
||||||
*/
|
*/
|
||||||
public fun useProjectDir(projectDir: File): IncrementalJvmCompilationConfiguration<P>
|
public val rootProjectDir: File?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see [IncrementalJvmCompilationConfiguration.rootProjectDir]
|
||||||
|
*/
|
||||||
|
public fun setRootProjectDir(rootProjectDir: File): IncrementalJvmCompilationConfiguration<P>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The build directory, used for computing relative paths in the incremental compilation caches.
|
||||||
|
*
|
||||||
|
* If it is not specified, incremental compilation caches will be non-relocatable.
|
||||||
|
*
|
||||||
|
* Managed by [setBuildDir]
|
||||||
|
* Default value is `null`
|
||||||
|
*/
|
||||||
|
public val buildDir: File?
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see [IncrementalJvmCompilationConfiguration.buildDir]
|
||||||
|
*/
|
||||||
|
public fun setBuildDir(buildDir: File): IncrementalJvmCompilationConfiguration<P>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An indicator whether incremental compilation will analyze Java files precisely for better changes detection
|
* An indicator whether incremental compilation will analyze Java files precisely for better changes detection
|
||||||
@@ -186,7 +202,9 @@ public interface ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration :
|
|||||||
*/
|
*/
|
||||||
public fun assureNoClasspathSnapshotsChanges(value: Boolean = true): ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration
|
public fun assureNoClasspathSnapshotsChanges(value: Boolean = true): ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration
|
||||||
|
|
||||||
override fun useProjectDir(projectDir: File): ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration
|
override fun setRootProjectDir(rootProjectDir: File): ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration
|
||||||
|
|
||||||
|
override fun setBuildDir(buildDir: File): ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration
|
||||||
|
|
||||||
override fun usePreciseJavaTracking(value: Boolean): ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration
|
override fun usePreciseJavaTracking(value: Boolean): ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration
|
||||||
|
|
||||||
|
|||||||
+16
-5
@@ -50,12 +50,18 @@ internal abstract class JvmIncrementalCompilationConfigurationImpl<P : Increment
|
|||||||
override var preciseJavaTrackingEnabled: Boolean = true,
|
override var preciseJavaTrackingEnabled: Boolean = true,
|
||||||
override var preciseCompilationResultsBackupEnabled: Boolean = false,
|
override var preciseCompilationResultsBackupEnabled: Boolean = false,
|
||||||
override var incrementalCompilationCachesKeptInMemory: Boolean = false,
|
override var incrementalCompilationCachesKeptInMemory: Boolean = false,
|
||||||
override var projectDir: File? = null,
|
override var rootProjectDir: File? = null,
|
||||||
|
override var buildDir: File? = null,
|
||||||
override var forcedNonIncrementalMode: Boolean = false,
|
override var forcedNonIncrementalMode: Boolean = false,
|
||||||
override var outputDirs: Set<File> = emptySet(),
|
override var outputDirs: Set<File> = emptySet(),
|
||||||
) : IncrementalJvmCompilationConfiguration<P> {
|
) : IncrementalJvmCompilationConfiguration<P> {
|
||||||
override fun useProjectDir(projectDir: File): IncrementalJvmCompilationConfiguration<P> {
|
override fun setRootProjectDir(rootProjectDir: File): IncrementalJvmCompilationConfiguration<P> {
|
||||||
this.projectDir = projectDir
|
this.rootProjectDir = rootProjectDir
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setBuildDir(buildDir: File): IncrementalJvmCompilationConfiguration<P> {
|
||||||
|
this.buildDir = buildDir
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,8 +96,13 @@ internal class ClasspathSnapshotBasedIncrementalJvmCompilationConfigurationImpl(
|
|||||||
) :
|
) :
|
||||||
JvmIncrementalCompilationConfigurationImpl<ClasspathSnapshotBasedIncrementalCompilationApproachParameters>(),
|
JvmIncrementalCompilationConfigurationImpl<ClasspathSnapshotBasedIncrementalCompilationApproachParameters>(),
|
||||||
ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration {
|
ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration {
|
||||||
override fun useProjectDir(projectDir: File): ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration {
|
override fun setRootProjectDir(rootProjectDir: File): ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration {
|
||||||
super.useProjectDir(projectDir)
|
super.setRootProjectDir(rootProjectDir)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setBuildDir(buildDir: File): ClasspathSnapshotBasedIncrementalJvmCompilationConfiguration {
|
||||||
|
super.setBuildDir(buildDir)
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -56,7 +56,8 @@ internal val JvmCompilationConfigurationImpl.asDaemonCompilationOptions: Compila
|
|||||||
outputFiles = options.outputDirs,
|
outputFiles = options.outputDirs,
|
||||||
multiModuleICSettings = null, // required only for the build history approach
|
multiModuleICSettings = null, // required only for the build history approach
|
||||||
modulesInfo = null, // required only for the build history approach
|
modulesInfo = null, // required only for the build history approach
|
||||||
rootProjectDir = options.projectDir,
|
rootProjectDir = options.rootProjectDir,
|
||||||
|
buildDir = options.buildDir,
|
||||||
kotlinScriptExtensions = ktsExtensionsAsArray,
|
kotlinScriptExtensions = ktsExtensionsAsArray,
|
||||||
withAbiSnapshot = false,
|
withAbiSnapshot = false,
|
||||||
preciseCompilationResultsBackup = options.preciseCompilationResultsBackupEnabled,
|
preciseCompilationResultsBackup = options.preciseCompilationResultsBackupEnabled,
|
||||||
|
|||||||
+4
-3
@@ -70,10 +70,11 @@ class IncrementalCompilationOptions(
|
|||||||
val outputFiles: Collection<File>? = null,
|
val outputFiles: Collection<File>? = null,
|
||||||
val multiModuleICSettings: MultiModuleICSettings? = null,
|
val multiModuleICSettings: MultiModuleICSettings? = null,
|
||||||
val modulesInfo: IncrementalModuleInfo? = 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 rootProjectDir: File?,
|
||||||
|
val buildDir: File?,
|
||||||
|
|
||||||
kotlinScriptExtensions: Array<String>? = null,
|
kotlinScriptExtensions: Array<String>? = null,
|
||||||
val withAbiSnapshot: Boolean = false,
|
val withAbiSnapshot: Boolean = false,
|
||||||
val preciseCompilationResultsBackup: 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.ModulesApiHistoryJs
|
||||||
import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryJvm
|
import org.jetbrains.kotlin.incremental.multiproject.ModulesApiHistoryJvm
|
||||||
import org.jetbrains.kotlin.incremental.parsing.classesFqNames
|
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.load.kotlin.incremental.components.IncrementalCompilationComponents
|
||||||
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -612,20 +613,21 @@ abstract class CompileServiceImplBase(
|
|||||||
|
|
||||||
val workingDir = incrementalCompilationOptions.workingDir
|
val workingDir = incrementalCompilationOptions.workingDir
|
||||||
|
|
||||||
val projectRoot = incrementalCompilationOptions.rootProjectDir
|
val rootProjectDir = incrementalCompilationOptions.rootProjectDir
|
||||||
|
val buildDir = incrementalCompilationOptions.buildDir
|
||||||
|
|
||||||
val modulesApiHistory = incrementalCompilationOptions.multiModuleICSettings?.run {
|
val modulesApiHistory = incrementalCompilationOptions.multiModuleICSettings?.run {
|
||||||
reporter.info { "Use module detection: $useModuleDetection" }
|
reporter.info { "Use module detection: $useModuleDetection" }
|
||||||
val modulesInfo = incrementalCompilationOptions.modulesInfo
|
val modulesInfo = incrementalCompilationOptions.modulesInfo
|
||||||
?: error("The build is configured to use the history-file based IC approach, but doesn't provide the 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"
|
"rootProjectDir is expected to be non null when the history-file based IC approach is used"
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!useModuleDetection) {
|
if (!useModuleDetection) {
|
||||||
ModulesApiHistoryJvm(projectRoot, modulesInfo)
|
ModulesApiHistoryJvm(rootProjectDir, modulesInfo)
|
||||||
} else {
|
} else {
|
||||||
ModulesApiHistoryAndroid(projectRoot, modulesInfo)
|
ModulesApiHistoryAndroid(rootProjectDir, modulesInfo)
|
||||||
}
|
}
|
||||||
} ?: EmptyModulesApiHistory
|
} ?: EmptyModulesApiHistory
|
||||||
|
|
||||||
@@ -648,7 +650,12 @@ abstract class CompileServiceImplBase(
|
|||||||
keepIncrementalCompilationCachesInMemory = incrementalCompilationOptions.keepIncrementalCompilationCachesInMemory,
|
keepIncrementalCompilationCachesInMemory = incrementalCompilationOptions.keepIncrementalCompilationCachesInMemory,
|
||||||
)
|
)
|
||||||
return try {
|
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 {
|
} finally {
|
||||||
reporter.endMeasureGc()
|
reporter.endMeasureGc()
|
||||||
reporter.flush()
|
reporter.flush()
|
||||||
|
|||||||
+20
-17
@@ -21,8 +21,11 @@ import org.jetbrains.kotlin.build.GeneratedFile
|
|||||||
import org.jetbrains.kotlin.build.report.BuildReporter
|
import org.jetbrains.kotlin.build.report.BuildReporter
|
||||||
import org.jetbrains.kotlin.build.report.debug
|
import org.jetbrains.kotlin.build.report.debug
|
||||||
import org.jetbrains.kotlin.build.report.info
|
import org.jetbrains.kotlin.build.report.info
|
||||||
import org.jetbrains.kotlin.build.report.metrics.*
|
import org.jetbrains.kotlin.build.report.metrics.BuildAttribute
|
||||||
import org.jetbrains.kotlin.build.report.metrics.BuildAttribute.*
|
import org.jetbrains.kotlin.build.report.metrics.BuildAttribute.*
|
||||||
|
import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric
|
||||||
|
import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime
|
||||||
|
import org.jetbrains.kotlin.build.report.metrics.measure
|
||||||
import org.jetbrains.kotlin.build.report.warn
|
import org.jetbrains.kotlin.build.report.warn
|
||||||
import org.jetbrains.kotlin.cli.common.*
|
import org.jetbrains.kotlin.cli.common.*
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||||
@@ -35,6 +38,8 @@ import org.jetbrains.kotlin.config.Services
|
|||||||
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
import org.jetbrains.kotlin.incremental.components.ExpectActualTracker
|
||||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||||
import org.jetbrains.kotlin.incremental.parsing.classesFqNames
|
import org.jetbrains.kotlin.incremental.parsing.classesFqNames
|
||||||
|
import org.jetbrains.kotlin.incremental.storage.FileLocations
|
||||||
|
import org.jetbrains.kotlin.incremental.storage.FileToAbsolutePathConverter
|
||||||
import org.jetbrains.kotlin.incremental.util.BufferingMessageCollector
|
import org.jetbrains.kotlin.incremental.util.BufferingMessageCollector
|
||||||
import org.jetbrains.kotlin.incremental.util.ExceptionLocation
|
import org.jetbrains.kotlin.incremental.util.ExceptionLocation
|
||||||
import org.jetbrains.kotlin.incremental.util.reportException
|
import org.jetbrains.kotlin.incremental.util.reportException
|
||||||
@@ -45,7 +50,6 @@ import org.jetbrains.kotlin.util.removeSuffixIfPresent
|
|||||||
import org.jetbrains.kotlin.utils.toMetadataVersion
|
import org.jetbrains.kotlin.utils.toMetadataVersion
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
abstract class IncrementalCompilerRunner<
|
abstract class IncrementalCompilerRunner<
|
||||||
Args : CommonCompilerArguments,
|
Args : CommonCompilerArguments,
|
||||||
@@ -83,11 +87,12 @@ abstract class IncrementalCompilerRunner<
|
|||||||
* Creates an instance of [IncrementalCompilationContext] that holds common incremental compilation context mostly required for [CacheManager]
|
* Creates an instance of [IncrementalCompilationContext] that holds common incremental compilation context mostly required for [CacheManager]
|
||||||
*/
|
*/
|
||||||
private fun createIncrementalCompilationContext(
|
private fun createIncrementalCompilationContext(
|
||||||
projectDir: File?,
|
fileLocations: FileLocations?,
|
||||||
transaction: CompilationTransaction
|
transaction: CompilationTransaction,
|
||||||
) = IncrementalCompilationContext(
|
) = IncrementalCompilationContext(
|
||||||
|
pathConverterForSourceFiles = fileLocations?.let { it.getRelocatablePathConverterForSourceFiles() } ?: FileToAbsolutePathConverter,
|
||||||
|
pathConverterForOutputFiles = fileLocations?.let { it.getRelocatablePathConverterForOutputFiles() } ?: FileToAbsolutePathConverter,
|
||||||
transaction = transaction,
|
transaction = transaction,
|
||||||
rootProjectDir = projectDir,
|
|
||||||
reporter = reporter,
|
reporter = reporter,
|
||||||
trackChangesInLookupCache = shouldTrackChangesInLookupCache,
|
trackChangesInLookupCache = shouldTrackChangesInLookupCache,
|
||||||
storeFullFqNamesInLookupCache = shouldStoreFullFqNamesInLookupCache,
|
storeFullFqNamesInLookupCache = shouldStoreFullFqNamesInLookupCache,
|
||||||
@@ -105,12 +110,10 @@ abstract class IncrementalCompilerRunner<
|
|||||||
allSourceFiles: List<File>,
|
allSourceFiles: List<File>,
|
||||||
args: Args,
|
args: Args,
|
||||||
messageCollector: MessageCollector,
|
messageCollector: MessageCollector,
|
||||||
// when `changedFiles` is not null, changes are provided by external system (e.g. Gradle)
|
changedFiles: ChangedFiles?, // When not-null, changes are provided by the build system; otherwise, the IC will need to track them
|
||||||
// otherwise we track source files changes ourselves.
|
fileLocations: FileLocations? = null, // Must be not-null if the build system needs to support build cache relocatability
|
||||||
changedFiles: ChangedFiles?,
|
|
||||||
projectDir: File? = null
|
|
||||||
): ExitCode = reporter.measure(GradleBuildTime.INCREMENTAL_COMPILATION_DAEMON) {
|
): ExitCode = reporter.measure(GradleBuildTime.INCREMENTAL_COMPILATION_DAEMON) {
|
||||||
return when (val result = tryCompileIncrementally(allSourceFiles, changedFiles, args, projectDir, messageCollector)) {
|
return when (val result = tryCompileIncrementally(allSourceFiles, changedFiles, args, fileLocations, messageCollector)) {
|
||||||
is ICResult.Completed -> {
|
is ICResult.Completed -> {
|
||||||
reporter.debug { "Incremental compilation completed" }
|
reporter.debug { "Incremental compilation completed" }
|
||||||
result.exitCode
|
result.exitCode
|
||||||
@@ -120,7 +123,7 @@ abstract class IncrementalCompilerRunner<
|
|||||||
reporter.addAttribute(result.reason)
|
reporter.addAttribute(result.reason)
|
||||||
|
|
||||||
compileNonIncrementally(
|
compileNonIncrementally(
|
||||||
result.reason, allSourceFiles, args, projectDir, trackChangedFiles = changedFiles == null, messageCollector
|
result.reason, allSourceFiles, args, fileLocations, trackChangedFiles = changedFiles == null, messageCollector
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is ICResult.Failed -> {
|
is ICResult.Failed -> {
|
||||||
@@ -139,7 +142,7 @@ abstract class IncrementalCompilerRunner<
|
|||||||
reporter.addAttribute(result.reason)
|
reporter.addAttribute(result.reason)
|
||||||
|
|
||||||
compileNonIncrementally(
|
compileNonIncrementally(
|
||||||
result.reason, allSourceFiles, args, projectDir, trackChangedFiles = changedFiles == null, messageCollector
|
result.reason, allSourceFiles, args, fileLocations, trackChangedFiles = changedFiles == null, messageCollector
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -173,8 +176,8 @@ abstract class IncrementalCompilerRunner<
|
|||||||
allSourceFiles: List<File>,
|
allSourceFiles: List<File>,
|
||||||
changedFiles: ChangedFiles?,
|
changedFiles: ChangedFiles?,
|
||||||
args: Args,
|
args: Args,
|
||||||
projectDir: File?,
|
fileLocations: FileLocations?,
|
||||||
messageCollector: MessageCollector
|
messageCollector: MessageCollector,
|
||||||
): ICResult {
|
): ICResult {
|
||||||
if (changedFiles is ChangedFiles.Unknown) {
|
if (changedFiles is ChangedFiles.Unknown) {
|
||||||
return ICResult.RequiresRebuild(UNKNOWN_CHANGES_IN_GRADLE_INPUTS)
|
return ICResult.RequiresRebuild(UNKNOWN_CHANGES_IN_GRADLE_INPUTS)
|
||||||
@@ -182,7 +185,7 @@ abstract class IncrementalCompilerRunner<
|
|||||||
changedFiles as ChangedFiles.Known?
|
changedFiles as ChangedFiles.Known?
|
||||||
|
|
||||||
return createTransaction().runWithin(::incrementalCompilationExceptionTransformer) { transaction ->
|
return createTransaction().runWithin(::incrementalCompilationExceptionTransformer) { transaction ->
|
||||||
val icContext = createIncrementalCompilationContext(projectDir, transaction)
|
val icContext = createIncrementalCompilationContext(fileLocations, transaction)
|
||||||
val caches = createCacheManager(icContext, args).also {
|
val caches = createCacheManager(icContext, args).also {
|
||||||
// this way we make the transaction to be responsible for closing the caches manager
|
// this way we make the transaction to be responsible for closing the caches manager
|
||||||
transaction.cachesManager = it
|
transaction.cachesManager = it
|
||||||
@@ -253,7 +256,7 @@ abstract class IncrementalCompilerRunner<
|
|||||||
rebuildReason: BuildAttribute,
|
rebuildReason: BuildAttribute,
|
||||||
allSourceFiles: List<File>,
|
allSourceFiles: List<File>,
|
||||||
args: Args,
|
args: Args,
|
||||||
projectDir: File?,
|
fileLocations: FileLocations?,
|
||||||
trackChangedFiles: Boolean, // Whether we need to track changes to the source files or the build system already handles it
|
trackChangedFiles: Boolean, // Whether we need to track changes to the source files or the build system already handles it
|
||||||
messageCollector: MessageCollector,
|
messageCollector: MessageCollector,
|
||||||
): ExitCode {
|
): ExitCode {
|
||||||
@@ -266,7 +269,7 @@ abstract class IncrementalCompilerRunner<
|
|||||||
reporter.debug { "Cleaning ${outputDirsToClean.size} output directories" }
|
reporter.debug { "Cleaning ${outputDirsToClean.size} output directories" }
|
||||||
cleanOrCreateDirectories(outputDirsToClean)
|
cleanOrCreateDirectories(outputDirsToClean)
|
||||||
}
|
}
|
||||||
val icContext = createIncrementalCompilationContext(projectDir, NonRecoverableCompilationTransaction())
|
val icContext = createIncrementalCompilationContext(fileLocations, NonRecoverableCompilationTransaction())
|
||||||
return createCacheManager(icContext, args).use { caches ->
|
return createCacheManager(icContext, args).use { caches ->
|
||||||
if (trackChangedFiles) {
|
if (trackChangedFiles) {
|
||||||
caches.inputsCache.sourceSnapshotMap.compareAndUpdate(allSourceFiles)
|
caches.inputsCache.sourceSnapshotMap.compareAndUpdate(allSourceFiles)
|
||||||
|
|||||||
+2
-2
@@ -38,7 +38,7 @@ class InputsCache(
|
|||||||
|
|
||||||
fun removeOutputForSourceFiles(sources: Iterable<File>) {
|
fun removeOutputForSourceFiles(sources: Iterable<File>) {
|
||||||
for (sourceFile in sources) {
|
for (sourceFile in sources) {
|
||||||
sourceToOutputMap.remove(sourceFile).forEach {
|
sourceToOutputMap.getAndRemove(sourceFile)?.forEach {
|
||||||
icContext.reporter.debug { "Deleting $it on clearing cache for $sourceFile" }
|
icContext.reporter.debug { "Deleting $it on clearing cache for $sourceFile" }
|
||||||
icContext.transaction.deleteFile(it.toPath())
|
icContext.transaction.deleteFile(it.toPath())
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ class InputsCache(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getOutputForSourceFiles(sources: Iterable<File>): List<File> = sources.flatMap {
|
fun getOutputForSourceFiles(sources: Iterable<File>): List<File> = sources.flatMap {
|
||||||
sourceToOutputMap[it]
|
sourceToOutputMap[it].orEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
// generatedFiles can contain multiple entries with the same source file
|
// generatedFiles can contain multiple entries with the same source file
|
||||||
|
|||||||
+5
-3
@@ -8,12 +8,14 @@ package org.jetbrains.kotlin.incremental.classpathDiff
|
|||||||
import com.intellij.openapi.util.io.FileUtil
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
import org.jetbrains.kotlin.build.report.DoNothingICReporter
|
import org.jetbrains.kotlin.build.report.DoNothingICReporter
|
||||||
import org.jetbrains.kotlin.build.report.debug
|
import org.jetbrains.kotlin.build.report.debug
|
||||||
import org.jetbrains.kotlin.build.report.metrics.*
|
import org.jetbrains.kotlin.build.report.metrics.BuildMetricsReporter
|
||||||
|
import org.jetbrains.kotlin.build.report.metrics.GradleBuildPerformanceMetric
|
||||||
|
import org.jetbrains.kotlin.build.report.metrics.GradleBuildTime
|
||||||
|
import org.jetbrains.kotlin.build.report.metrics.measure
|
||||||
import org.jetbrains.kotlin.incremental.*
|
import org.jetbrains.kotlin.incremental.*
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.BreadthFirstSearch.findReachableNodes
|
import org.jetbrains.kotlin.incremental.classpathDiff.BreadthFirstSearch.findReachableNodes
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotShrinker.shrinkClasspath
|
import org.jetbrains.kotlin.incremental.classpathDiff.ClasspathSnapshotShrinker.shrinkClasspath
|
||||||
import org.jetbrains.kotlin.incremental.classpathDiff.ImpactedSymbolsComputer.computeImpactedSymbols
|
import org.jetbrains.kotlin.incremental.classpathDiff.ImpactedSymbolsComputer.computeImpactedSymbols
|
||||||
import org.jetbrains.kotlin.incremental.storage.FileToAbsolutePathConverter
|
|
||||||
import org.jetbrains.kotlin.incremental.storage.ListExternalizer
|
import org.jetbrains.kotlin.incremental.storage.ListExternalizer
|
||||||
import org.jetbrains.kotlin.incremental.storage.loadFromFile
|
import org.jetbrains.kotlin.incremental.storage.loadFromFile
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
@@ -202,7 +204,7 @@ object ClasspathChangesComputer {
|
|||||||
): ProgramSymbolSet {
|
): ProgramSymbolSet {
|
||||||
val workingDir =
|
val workingDir =
|
||||||
FileUtil.createTempDirectory(this::class.java.simpleName, "_WorkingDir_${UUID.randomUUID()}", /* deleteOnExit */ true)
|
FileUtil.createTempDirectory(this::class.java.simpleName, "_WorkingDir_${UUID.randomUUID()}", /* deleteOnExit */ true)
|
||||||
val icContext = IncrementalCompilationContext(pathConverter = FileToAbsolutePathConverter)
|
val icContext = IncrementalCompilationContext()
|
||||||
val incrementalJvmCache = IncrementalJvmCache(workingDir, icContext, null)
|
val incrementalJvmCache = IncrementalJvmCache(workingDir, icContext, null)
|
||||||
|
|
||||||
// Step 1:
|
// Step 1:
|
||||||
|
|||||||
+5
-5
@@ -14,15 +14,15 @@ class SourceToOutputFilesMap(
|
|||||||
icContext: IncrementalCompilationContext,
|
icContext: IncrementalCompilationContext,
|
||||||
) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer, icContext) {
|
) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer, icContext) {
|
||||||
operator fun set(sourceFile: File, outputFiles: Collection<File>) {
|
operator fun set(sourceFile: File, outputFiles: Collection<File>) {
|
||||||
storage[pathConverter.toPath(sourceFile)] = outputFiles.map(pathConverter::toPath)
|
storage[icContext.pathConverterForSourceFiles.toPath(sourceFile)] = outputFiles.map(icContext.pathConverterForOutputFiles::toPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun get(sourceFile: File): Collection<File> =
|
operator fun get(sourceFile: File): Collection<File>? =
|
||||||
storage[pathConverter.toPath(sourceFile)].orEmpty().map(pathConverter::toFile)
|
storage[icContext.pathConverterForSourceFiles.toPath(sourceFile)]?.map(icContext.pathConverterForOutputFiles::toFile)
|
||||||
|
|
||||||
override fun dumpValue(value: Collection<String>) =
|
override fun dumpValue(value: Collection<String>) =
|
||||||
value.dumpCollection()
|
value.dumpCollection()
|
||||||
|
|
||||||
fun remove(file: File): Collection<File> =
|
fun getAndRemove(file: File): Collection<File>? =
|
||||||
get(file).also { storage.remove(pathConverter.toPath(file)) }
|
get(file).also { storage.remove(icContext.pathConverterForSourceFiles.toPath(file)) }
|
||||||
}
|
}
|
||||||
+1
-1
@@ -28,7 +28,7 @@ import java.util.*
|
|||||||
class BuildDiffsStorageTest {
|
class BuildDiffsStorageTest {
|
||||||
lateinit var storageFile: File
|
lateinit var storageFile: File
|
||||||
private val random = Random(System.currentTimeMillis())
|
private val random = Random(System.currentTimeMillis())
|
||||||
private val icContext = IncrementalCompilationContext(null)
|
private val icContext = IncrementalCompilationContext()
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun setUp() {
|
fun setUp() {
|
||||||
|
|||||||
+3
-4
@@ -7,8 +7,7 @@ package org.jetbrains.kotlin.incremental.snapshots
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.TestWithWorkingDir
|
import org.jetbrains.kotlin.TestWithWorkingDir
|
||||||
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.jetbrains.kotlin.incremental.storage.FileToPathConverter
|
import org.jetbrains.kotlin.incremental.storage.RelocatableFileToPathConverter
|
||||||
import org.jetbrains.kotlin.incremental.storage.IncrementalFileToPathConverter
|
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Assert.assertArrayEquals
|
import org.junit.Assert.assertArrayEquals
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@@ -24,9 +23,9 @@ class FileSnapshotMapTest : TestWithWorkingDir() {
|
|||||||
super.setUp()
|
super.setUp()
|
||||||
val caches = File(workingDir, "caches").apply { mkdirs() }
|
val caches = File(workingDir, "caches").apply { mkdirs() }
|
||||||
val snapshotMapFile = File(caches, "snapshots.tab")
|
val snapshotMapFile = File(caches, "snapshots.tab")
|
||||||
val pathConverter = IncrementalFileToPathConverter((workingDir.canonicalFile))
|
val pathConverter = RelocatableFileToPathConverter((workingDir.canonicalFile))
|
||||||
val icContext = IncrementalCompilationContext(
|
val icContext = IncrementalCompilationContext(
|
||||||
pathConverter = pathConverter
|
pathConverterForSourceFiles = pathConverter
|
||||||
)
|
)
|
||||||
snapshotMap = FileSnapshotMap(snapshotMapFile, icContext)
|
snapshotMap = FileSnapshotMap(snapshotMapFile, icContext)
|
||||||
}
|
}
|
||||||
|
|||||||
+67
-93
@@ -5,131 +5,105 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.incremental.storage
|
package org.jetbrains.kotlin.incremental.storage
|
||||||
|
|
||||||
import org.jetbrains.kotlin.TestWithWorkingDir
|
import junit.framework.TestCase.assertEquals
|
||||||
|
import junit.framework.TestCase.assertNull
|
||||||
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
import org.jetbrains.kotlin.incremental.IncrementalCompilationContext
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Assert.assertArrayEquals
|
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import org.junit.rules.TemporaryFolder
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.properties.Delegates
|
import kotlin.test.assertFailsWith
|
||||||
|
|
||||||
class SourceToOutputFilesMapTest : TestWithWorkingDir() {
|
class SourceToOutputFilesMapTest {
|
||||||
private var stofMap: SourceToOutputFilesMap by Delegates.notNull()
|
|
||||||
private var pathConverter: FileToPathConverter by Delegates.notNull()
|
@get:Rule
|
||||||
|
val tmpDir = TemporaryFolder()
|
||||||
|
|
||||||
|
private lateinit var srcDir: File
|
||||||
|
private lateinit var classesDir: File
|
||||||
|
|
||||||
|
private lateinit var stofMap: SourceToOutputFilesMap
|
||||||
|
|
||||||
|
private lateinit var fooDotKt: File
|
||||||
|
private lateinit var fooDotClass: File
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
override fun setUp() {
|
fun setUp() {
|
||||||
super.setUp()
|
val workingDir = tmpDir.root
|
||||||
val caches = File(workingDir, "caches").apply { mkdirs() }
|
|
||||||
val stofMapFile = File(caches, "stof.tab")
|
srcDir = workingDir.resolve("src")
|
||||||
pathConverter = IncrementalFileToPathConverter((workingDir.canonicalFile))
|
classesDir = workingDir.resolve("classes")
|
||||||
val icContext = IncrementalCompilationContext(
|
|
||||||
pathConverter = pathConverter
|
stofMap = SourceToOutputFilesMap(
|
||||||
|
storageFile = workingDir.resolve("stof.tab"),
|
||||||
|
icContext = IncrementalCompilationContext(
|
||||||
|
pathConverterForSourceFiles = RelocatableFileToPathConverter(srcDir),
|
||||||
|
pathConverterForOutputFiles = RelocatableFileToPathConverter(classesDir),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
stofMap = SourceToOutputFilesMap(stofMapFile, icContext)
|
|
||||||
|
fooDotKt = srcDir.resolve("Foo.kt")
|
||||||
|
fooDotClass = classesDir.resolve("Foo.class")
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
override fun tearDown() {
|
fun tearDown() {
|
||||||
stofMap.flush(false)
|
stofMap.flush(false)
|
||||||
stofMap.closeForTest()
|
stofMap.closeForTest()
|
||||||
super.tearDown()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testEmptyGetReturnsEmpty() {
|
fun testNoSetGetReturnsNull() {
|
||||||
assertTrue(stofMap.get(File("")).isEmpty())
|
assertNull(stofMap[fooDotKt])
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSetGetOneReturnsOne() {
|
fun testSetOneGetReturnsOne() {
|
||||||
stofMap.set(
|
stofMap[fooDotKt] = listOf(fooDotClass)
|
||||||
File(""),
|
|
||||||
listOf(File("one").canonicalFile))
|
assertEquals(listOf(fooDotClass), stofMap[fooDotKt])
|
||||||
assertEquals(
|
|
||||||
listOf(File("one").canonicalFile),
|
|
||||||
stofMap.get(File("")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSetDupeReturnsUnique() {
|
fun testSetDupeGetReturnsUnique() {
|
||||||
stofMap.set(
|
stofMap[fooDotKt] = listOf(fooDotClass, fooDotClass)
|
||||||
File(""),
|
|
||||||
listOf(File("one").canonicalFile, File("one").canonicalFile, File("one").canonicalFile))
|
|
||||||
|
|
||||||
assertEquals(
|
assertEquals(listOf(fooDotClass), stofMap[fooDotKt])
|
||||||
listOf(File("one").canonicalFile),
|
|
||||||
stofMap.get(File("")))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testSetOverwriteReturnsNew() {
|
fun testSetOverwriteGetReturnsNew() {
|
||||||
stofMap.set(
|
val fooKtDotClass = classesDir.resolve("FooKt.class")
|
||||||
File(""),
|
stofMap[fooDotKt] = listOf(fooDotClass)
|
||||||
listOf(File("old").canonicalFile, File("old").canonicalFile, File("old").canonicalFile))
|
stofMap[fooDotKt] = listOf(fooKtDotClass)
|
||||||
stofMap.set(
|
|
||||||
File(""),
|
|
||||||
listOf(File("one").canonicalFile, File("two").canonicalFile, File("three").canonicalFile))
|
|
||||||
|
|
||||||
assertArrayEquals(
|
assertEquals(listOf(fooKtDotClass), stofMap[fooDotKt])
|
||||||
listOf(File("one").canonicalFile, File("two").canonicalFile, File("three").canonicalFile).toSortedPaths(),
|
|
||||||
stofMap.get(File("")).toSortedPaths())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testRelativeInReturnsAbsolute() {
|
fun testSetRelativeFails() {
|
||||||
stofMap.set(
|
assertFailsWith<IllegalStateException> {
|
||||||
File(""),
|
stofMap[fooDotKt] = listOf(File("relativePath"))
|
||||||
listOf(File("one"), File("two"), File("three")))
|
|
||||||
|
|
||||||
assertArrayEquals(
|
|
||||||
listOf(File("one").canonicalFile, File("two").canonicalFile, File("three").canonicalFile).toSortedPaths(),
|
|
||||||
stofMap.get(File("")).toSortedPaths()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testSetRelativeGetAbsolute() {
|
|
||||||
stofMap.set(
|
|
||||||
File("blah"),
|
|
||||||
listOf(File("one"), File("two"), File("three")))
|
|
||||||
|
|
||||||
assertArrayEquals(
|
|
||||||
listOf(File("one").canonicalFile, File("two").canonicalFile, File("three").canonicalFile).toSortedPaths(),
|
|
||||||
stofMap.get(File("blah").canonicalFile).toSortedPaths()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testSetRemove() {
|
|
||||||
stofMap.set(
|
|
||||||
File("blah"),
|
|
||||||
listOf(File("one"), File("two"), File("three")))
|
|
||||||
|
|
||||||
assertArrayEquals(
|
|
||||||
listOf(File("one").canonicalFile, File("two").canonicalFile, File("three").canonicalFile).toSortedPaths(),
|
|
||||||
stofMap.remove(File("blah")).toSortedPaths()
|
|
||||||
)
|
|
||||||
assertTrue(stofMap.get(File("blah")).isEmpty())
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testSetRemoveLoop() {
|
|
||||||
repeat(5) {
|
|
||||||
stofMap.set(
|
|
||||||
File("blah"),
|
|
||||||
listOf(File("one"), File("two"), File("three"))
|
|
||||||
)
|
|
||||||
|
|
||||||
assertArrayEquals(
|
|
||||||
listOf(File("one").canonicalFile, File("two").canonicalFile, File("three").canonicalFile).toSortedPaths(),
|
|
||||||
stofMap.remove(File("blah")).toSortedPaths()
|
|
||||||
)
|
|
||||||
assertTrue(stofMap.get(File("blah")).isEmpty())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Iterable<File>.toSortedPaths(): Array<String> =
|
@Test
|
||||||
map { it.canonicalPath }.sorted().toTypedArray()
|
fun testGetRelativeFails() {
|
||||||
|
stofMap[fooDotKt] = listOf(fooDotClass)
|
||||||
|
|
||||||
|
assertFailsWith<IllegalStateException> {
|
||||||
|
stofMap[fooDotKt.relativeTo(srcDir)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testGetAndRemove() {
|
||||||
|
stofMap[fooDotKt] = listOf(fooDotClass)
|
||||||
|
|
||||||
|
assertEquals(listOf(fooDotClass), stofMap.getAndRemove(fooDotKt))
|
||||||
|
assertNull(stofMap[fooDotKt])
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -82,7 +82,10 @@ class KotlinCompileContext(val jpsContext: CompileContext) {
|
|||||||
val fileToPathConverter: FileToPathConverter =
|
val fileToPathConverter: FileToPathConverter =
|
||||||
JpsFileToPathConverter(jpsContext.projectDescriptor.project)
|
JpsFileToPathConverter(jpsContext.projectDescriptor.project)
|
||||||
|
|
||||||
val icContext = IncrementalCompilationContext(pathConverter = fileToPathConverter)
|
val icContext = IncrementalCompilationContext(
|
||||||
|
pathConverterForSourceFiles = fileToPathConverter,
|
||||||
|
pathConverterForOutputFiles = fileToPathConverter
|
||||||
|
)
|
||||||
|
|
||||||
val lookupStorageManager = JpsLookupStorageManager(dataManager, icContext)
|
val lookupStorageManager = JpsLookupStorageManager(dataManager, icContext)
|
||||||
|
|
||||||
|
|||||||
+28
-1
@@ -17,13 +17,15 @@
|
|||||||
package org.jetbrains.kotlin.gradle
|
package org.jetbrains.kotlin.gradle
|
||||||
|
|
||||||
import org.gradle.api.logging.LogLevel
|
import org.gradle.api.logging.LogLevel
|
||||||
import org.gradle.api.logging.configuration.WarningMode
|
|
||||||
import org.gradle.testkit.runner.BuildResult
|
import org.gradle.testkit.runner.BuildResult
|
||||||
import org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
import org.jetbrains.kotlin.gradle.testbase.*
|
import org.jetbrains.kotlin.gradle.testbase.*
|
||||||
import org.junit.jupiter.api.DisplayName
|
import org.junit.jupiter.api.DisplayName
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import kotlin.io.path.createDirectory
|
import kotlin.io.path.createDirectory
|
||||||
|
import kotlin.io.path.isRegularFile
|
||||||
|
import kotlin.io.path.readText
|
||||||
|
import kotlin.io.path.walk
|
||||||
|
|
||||||
@DisplayName("Build cache relocation")
|
@DisplayName("Build cache relocation")
|
||||||
class BuildCacheRelocationIT : KGPBaseTest() {
|
class BuildCacheRelocationIT : KGPBaseTest() {
|
||||||
@@ -400,4 +402,29 @@ class BuildCacheRelocationIT : KGPBaseTest() {
|
|||||||
assertTasksFromCache(":app:kaptGenerateStubsKotlin", ":app:kaptKotlin")
|
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.gradle.api.logging.Logger
|
||||||
import org.jetbrains.kotlin.build.report.metrics.*
|
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.ExitCode
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.config.Services
|
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.logging.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
|
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers
|
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.report.*
|
||||||
import org.jetbrains.kotlin.gradle.tasks.*
|
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.gradle.utils.stackTraceAsString
|
||||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||||
import org.jetbrains.kotlin.incremental.ClasspathChanges
|
import org.jetbrains.kotlin.incremental.ClasspathChanges
|
||||||
@@ -38,7 +35,6 @@ import java.util.*
|
|||||||
import java.util.concurrent.Callable
|
import java.util.concurrent.Callable
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.collections.HashSet
|
|
||||||
|
|
||||||
internal class ProjectFilesForCompilation(
|
internal class ProjectFilesForCompilation(
|
||||||
val projectRootFile: File,
|
val projectRootFile: File,
|
||||||
@@ -331,6 +327,7 @@ internal class GradleKotlinCompilerWork @Inject constructor(
|
|||||||
multiModuleICSettings = icEnv.multiModuleICSettings,
|
multiModuleICSettings = icEnv.multiModuleICSettings,
|
||||||
modulesInfo = incrementalModuleInfo!!,
|
modulesInfo = incrementalModuleInfo!!,
|
||||||
rootProjectDir = icEnv.rootProjectDir,
|
rootProjectDir = icEnv.rootProjectDir,
|
||||||
|
buildDir = icEnv.buildDir,
|
||||||
kotlinScriptExtensions = kotlinScriptExtensions,
|
kotlinScriptExtensions = kotlinScriptExtensions,
|
||||||
withAbiSnapshot = icEnv.withAbiSnapshot,
|
withAbiSnapshot = icEnv.withAbiSnapshot,
|
||||||
preciseCompilationResultsBackup = icEnv.preciseCompilationResultsBackup,
|
preciseCompilationResultsBackup = icEnv.preciseCompilationResultsBackup,
|
||||||
|
|||||||
+1
@@ -16,6 +16,7 @@ internal class IncrementalCompilationEnvironment(
|
|||||||
val classpathChanges: ClasspathChanges,
|
val classpathChanges: ClasspathChanges,
|
||||||
val workingDir: File,
|
val workingDir: File,
|
||||||
val rootProjectDir: File,
|
val rootProjectDir: File,
|
||||||
|
val buildDir: File,
|
||||||
val usePreciseJavaTracking: Boolean = false,
|
val usePreciseJavaTracking: Boolean = false,
|
||||||
val disableMultiModuleIC: Boolean = false,
|
val disableMultiModuleIC: Boolean = false,
|
||||||
val multiModuleICSettings: MultiModuleICSettings,
|
val multiModuleICSettings: MultiModuleICSettings,
|
||||||
|
|||||||
+2
-1
@@ -96,7 +96,8 @@ internal abstract class BuildToolsApiCompilationWork : WorkAction<BuildToolsApiC
|
|||||||
val classpathChanges = icEnv?.classpathChanges
|
val classpathChanges = icEnv?.classpathChanges
|
||||||
if (classpathChanges is ClasspathChanges.ClasspathSnapshotEnabled) {
|
if (classpathChanges is ClasspathChanges.ClasspathSnapshotEnabled) {
|
||||||
val classpathSnapshotsConfig = jvmCompilationConfig.makeClasspathSnapshotBasedIncrementalCompilationConfiguration()
|
val classpathSnapshotsConfig = jvmCompilationConfig.makeClasspathSnapshotBasedIncrementalCompilationConfiguration()
|
||||||
.useProjectDir(icEnv.rootProjectDir)
|
.setRootProjectDir(icEnv.rootProjectDir)
|
||||||
|
.setBuildDir(icEnv.buildDir)
|
||||||
.usePreciseJavaTracking(icEnv.usePreciseJavaTracking)
|
.usePreciseJavaTracking(icEnv.usePreciseJavaTracking)
|
||||||
.usePreciseCompilationResultsBackup(icEnv.preciseCompilationResultsBackup)
|
.usePreciseCompilationResultsBackup(icEnv.preciseCompilationResultsBackup)
|
||||||
.keepIncrementalCompilationCachesInMemory(icEnv.keepIncrementalCompilationCachesInMemory)
|
.keepIncrementalCompilationCachesInMemory(icEnv.keepIncrementalCompilationCachesInMemory)
|
||||||
|
|||||||
+6
-4
@@ -328,7 +328,8 @@ abstract class Kotlin2JsCompile @Inject constructor(
|
|||||||
getChangedFiles(inputChanges, incrementalProps),
|
getChangedFiles(inputChanges, incrementalProps),
|
||||||
ClasspathChanges.NotAvailableForJSCompiler,
|
ClasspathChanges.NotAvailableForJSCompiler,
|
||||||
taskBuildCacheableOutputDirectory.get().asFile,
|
taskBuildCacheableOutputDirectory.get().asFile,
|
||||||
projectRootDir,
|
rootProjectDir = rootProjectDir,
|
||||||
|
buildDir = buildDir,
|
||||||
multiModuleICSettings = multiModuleICSettings,
|
multiModuleICSettings = multiModuleICSettings,
|
||||||
preciseCompilationResultsBackup = preciseCompilationResultsBackup.get(),
|
preciseCompilationResultsBackup = preciseCompilationResultsBackup.get(),
|
||||||
keepIncrementalCompilationCachesInMemory = keepIncrementalCompilationCachesInMemory.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() {
|
private fun validateOutputDirectory() {
|
||||||
val outputFile = outputFileProperty.get()
|
val outputFile = outputFileProperty.get()
|
||||||
val outputDir = outputFile.parentFile
|
val outputDir = outputFile.parentFile
|
||||||
|
|
||||||
if (outputDir.isParentOf(projectRootDir)) {
|
if (outputDir.isParentOf(rootProjectDir)) {
|
||||||
throw InvalidUserDataException(
|
throw InvalidUserDataException(
|
||||||
"The output directory '$outputDir' (defined by outputFile of ':$name') contains or " +
|
"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" +
|
"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."
|
"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.compilerRunner.OutputItemsCollectorImpl
|
||||||
import org.jetbrains.kotlin.config.JvmTarget
|
import org.jetbrains.kotlin.config.JvmTarget
|
||||||
import org.jetbrains.kotlin.gradle.dsl.*
|
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.jvm.JvmTargetValidationMode
|
||||||
import org.jetbrains.kotlin.gradle.dsl.usesK2
|
|
||||||
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
|
import org.jetbrains.kotlin.gradle.internal.tasks.allOutputFiles
|
||||||
import org.jetbrains.kotlin.gradle.logging.GradleErrorMessageCollector
|
import org.jetbrains.kotlin.gradle.logging.GradleErrorMessageCollector
|
||||||
import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
|
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.tasks.internal.KotlinJvmOptionsCompat
|
||||||
import org.jetbrains.kotlin.gradle.utils.*
|
import org.jetbrains.kotlin.gradle.utils.*
|
||||||
import org.jetbrains.kotlin.incremental.ClasspathChanges
|
import org.jetbrains.kotlin.incremental.ClasspathChanges
|
||||||
import org.jetbrains.kotlin.incremental.ClasspathChanges.*
|
import org.jetbrains.kotlin.incremental.ClasspathChanges.ClasspathSnapshotDisabled
|
||||||
import org.jetbrains.kotlin.incremental.ClasspathChanges.ClasspathSnapshotEnabled.*
|
|
||||||
import org.jetbrains.kotlin.incremental.ClasspathChanges.ClasspathSnapshotEnabled.IncrementalRun.NoChanges
|
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.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.ClasspathSnapshotFiles
|
||||||
import org.jetbrains.kotlin.incremental.classpathAsList
|
import org.jetbrains.kotlin.incremental.classpathAsList
|
||||||
import org.jetbrains.kotlin.incremental.destinationAsFile
|
import org.jetbrains.kotlin.incremental.destinationAsFile
|
||||||
@@ -302,6 +301,7 @@ abstract class KotlinCompile @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val projectRootDir = project.rootDir
|
private val projectRootDir = project.rootDir
|
||||||
|
private val buildDir = project.buildDir
|
||||||
|
|
||||||
override fun callCompilerAsync(
|
override fun callCompilerAsync(
|
||||||
args: K2JVMCompilerArguments,
|
args: K2JVMCompilerArguments,
|
||||||
@@ -325,6 +325,7 @@ abstract class KotlinCompile @Inject constructor(
|
|||||||
classpathChanges = getClasspathChanges(inputChanges),
|
classpathChanges = getClasspathChanges(inputChanges),
|
||||||
workingDir = taskBuildCacheableOutputDirectory.get().asFile,
|
workingDir = taskBuildCacheableOutputDirectory.get().asFile,
|
||||||
rootProjectDir = projectRootDir,
|
rootProjectDir = projectRootDir,
|
||||||
|
buildDir = buildDir,
|
||||||
usePreciseJavaTracking = usePreciseJavaTracking,
|
usePreciseJavaTracking = usePreciseJavaTracking,
|
||||||
disableMultiModuleIC = disableMultiModuleIC,
|
disableMultiModuleIC = disableMultiModuleIC,
|
||||||
multiModuleICSettings = multiModuleICSettings,
|
multiModuleICSettings = multiModuleICSettings,
|
||||||
|
|||||||
Reference in New Issue
Block a user