Fix multiproject Gradle IC with daemon

This commit is contained in:
Alexey Tsvetkov
2016-12-06 17:34:43 +03:00
parent fb869277d9
commit 8228d5828e
14 changed files with 235 additions and 45 deletions
@@ -32,8 +32,8 @@ import org.jetbrains.kotlin.compilerRunner.OutputItemsCollector
import org.jetbrains.kotlin.compilerRunner.OutputItemsCollectorImpl
import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifference
import org.jetbrains.kotlin.incremental.multiproject.ArtifactDifferenceRegistryProvider
import org.jetbrains.kotlin.incremental.multiproject.ArtifactChangesProvider
import org.jetbrains.kotlin.incremental.multiproject.ChangesRegistry
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.modules.TargetId
import org.jetbrains.kotlin.name.FqName
@@ -92,8 +92,8 @@ class IncrementalJvmCompilerRunner(
private val cacheVersions: List<CacheVersion>,
private val reporter: ICReporter,
private var kaptAnnotationsFileUpdater: AnnotationFileUpdater? = null,
private val artifactDifferenceRegistryProvider: ArtifactDifferenceRegistryProvider? = null,
private val artifactFile: File? = null
private val artifactChangesProvider: ArtifactChangesProvider? = null,
private val changesRegistry: ChangesRegistry? = null
) {
var anyClassesCompiled: Boolean = false
private set
@@ -112,7 +112,6 @@ class IncrementalJvmCompilerRunner(
fun onError(e: Exception): ExitCode {
caches.clean()
artifactDifferenceRegistryProvider?.clean()
// todo: warn?
reporter.report { "Possible cache corruption. Rebuilding. $e" }
@@ -135,9 +134,6 @@ class IncrementalJvmCompilerRunner(
onError(e)
}
finally {
artifactDifferenceRegistryProvider?.withRegistry(reporter) {
it.flush(memoryCachesOnly = true)
}
caches.close(flush = true)
reporter.report { "flushed incremental caches" }
}
@@ -227,10 +223,6 @@ class IncrementalJvmCompilerRunner(
reporter.report {"No classpath changes"}
return ChangesEither.Known()
}
if (artifactDifferenceRegistryProvider == null) {
reporter.report {"No artifact history provider"}
return ChangesEither.Unknown()
}
val lastBuildTS = lastBuildInfo?.startTS
if (lastBuildTS == null) {
@@ -241,23 +233,16 @@ class IncrementalJvmCompilerRunner(
val symbols = HashSet<LookupSymbol>()
val fqNames = HashSet<FqName>()
for (file in modifiedClasspath) {
val diffs = artifactDifferenceRegistryProvider.withRegistry(reporter) {artifactDifferenceRegistry ->
artifactDifferenceRegistry[file]
}
val diffs = artifactChangesProvider?.getChanges(file, lastBuildTS)
if (diffs == null) {
reporter.report {"Could not get changes for file: $file"}
return ChangesEither.Unknown()
}
val (beforeLastBuild, afterLastBuild) = diffs.partition {it.buildTS < lastBuildTS}
if (beforeLastBuild.isEmpty()) {
reporter.report {"No known build preceding timestamp $lastBuildTS for file $file"}
return ChangesEither.Unknown()
}
afterLastBuild.forEach {
symbols.addAll(it.dirtyData.dirtyLookupSymbols)
fqNames.addAll(it.dirtyData.dirtyClassesFqNames)
diffs.forEach {
symbols.addAll(it.dirtyLookupSymbols)
fqNames.addAll(it.dirtyClassesFqNames)
}
}
@@ -295,7 +280,6 @@ class IncrementalJvmCompilerRunner(
@Suppress("NAME_SHADOWING")
var compilationMode = compilationMode
reporter.report { "Artifact to register difference for: $artifactFile" }
val currentBuildInfo = BuildInfo(startTS = System.currentTimeMillis())
BuildInfo.write(currentBuildInfo, lastBuildInfoFile)
val buildDirtyLookupSymbols = HashSet<LookupSymbol>()
@@ -347,11 +331,6 @@ class IncrementalJvmCompilerRunner(
caches.lookupCache.update(lookupTracker, sourcesToCompile, removedKotlinSources)
if (compilationMode is CompilationMode.Rebuild) {
artifactFile?.let { artifactFile ->
artifactDifferenceRegistryProvider?.withRegistry(reporter) { registry ->
registry.remove(artifactFile)
}
}
break
}
@@ -371,16 +350,14 @@ class IncrementalJvmCompilerRunner(
if (exitCode == ExitCode.OK && compilationMode is CompilationMode.Incremental) {
buildDirtyLookupSymbols.addAll(javaFilesProcessor.allChangedSymbols)
}
if (artifactFile != null && artifactDifferenceRegistryProvider != null) {
val dirtyData = DirtyData(buildDirtyLookupSymbols, buildDirtyFqNames)
val artifactDifference = ArtifactDifference(currentBuildInfo.startTS, dirtyData)
artifactDifferenceRegistryProvider.withRegistry(reporter) {registry ->
registry.add(artifactFile, artifactDifference)
if (changesRegistry != null) {
if (compilationMode is CompilationMode.Incremental) {
val dirtyData = DirtyData(buildDirtyLookupSymbols, buildDirtyFqNames)
changesRegistry.registerChanges(currentBuildInfo.startTS, dirtyData)
}
reporter.report {
val dirtySymbolsSorted = buildDirtyLookupSymbols.map { it.scope + "#" + it.name }.sorted()
"Added artifact difference for $artifactFile (ts: ${currentBuildInfo.startTS}): " +
"[\n\t${dirtySymbolsSorted.joinToString(",\n\t")}]"
else {
assert(compilationMode is CompilationMode.Rebuild) { "Unexpected compilation mode: ${compilationMode.javaClass}" }
changesRegistry.unknownChanges(currentBuildInfo.startTS)
}
}
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental.multiproject
import org.jetbrains.kotlin.incremental.DirtyData
import java.io.File
interface ArtifactChangesProvider {
fun getChanges(artifact: File, sinceTS: Long): Iterable<DirtyData>?
}
@@ -1,46 +0,0 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental.multiproject
import org.jetbrains.kotlin.incremental.DirtyData
import org.jetbrains.kotlin.incremental.ICReporter
import java.io.File
interface ArtifactDifferenceRegistry {
operator fun get(artifact: File): Iterable<ArtifactDifference>?
fun add(artifact: File, difference: ArtifactDifference)
fun remove(artifact: File)
fun flush(memoryCachesOnly: Boolean)
}
class ArtifactDifference(val buildTS: Long, val dirtyData: DirtyData)
interface ArtifactDifferenceRegistryProvider {
fun <T> withRegistry(
report: (String) -> Unit,
fn: (ArtifactDifferenceRegistry) -> T
): T?
fun <T> withRegistry(
reporter: ICReporter,
fn: (ArtifactDifferenceRegistry) -> T
): T? {
return withRegistry({reporter.report {it}}, fn)
}
fun clean()
}
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.incremental.multiproject
import org.jetbrains.kotlin.incremental.DirtyData
interface ChangesRegistry {
fun registerChanges(timestamp: Long, dirtyData: DirtyData)
fun unknownChanges(timestamp: Long)
}