Baby steps for incremental compilation.

This commit is contained in:
Evgeny Gerashchenko
2014-01-22 23:38:57 +04:00
parent 9e22c29825
commit 5acd054c72
16 changed files with 226 additions and 19 deletions
@@ -16,9 +16,12 @@
package org.jetbrains.jet.jps.build;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.cli.common.KotlinVersion;
import org.jetbrains.jet.cli.common.arguments.CommonCompilerArguments;
@@ -46,6 +49,7 @@ import org.jetbrains.jps.model.JpsProject;
import org.jetbrains.jps.model.module.JpsModule;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
@@ -58,8 +62,9 @@ import static org.jetbrains.jet.compiler.runner.KotlinCompilerRunner.runK2JsComp
import static org.jetbrains.jet.compiler.runner.KotlinCompilerRunner.runK2JvmCompiler;
public class KotlinBuilder extends ModuleLevelBuilder {
private static final Key<Set<File>> ALL_COMPILED_FILES_KEY = Key.create("_all_kotlin_compiled_files_");
private static final String KOTLIN_BUILDER_NAME = "Kotlin Builder";
public static final String KOTLIN_BUILDER_NAME = "Kotlin Builder";
private static final List<String> COMPILABLE_FILE_EXTENSIONS = Collections.singletonList("kt");
private static final Function<JpsModule,String> MODULE_NAME = new Function<JpsModule, String>() {
@@ -122,6 +127,8 @@ public class KotlinBuilder extends ModuleLevelBuilder {
CommonCompilerArguments commonArguments = JpsKotlinCompilerSettings.getCommonCompilerArguments(project);
CompilerSettings compilerSettings = JpsKotlinCompilerSettings.getCompilerSettings(project);
final Set<File> allCompiledFiles = getAllCompiledFilesContainer(context);
if (JpsUtils.isJsKotlinModule(representativeTarget)) {
if (chunk.getModules().size() > 1) {
// We do not support circular dependencies, but if they are present, we do our best should not break the build,
@@ -134,7 +141,7 @@ public class KotlinBuilder extends ModuleLevelBuilder {
return ExitCode.NOTHING_DONE;
}
List<File> sourceFiles = KotlinSourceFileCollector.getAllKotlinSourceFiles(representativeTarget);
Collection<File> sourceFiles = KotlinSourceFileCollector.getAllKotlinSourceFiles(representativeTarget);
//List<File> sourceFiles = KotlinSourceFileCollector.getDirtySourceFiles(dirtyFilesHolder);
if (sourceFiles.isEmpty()) {
@@ -157,7 +164,11 @@ public class KotlinBuilder extends ModuleLevelBuilder {
NO_LOCATION);
}
File moduleFile = KotlinBuilderModuleScriptGenerator.generateModuleDescription(context, chunk);
List<File> filesToCompile = KotlinSourceFileCollector.getDirtySourceFiles(dirtyFilesHolder);
filesToCompile.removeAll(allCompiledFiles);
allCompiledFiles.addAll(filesToCompile);
File moduleFile = KotlinBuilderModuleScriptGenerator.generateModuleDescription(context, chunk, filesToCompile);
if (moduleFile == null) {
// No Kotlin sources found
return ExitCode.NOTHING_DONE;
@@ -192,13 +203,29 @@ public class KotlinBuilder extends ModuleLevelBuilder {
outputConsumer.registerOutputFile(target != null ? target : representativeTarget, outputItem.getOutputFile(), paths(sourceFiles));
}
return ExitCode.OK;
// TODO should mark dependencies as dirty, as well
FSOperations.markDirty(context, chunk, new FileFilter() {
@Override
public boolean accept(@NotNull File file) {
return !allCompiledFiles.contains(file);
}
});
return ExitCode.ADDITIONAL_PASS_REQUIRED;
}
private static Set<File> getAllCompiledFilesContainer(CompileContext context) {
Set<File> allCompiledFiles = ALL_COMPILED_FILES_KEY.get(context);
if (allCompiledFiles == null) {
allCompiledFiles = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
ALL_COMPILED_FILES_KEY.set(context, allCompiledFiles);
}
return allCompiledFiles;
}
private static boolean hasKotlinFiles(@NotNull ModuleChunk chunk) {
boolean hasKotlinFiles = false;
for (ModuleBuildTarget target : chunk.getTargets()) {
List<File> sourceFiles = KotlinSourceFileCollector.getAllKotlinSourceFiles(target);
Collection<File> sourceFiles = KotlinSourceFileCollector.getAllKotlinSourceFiles(target);
if (!sourceFiles.isEmpty()) {
hasKotlinFiles = true;
break;
@@ -25,6 +25,7 @@ import org.jetbrains.jet.compiler.runner.KotlinModuleDescriptionBuilderFactory;
import org.jetbrains.jet.compiler.runner.KotlinModuleXmlBuilderFactory;
import org.jetbrains.jps.ModuleChunk;
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
import org.jetbrains.jps.incremental.CompileContext;
import org.jetbrains.jps.incremental.ModuleBuildTarget;
import org.jetbrains.jps.incremental.messages.BuildMessage;
@@ -52,7 +53,11 @@ public class KotlinBuilderModuleScriptGenerator {
public static final KotlinModuleDescriptionBuilderFactory FACTORY = KotlinModuleXmlBuilderFactory.INSTANCE;
@Nullable
public static File generateModuleDescription(CompileContext context, ModuleChunk chunk)
public static File generateModuleDescription(
CompileContext context,
ModuleChunk chunk,
List<File> sourceFiles
)
throws IOException
{
KotlinModuleDescriptionBuilder builder = FACTORY.create();
@@ -63,11 +68,17 @@ public class KotlinBuilderModuleScriptGenerator {
for (ModuleBuildTarget target : chunk.getTargets()) {
outputDirs.add(getOutputDir(target));
}
ProjectBuilderLogger logger = context.getLoggingManager().getProjectBuilderLogger();
for (ModuleBuildTarget target : chunk.getTargets()) {
File outputDir = getOutputDir(target);
List<File> sourceFiles = KotlinSourceFileCollector.getAllKotlinSourceFiles(target);
noSources &= sourceFiles.isEmpty();
if (sourceFiles.size() > 0) {
noSources = false;
if (logger.isEnabled()) {
logger.logCompiledFiles(sourceFiles, KotlinBuilder.KOTLIN_BUILDER_NAME, "Compiling files:");
}
}
builder.addModule(
target.getId(),