external build: unified processing of forced compilation [rev by jeka]

This commit is contained in:
nik
2012-11-26 11:57:29 +04:00
parent 1a5119dd39
commit ec7e061d69
5 changed files with 49 additions and 31 deletions
@@ -149,18 +149,21 @@ public abstract class BaseCompilerTestCase extends ModuleTestCase {
return make(scope, CompilerFilter.ALL);
}
protected CompilationLog make(Module module) {
return make(getCompilerManager().createModuleCompileScope(module, false), CompilerFilter.ALL);
protected CompilationLog make(Module... modules) {
return make(getCompilerManager().createModulesCompileScope(modules, false), CompilerFilter.ALL);
}
private CompilerManager getCompilerManager() {
protected CompilationLog recompile(Module... modules) {
return compile(getCompilerManager().createModulesCompileScope(modules, false), CompilerFilter.ALL, true);
}
protected CompilerManager getCompilerManager() {
return CompilerManager.getInstance(myProject);
}
protected void assertModulesUpToDate() {
//todo[nik,jeka] uncomment this when isUpToDate become supported in external compiler
//boolean upToDate = getCompilerManager().isUpToDate(getCompilerManager().createProjectCompileScope(myProject));
//assertTrue("Modules are not up to date", upToDate);
boolean upToDate = getCompilerManager().isUpToDate(getCompilerManager().createProjectCompileScope(myProject));
assertTrue("Modules are not up to date", upToDate);
}
protected CompilationLog compile(boolean force, VirtualFile... files) {
@@ -42,22 +42,16 @@ public class BuildOperations {
if (context.isProjectRebuild()) {
FSOperations.markDirtyFiles(context, target, timestamps, true, null, null);
pd.fsState.markInitialScanPerformed(target);
configuration.save();
}
else if (context.getScope().isRecompilationForced(target) || configuration.isTargetDirty() || configuration.outputRootWasDeleted(context)) {
if (target instanceof ModuleBuildTarget) {
// Using special FSState initialization, because for correct results of "integrate" operation of JavaBuilder
// we still need to know which sources were deleted from previous compilation
initTargetFSState(context, target, true);
}
else {
IncProjectBuilder.clearOutputFiles(context, target);
pd.dataManager.cleanTargetStorages(target);
FSOperations.markDirtyFiles(context, target, timestamps, true, null, null);
}
initTargetFSState(context, target, true);
IncProjectBuilder.clearOutputFiles(context, target);
pd.dataManager.cleanTargetStorages(target);
configuration.save();
}
else if (pd.fsState.markInitialScanPerformed(target)) {
else if (!pd.fsState.isInitialScanPerformed(target)) {
initTargetFSState(context, target, false);
}
}
@@ -80,6 +74,7 @@ public class BuildOperations {
fsState.registerDeleted(target, file, timestamps);
}
}
pd.fsState.markInitialScanPerformed(target);
}
public static <R extends BuildRootDescriptor, T extends BuildTarget<R>>
@@ -113,9 +108,6 @@ public class BuildOperations {
// ensure non-incremental flag cleared
context.clearNonIncrementalMark((ModuleBuildTarget)target);
}
if (context.isProjectRebuild()) {
fsState.markInitialScanPerformed(target);
}
final Timestamps timestamps = pd.timestamps.getStorage();
for (BuildRootDescriptor rd : pd.getBuildRootIndex().getTargetRoots(target, context)) {
marked |= fsState.markAllUpToDate(context, rd, timestamps);
@@ -60,6 +60,7 @@ public class IncProjectBuilder {
private static final String CLASSPATH_INDEX_FINE_NAME = "classpath.index";
private static final boolean GENERATE_CLASSPATH_INDEX = Boolean.parseBoolean(System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION, "false"));
private static final Key<Set<BuildTarget<?>>> TARGET_WITH_CLEARED_OUTPUT = Key.create("_targets_with_cleared_output_");
private static final int MAX_BUILDER_THREADS;
static {
int maxThreads = 4;
@@ -362,11 +363,26 @@ public class IncProjectBuilder {
context.processMessage(new FileDeletedEvent(outs));
}
}
registerTargetsWithClearedOutput(context, Collections.singletonList(target));
if (dirsToDelete != null) {
FSOperations.pruneEmptyDirs(context, dirsToDelete);
}
}
private static void registerTargetsWithClearedOutput(CompileContext context, Collection<? extends BuildTarget<?>> targets) {
Set<BuildTarget<?>> data = context.getUserData(TARGET_WITH_CLEARED_OUTPUT);
if (data == null) {
data = new THashSet<BuildTarget<?>>();
context.putUserData(TARGET_WITH_CLEARED_OUTPUT, data);
}
data.addAll(targets);
}
private static boolean isTargetOutputCleared(CompileContext context, BuildTarget<?> target) {
Set<BuildTarget<?>> data = context.getUserData(TARGET_WITH_CLEARED_OUTPUT);
return data != null && data.contains(target);
}
private void clearOutputs(CompileContext context) throws ProjectBuildException, IOException {
final MultiMap<File, BuildTarget<?>> rootsToDelete = new MultiMapBasedOnSet<File, BuildTarget<?>>();
final Set<File> allSourceRoots = new HashSet<File>();
@@ -417,6 +433,7 @@ public class IncProjectBuilder {
else if (outputRoot.isFile()) {
filesToDelete.add(outputRoot);
}
registerTargetsWithClearedOutput(context, entry.getValue());
}
else {
context.processMessage(new CompilerMessage(
@@ -594,13 +611,11 @@ public class IncProjectBuilder {
}
private void buildTargetsChunk(CompileContext context, final BuildTargetChunk chunk) throws ProjectBuildException {
boolean doneSomething = false;
boolean doneSomething;
try {
Utils.ERRORS_DETECTED_KEY.set(context, Boolean.FALSE);
BuildOperations.ensureFSStateInitialized(context, chunk);
if (context.isMake()) {
doneSomething = processDeletedPaths(context, chunk.getTargets());
}
doneSomething = processDeletedPaths(context, chunk.getTargets());
myProjectDescriptor.fsState.beforeChunkBuildStart(context, chunk);
@@ -696,11 +711,16 @@ public class IncProjectBuilder {
final THashSet<File> dirsToDelete = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
for (BuildTarget<?> target : targets) {
final Collection<String> deletedPaths = myProjectDescriptor.fsState.getAndClearDeletedPaths(target);
if (deletedPaths.isEmpty()) {
continue;
}
targetToRemovedSources.put(target, deletedPaths);
if (isTargetOutputCleared(context, target)) {
continue;
}
final boolean shouldPruneEmptyDirs = target instanceof ModuleBasedTarget;
final SourceToOutputMapping sourceToOutputStorage = context.getProjectDescriptor().dataManager.getSourceToOutputMap(target);
final ProjectBuilderLogger logger = context.getLoggingManager().getProjectBuilderLogger();
@@ -821,9 +841,7 @@ public class IncProjectBuilder {
}
for (ModuleLevelBuilder builder : builders) {
if (context.isMake()) {
processDeletedPaths(context, chunk.getTargets());
}
processDeletedPaths(context, chunk.getTargets());
final ModuleLevelBuilder.ExitCode buildResult = builder.build(context, chunk, dirtyFilesHolder, outputConsumer);
doneSomething |= (buildResult != ModuleLevelBuilder.ExitCode.NOTHING_DONE);
@@ -953,6 +971,7 @@ public class IncProjectBuilder {
// keys for data that must be visible to all threads
GLOBAL_CONTEXT_KEYS.add(ExternalJavacDescriptor.KEY);
GLOBAL_CONTEXT_KEYS.add(FSOperations.ALL_OUTPUTS_KEY);
GLOBAL_CONTEXT_KEYS.add(TARGET_WITH_CLEARED_OUTPUT);
}
private static CompileContext createContextWrapper(final CompileContext delegate) {
@@ -43,8 +43,8 @@ public class BuildFSState extends FSState {
}
@Override
public boolean markInitialScanPerformed(BuildTarget<?> target) {
return myAlwaysScanFS || super.markInitialScanPerformed(target);
public boolean isInitialScanPerformed(BuildTarget<?> target) {
return !myAlwaysScanFS && super.isInitialScanPerformed(target);
}
@Override
@@ -160,7 +160,11 @@ public class FSState {
return delta != null && delta.hasChanges();
}
public boolean markInitialScanPerformed(BuildTarget<?> target) {
return myInitialScanPerformed.add(target);
public void markInitialScanPerformed(BuildTarget<?> target) {
myInitialScanPerformed.add(target);
}
public boolean isInitialScanPerformed(BuildTarget<?> target) {
return myInitialScanPerformed.contains(target);
}
}