Added incremental cache format versioning.

Original commit: 954a011721
This commit is contained in:
Evgeny Gerashchenko
2014-09-24 19:35:19 +04:00
parent 2462b95e6b
commit 07d79c88f5
12 changed files with 148 additions and 13 deletions
@@ -51,6 +51,7 @@ import org.jetbrains.jet.compiler.runner.KotlinCompilerRunner.runK2JvmCompiler
import org.jetbrains.jet.utils.keysToMap
import org.jetbrains.jps.incremental.ModuleLevelBuilder.ExitCode.*
import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.jet.lang.resolve.java.JvmAbi
public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR) {
class object {
@@ -83,6 +84,16 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
val representativeTarget = chunk.representativeTarget()
val outputDir = representativeTarget.getOutputDir()
val dataManager = context.getProjectDescriptor().dataManager
val incrementalCaches = chunk.getTargets().keysToMap { dataManager.getStorage(it, IncrementalCacheStorageProvider) }
if (incrementalCaches.values().any { it -> it.isCacheVersionIncompatible() }) {
incrementalCaches.values().forEach { it.clean() }
return CHUNK_REBUILD_REQUIRED
}
// For non-incremental build: take all sources
if (!dirtyFilesHolder.hasDirtyFiles() && !dirtyFilesHolder.hasRemovedFiles()) {
return NOTHING_DONE
@@ -94,11 +105,6 @@ public class KotlinBuilder : ModuleLevelBuilder(BuilderCategory.SOURCE_PROCESSOR
messageCollector.report(INFO, "Kotlin JPS plugin version " + KotlinVersion.VERSION, NO_LOCATION)
val outputDir = representativeTarget.getOutputDir()
val dataManager = context.getProjectDescriptor().dataManager
val incrementalCaches = chunk.getTargets().keysToMap { dataManager.getStorage(it, IncrementalCacheStorageProvider) }
val compilerServices = Services.Builder()
.register(javaClass<IncrementalCacheProvider>(), IncrementalCacheProviderImpl(incrementalCaches))
.build()
@@ -40,15 +40,25 @@ import java.security.MessageDigest
import org.jetbrains.jps.incremental.storage.StorageOwner
import org.jetbrains.jps.builders.storage.StorageProvider
import java.io.IOException
import java.util.Scanner
import org.jetbrains.jet.lang.resolve.java.JvmAbi
val INLINE_ANNOTATION_DESC = "Lkotlin/inline;"
public class IncrementalCacheImpl(val baseDir: File): StorageOwner, IncrementalCache {
class object {
val DIRECTORY_NAME = "kotlin"
val PROTO_MAP = "proto.tab"
val CONSTANTS_MAP = "constants.tab"
val INLINE_FUNCTIONS = "inline-functions.tab"
val PACKAGE_PARTS = "package-parts.tab"
// Change this when incremental cache format changes
private val INCREMENTAL_CACHE_OWN_VERSION = 1
public val CACHE_FORMAT_VERSION: Int = INCREMENTAL_CACHE_OWN_VERSION * 1000000 + JvmAbi.VERSION
val FORMAT_VERSION_TXT = "format-version.txt"
}
private val protoMap = ProtoMap()
@@ -58,8 +68,34 @@ public class IncrementalCacheImpl(val baseDir: File): StorageOwner, IncrementalC
private val maps = listOf(protoMap, constantsMap, inlineFunctionsMap, packagePartMap)
private fun getFormatVersionFile(): File {
return File(baseDir, FORMAT_VERSION_TXT)
}
public fun isCacheVersionIncompatible(): Boolean {
val version = loadCacheFormatVersion()
return version != -1 && version != CACHE_FORMAT_VERSION
}
private fun loadCacheFormatVersion(): Int {
val versionFile = getFormatVersionFile()
if (!versionFile.exists()) return -1
return versionFile.readText().toInt()
}
private fun saveCacheFormatVersionIfNeeded() {
val versionFile = getFormatVersionFile()
if (!versionFile.exists()) {
versionFile.writeText(CACHE_FORMAT_VERSION.toString())
}
}
public fun saveFileToCache(sourceFiles: Collection<File>, classFile: File): RecompilationDecision {
if (classFile.extension.toLowerCase() != "class") return DO_NOTHING
saveCacheFormatVersionIfNeeded()
val kotlinClass = LocalFileKotlinClass.create(classFile)
if (kotlinClass == null) return DO_NOTHING
@@ -121,6 +157,7 @@ public class IncrementalCacheImpl(val baseDir: File): StorageOwner, IncrementalC
public override fun clean() {
maps.forEach { it.clean() }
getFormatVersionFile().delete()
}
public override fun close() {
@@ -457,7 +494,7 @@ public class IncrementalCacheImpl(val baseDir: File): StorageOwner, IncrementalC
public object IncrementalCacheStorageProvider : StorageProvider<IncrementalCacheImpl>() {
override fun createStorage(targetDataDir: File?): IncrementalCacheImpl {
return IncrementalCacheImpl(File(targetDataDir, "kotlin"))
return IncrementalCacheImpl(File(targetDataDir, IncrementalCacheImpl.DIRECTORY_NAME))
}
}
@@ -50,6 +50,9 @@ public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() {
super.tearDown()
}
protected open val customTest: Boolean
get() = false
fun buildGetLog(scope: CompileScopeTestBuilder = CompileScopeTestBuilder.make().all()): String {
val logger = MyLogger(FileUtil.toSystemIndependentName(workDir.getAbsolutePath()))
val descriptor = createProjectDescriptor(BuildLoggingManager(logger))
@@ -119,7 +122,12 @@ public abstract class AbstractIncrementalJpsTest : JpsBuildTestCase() {
fail("Bad test data format: files ending with both unnumbered and numbered \".new\"/\".delete\" were found")
}
if (!haveFilesWithoutNumbers && !haveFilesWithNumbers) {
fail("Bad test data format: no files ending with \".new\" or \".delete\" found")
if (customTest) {
return listOf(listOf())
}
else {
fail("Bad test data format: no files ending with \".new\" or \".delete\" found")
}
}
if (haveFilesWithoutNumbers) {
@@ -0,0 +1,50 @@
/*
* Copyright 2010-2014 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.jet.jps.build
import com.intellij.testFramework.TestDataPath
import org.jetbrains.jet.JetTestUtils
import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.jps.builders.impl.BuildDataPathsImpl
import java.io.File
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType
import org.jetbrains.jet.jps.incremental
import com.sun.tools.javac.resources.version
import org.jetbrains.jet.jps.incremental.IncrementalCacheImpl
import kotlin.test.assertTrue
public class IncrementalCacheVersionChangedTest : AbstractIncrementalJpsTest() {
fun testCacheVersionChanged() {
doTest("jps-plugin/testData/incremental/custom/cacheVersionChanged/")
}
fun testCacheVersionChangedAndFileModified() {
doTest("jps-plugin/testData/incremental/custom/cacheVersionChangedAndFileModified/")
}
override val customTest: Boolean
get() = true
override fun performAdditionalModifications() {
val storageForTargetType = BuildDataPathsImpl(myDataStorageRoot).getTargetTypeDataRoot(JavaModuleBuildTargetType.PRODUCTION)
val relativePath = "module/${File.separator}${IncrementalCacheImpl.DIRECTORY_NAME}/${IncrementalCacheImpl.FORMAT_VERSION_TXT}"
val cacheVersionFile = File(storageForTargetType, relativePath)
assertTrue(cacheVersionFile.exists())
cacheVersionFile.writeText("777")
}
}
@@ -30,15 +30,9 @@ import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("jps-plugin/testData/incremental")
@TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({IncrementalJpsTestGenerated.CircularDependency.class, IncrementalJpsTestGenerated.PureKotlin.class})
@RunWith(org.jetbrains.jet.JUnit3RunnerWithInners.class)
public class IncrementalJpsTestGenerated extends AbstractIncrementalJpsTest {
public void testAllFilesPresentInIncremental() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("jps-plugin/testData/incremental"), Pattern.compile("^([^\\.]+)$"), true);
}
@TestMetadata("jps-plugin/testData/incremental/circularDependency")
@TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({})
@@ -0,0 +1,4 @@
package test
fun f() {
}
@@ -0,0 +1,4 @@
package test
fun g() {
}
@@ -0,0 +1,9 @@
Cleaning output files:
out/production/module/test/TestPackage$a$*.class
out/production/module/test/TestPackage$b$*.class
out/production/module/test/TestPackage.class
End of files
Compiling files:
src/a.kt
src/b.kt
End of files
@@ -0,0 +1,4 @@
package test
fun f() {
}
@@ -0,0 +1,4 @@
package test
fun g() {
}
@@ -0,0 +1,4 @@
package test
fun g() {
}
@@ -0,0 +1,11 @@
Cleaning output files:
out/production/module/test/TestPackage$b$*.class
out/production/module/test/TestPackage.class
End of files
Cleaning output files:
out/production/module/test/TestPackage$a$*.class
End of files
Compiling files:
src/a.kt
src/b.kt
End of files