Move compileIncrementally to common IC
This commit is contained in:
+108
-119
@@ -24,10 +24,7 @@ import org.jetbrains.kotlin.build.JvmSourceRoot
|
|||||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
|
||||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
|
||||||
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
|
||||||
import org.jetbrains.kotlin.compilerRunner.*
|
import org.jetbrains.kotlin.compilerRunner.*
|
||||||
import org.jetbrains.kotlin.config.IncrementalCompilation
|
import org.jetbrains.kotlin.config.IncrementalCompilation
|
||||||
@@ -177,6 +174,13 @@ abstract class IncrementalCompilerRunner<
|
|||||||
return dirtyFiles
|
return dirtyFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected sealed class CompilationMode {
|
||||||
|
class Incremental(val dirtyFiles: Set<File>) : CompilationMode()
|
||||||
|
class Rebuild(getReason: ()->String = { "" }) : CompilationMode() {
|
||||||
|
val reason: String by lazy(getReason)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected open fun markOutputDirty(caches: CacheManager, dirtySources: List<File>) {
|
protected open fun markOutputDirty(caches: CacheManager, dirtySources: List<File>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,14 +193,6 @@ abstract class IncrementalCompilerRunner<
|
|||||||
protected open fun additionalDirtyLookupSymbols(): Iterable<LookupSymbol> =
|
protected open fun additionalDirtyLookupSymbols(): Iterable<LookupSymbol> =
|
||||||
emptyList()
|
emptyList()
|
||||||
|
|
||||||
protected abstract fun compileIncrementally(
|
|
||||||
args: Args,
|
|
||||||
caches: CacheManager,
|
|
||||||
allKotlinSources: List<File>,
|
|
||||||
compilationMode: CompilationMode,
|
|
||||||
messageCollector: MessageCollector
|
|
||||||
): ExitCode
|
|
||||||
|
|
||||||
protected abstract fun runCompiler(
|
protected abstract fun runCompiler(
|
||||||
sourcesToCompile: Set<File>,
|
sourcesToCompile: Set<File>,
|
||||||
args: Args,
|
args: Args,
|
||||||
@@ -205,11 +201,108 @@ abstract class IncrementalCompilerRunner<
|
|||||||
messageCollector: MessageCollector
|
messageCollector: MessageCollector
|
||||||
): ExitCode
|
): ExitCode
|
||||||
|
|
||||||
protected sealed class CompilationMode {
|
private fun compileIncrementally(
|
||||||
class Incremental(val dirtyFiles: Set<File>) : CompilationMode()
|
args: Args,
|
||||||
class Rebuild(getReason: ()->String = { "" }) : CompilationMode() {
|
caches: CacheManager,
|
||||||
val reason: String by lazy(getReason)
|
allKotlinSources: List<File>,
|
||||||
|
compilationMode: CompilationMode,
|
||||||
|
messageCollector: MessageCollector
|
||||||
|
): ExitCode {
|
||||||
|
preBuildHook(args, compilationMode)
|
||||||
|
|
||||||
|
val dirtySources = when (compilationMode) {
|
||||||
|
is CompilationMode.Incremental -> ArrayList(compilationMode.dirtyFiles)
|
||||||
|
is CompilationMode.Rebuild -> allKotlinSources.toMutableList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val currentBuildInfo = BuildInfo(startTS = System.currentTimeMillis())
|
||||||
|
BuildInfo.write(currentBuildInfo, lastBuildInfoFile)
|
||||||
|
val buildDirtyLookupSymbols = HashSet<LookupSymbol>()
|
||||||
|
val buildDirtyFqNames = HashSet<FqName>()
|
||||||
|
val allSourcesToCompile = HashSet<File>()
|
||||||
|
|
||||||
|
var exitCode = ExitCode.OK
|
||||||
|
val allGeneratedFiles = hashSetOf<GeneratedFile>()
|
||||||
|
|
||||||
|
while (dirtySources.any()) {
|
||||||
|
markOutputDirty(caches, dirtySources)
|
||||||
|
caches.inputsCache.removeOutputForSourceFiles(dirtySources)
|
||||||
|
|
||||||
|
val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING)
|
||||||
|
val (sourcesToCompile, removedKotlinSources) = dirtySources.partition(File::exists)
|
||||||
|
|
||||||
|
// todo: more optimal to save only last iteration, but it will require adding standalone-ic specific logs
|
||||||
|
// (because jps rebuilds all files from last build if it failed and gradle rebuilds everything)
|
||||||
|
allSourcesToCompile.addAll(sourcesToCompile)
|
||||||
|
val text = allSourcesToCompile.joinToString(separator = System.getProperty("line.separator")) { it.canonicalPath }
|
||||||
|
dirtySourcesSinceLastTimeFile.writeText(text)
|
||||||
|
|
||||||
|
val services = Services.Builder().apply {
|
||||||
|
register(LookupTracker::class.java, lookupTracker)
|
||||||
|
register(CompilationCanceledStatus::class.java, EmptyCompilationCanceledStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
args.reportOutputFiles = true
|
||||||
|
val outputItemsCollector = OutputItemsCollectorImpl()
|
||||||
|
val messageCollectorAdapter = MessageCollectorToOutputItemsCollectorAdapter(messageCollector, outputItemsCollector)
|
||||||
|
|
||||||
|
exitCode = runCompiler(sourcesToCompile.toSet(), args, caches, services, messageCollectorAdapter)
|
||||||
|
postCompilationHook(exitCode)
|
||||||
|
|
||||||
|
if (exitCode != ExitCode.OK) break
|
||||||
|
|
||||||
|
dirtySourcesSinceLastTimeFile.delete()
|
||||||
|
val generatedFiles = outputItemsCollector.outputs.map(SimpleOutputItem::toGeneratedFile)
|
||||||
|
|
||||||
|
if (compilationMode is CompilationMode.Incremental) {
|
||||||
|
// todo: feels dirty, can this be refactored?
|
||||||
|
val dirtySourcesSet = dirtySources.toHashSet()
|
||||||
|
val additionalDirtyFiles = additionalDirtyFiles(caches, generatedFiles).filter { it !in dirtySourcesSet }
|
||||||
|
if (additionalDirtyFiles.isNotEmpty()) {
|
||||||
|
dirtySources.addAll(additionalDirtyFiles)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allGeneratedFiles.addAll(generatedFiles)
|
||||||
|
caches.inputsCache.registerOutputForSourceFiles(generatedFiles)
|
||||||
|
caches.lookupCache.update(lookupTracker, sourcesToCompile, removedKotlinSources)
|
||||||
|
val compilationResult = compareAndUpdateCache(caches, generatedFiles)
|
||||||
|
|
||||||
|
if (compilationMode is CompilationMode.Rebuild) break
|
||||||
|
|
||||||
|
val (dirtyLookupSymbols, dirtyClassFqNames) = compilationResult.getDirtyData(listOf(caches.platformCache), reporter)
|
||||||
|
val compiledInThisIterationSet = sourcesToCompile.toHashSet()
|
||||||
|
|
||||||
|
with (dirtySources) {
|
||||||
|
clear()
|
||||||
|
addAll(mapLookupSymbolsToFiles(caches.lookupCache, dirtyLookupSymbols, reporter, excludes = compiledInThisIterationSet))
|
||||||
|
addAll(mapClassesFqNamesToFiles(listOf(caches.platformCache), dirtyClassFqNames, reporter, excludes = compiledInThisIterationSet))
|
||||||
|
}
|
||||||
|
|
||||||
|
buildDirtyLookupSymbols.addAll(dirtyLookupSymbols)
|
||||||
|
buildDirtyFqNames.addAll(dirtyClassFqNames)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exitCode == ExitCode.OK && compilationMode is CompilationMode.Incremental) {
|
||||||
|
buildDirtyLookupSymbols.addAll(additionalDirtyLookupSymbols())
|
||||||
|
}
|
||||||
|
if (changesRegistry != null) {
|
||||||
|
if (compilationMode is CompilationMode.Incremental) {
|
||||||
|
val dirtyData = DirtyData(buildDirtyLookupSymbols, buildDirtyFqNames)
|
||||||
|
changesRegistry.registerChanges(currentBuildInfo.startTS, dirtyData)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assert(compilationMode is CompilationMode.Rebuild) { "Unexpected compilation mode: ${compilationMode::class.java}" }
|
||||||
|
changesRegistry.unknownChanges(currentBuildInfo.startTS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exitCode == ExitCode.OK) {
|
||||||
|
cacheVersions.forEach { it.saveIfNeeded() }
|
||||||
|
}
|
||||||
|
|
||||||
|
return exitCode
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@@ -351,110 +444,6 @@ class IncrementalJvmCompilerRunner(
|
|||||||
override fun compareAndUpdateCache(caches: IncrementalJvmCachesManager, generatedFiles: List<GeneratedFile>): CompilationResult =
|
override fun compareAndUpdateCache(caches: IncrementalJvmCachesManager, generatedFiles: List<GeneratedFile>): CompilationResult =
|
||||||
updateIncrementalCache(generatedFiles, caches.platformCache)
|
updateIncrementalCache(generatedFiles, caches.platformCache)
|
||||||
|
|
||||||
override fun compileIncrementally(
|
|
||||||
args: K2JVMCompilerArguments,
|
|
||||||
caches: IncrementalJvmCachesManager,
|
|
||||||
allKotlinSources: List<File>,
|
|
||||||
compilationMode: CompilationMode,
|
|
||||||
messageCollector: MessageCollector
|
|
||||||
): ExitCode {
|
|
||||||
preBuildHook(args, compilationMode)
|
|
||||||
|
|
||||||
val dirtySources = when (compilationMode) {
|
|
||||||
is CompilationMode.Incremental -> ArrayList(compilationMode.dirtyFiles)
|
|
||||||
is CompilationMode.Rebuild -> allKotlinSources.toMutableList()
|
|
||||||
}
|
|
||||||
|
|
||||||
val currentBuildInfo = BuildInfo(startTS = System.currentTimeMillis())
|
|
||||||
BuildInfo.write(currentBuildInfo, lastBuildInfoFile)
|
|
||||||
val buildDirtyLookupSymbols = HashSet<LookupSymbol>()
|
|
||||||
val buildDirtyFqNames = HashSet<FqName>()
|
|
||||||
val allSourcesToCompile = HashSet<File>()
|
|
||||||
|
|
||||||
var exitCode = ExitCode.OK
|
|
||||||
val allGeneratedFiles = hashSetOf<GeneratedFile>()
|
|
||||||
|
|
||||||
while (dirtySources.any()) {
|
|
||||||
markOutputDirty(caches, dirtySources)
|
|
||||||
caches.inputsCache.removeOutputForSourceFiles(dirtySources)
|
|
||||||
|
|
||||||
val lookupTracker = LookupTrackerImpl(LookupTracker.DO_NOTHING)
|
|
||||||
val (sourcesToCompile, removedKotlinSources) = dirtySources.partition(File::exists)
|
|
||||||
|
|
||||||
// todo: more optimal to save only last iteration, but it will require adding standalone-ic specific logs
|
|
||||||
// (because jps rebuilds all files from last build if it failed and gradle rebuilds everything)
|
|
||||||
allSourcesToCompile.addAll(sourcesToCompile)
|
|
||||||
val text = allSourcesToCompile.joinToString(separator = System.getProperty("line.separator")) { it.canonicalPath }
|
|
||||||
dirtySourcesSinceLastTimeFile.writeText(text)
|
|
||||||
|
|
||||||
val services = Services.Builder().apply {
|
|
||||||
register(LookupTracker::class.java, lookupTracker)
|
|
||||||
register(CompilationCanceledStatus::class.java, EmptyCompilationCanceledStatus)
|
|
||||||
}
|
|
||||||
|
|
||||||
args.reportOutputFiles = true
|
|
||||||
val outputItemsCollector = OutputItemsCollectorImpl()
|
|
||||||
val messageCollectorAdapter = MessageCollectorToOutputItemsCollectorAdapter(messageCollector, outputItemsCollector)
|
|
||||||
|
|
||||||
exitCode = runCompiler(sourcesToCompile.toSet(), args, caches, services, messageCollectorAdapter)
|
|
||||||
postCompilationHook(exitCode)
|
|
||||||
|
|
||||||
if (exitCode != ExitCode.OK) break
|
|
||||||
|
|
||||||
dirtySourcesSinceLastTimeFile.delete()
|
|
||||||
val generatedFiles = outputItemsCollector.outputs.map(SimpleOutputItem::toGeneratedFile)
|
|
||||||
|
|
||||||
if (compilationMode is CompilationMode.Incremental) {
|
|
||||||
// todo: feels dirty, can this be refactored?
|
|
||||||
val dirtySourcesSet = dirtySources.toHashSet()
|
|
||||||
val additionalDirtyFiles = additionalDirtyFiles(caches, generatedFiles).filter { it !in dirtySourcesSet }
|
|
||||||
if (additionalDirtyFiles.isNotEmpty()) {
|
|
||||||
dirtySources.addAll(additionalDirtyFiles)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allGeneratedFiles.addAll(generatedFiles)
|
|
||||||
caches.inputsCache.registerOutputForSourceFiles(generatedFiles)
|
|
||||||
caches.lookupCache.update(lookupTracker, sourcesToCompile, removedKotlinSources)
|
|
||||||
val compilationResult = compareAndUpdateCache(caches, generatedFiles)
|
|
||||||
|
|
||||||
if (compilationMode is CompilationMode.Rebuild) break
|
|
||||||
|
|
||||||
val (dirtyLookupSymbols, dirtyClassFqNames) = compilationResult.getDirtyData(listOf(caches.platformCache), reporter)
|
|
||||||
val compiledInThisIterationSet = sourcesToCompile.toHashSet()
|
|
||||||
|
|
||||||
with (dirtySources) {
|
|
||||||
clear()
|
|
||||||
addAll(mapLookupSymbolsToFiles(caches.lookupCache, dirtyLookupSymbols, reporter, excludes = compiledInThisIterationSet))
|
|
||||||
addAll(mapClassesFqNamesToFiles(listOf(caches.platformCache), dirtyClassFqNames, reporter, excludes = compiledInThisIterationSet))
|
|
||||||
}
|
|
||||||
|
|
||||||
buildDirtyLookupSymbols.addAll(dirtyLookupSymbols)
|
|
||||||
buildDirtyFqNames.addAll(dirtyClassFqNames)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exitCode == ExitCode.OK && compilationMode is CompilationMode.Incremental) {
|
|
||||||
buildDirtyLookupSymbols.addAll(additionalDirtyLookupSymbols())
|
|
||||||
}
|
|
||||||
if (changesRegistry != null) {
|
|
||||||
if (compilationMode is CompilationMode.Incremental) {
|
|
||||||
val dirtyData = DirtyData(buildDirtyLookupSymbols, buildDirtyFqNames)
|
|
||||||
changesRegistry.registerChanges(currentBuildInfo.startTS, dirtyData)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
assert(compilationMode is CompilationMode.Rebuild) { "Unexpected compilation mode: ${compilationMode::class.java}" }
|
|
||||||
changesRegistry.unknownChanges(currentBuildInfo.startTS)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exitCode == ExitCode.OK) {
|
|
||||||
cacheVersions.forEach { it.saveIfNeeded() }
|
|
||||||
}
|
|
||||||
|
|
||||||
return exitCode
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun additionalDirtyFiles(
|
override fun additionalDirtyFiles(
|
||||||
caches: IncrementalJvmCachesManager,
|
caches: IncrementalJvmCachesManager,
|
||||||
generatedFiles: List<GeneratedFile>
|
generatedFiles: List<GeneratedFile>
|
||||||
|
|||||||
Reference in New Issue
Block a user