@@ -456,6 +456,70 @@ int Compilation::performJobsImpl() {
456456 llvm::errs () << Output;
457457 }
458458
459+ // In order to handle both old dependencies that have disappeared and new
460+ // dependencies that have arisen, we need to reload the dependency file.
461+ // Do this whether or not the build succeeded.
462+ SmallVector<const Job *, 16 > Dependents;
463+ if (getIncrementalBuildEnabled ()) {
464+ const CommandOutput &Output = FinishedCmd->getOutput ();
465+ StringRef DependenciesFile =
466+ Output.getAdditionalOutputForType (types::TY_SwiftDeps);
467+ if (!DependenciesFile.empty () &&
468+ (ReturnCode == EXIT_SUCCESS || ReturnCode == EXIT_FAILURE)) {
469+ bool wasCascading = DepGraph.isMarked (FinishedCmd);
470+
471+ switch (DepGraph.loadFromPath (FinishedCmd, DependenciesFile)) {
472+ case DependencyGraphImpl::LoadResult::HadError:
473+ if (ReturnCode == EXIT_SUCCESS) {
474+ disableIncrementalBuild ();
475+ for (const Job *Cmd : DeferredCommands)
476+ scheduleCommandIfNecessaryAndPossible (Cmd);
477+ DeferredCommands.clear ();
478+ Dependents.clear ();
479+ } // else, let the next build handle it.
480+ break ;
481+ case DependencyGraphImpl::LoadResult::UpToDate:
482+ if (!wasCascading)
483+ break ;
484+ SWIFT_FALLTHROUGH;
485+ case DependencyGraphImpl::LoadResult::AffectsDownstream:
486+ llvm::errs () << " DOWNSTREAM " << ReturnCode << " \n " ;
487+ DepGraph.markTransitive (Dependents, FinishedCmd);
488+ break ;
489+ }
490+ } else {
491+ // If there's a crash, assume the worst.
492+ switch (FinishedCmd->getCondition ()) {
493+ case Job::Condition::NewlyAdded:
494+ // The job won't be treated as newly added next time. Conservatively
495+ // mark it as affecting other jobs, because some of them may have
496+ // completed already.
497+ DepGraph.markTransitive (Dependents, FinishedCmd);
498+ break ;
499+ case Job::Condition::Always:
500+ // This applies to non-incremental tasks as well, but any incremental
501+ // task that shows up here has already been marked.
502+ break ;
503+ case Job::Condition::RunWithoutCascading:
504+ // If this file changed, it might have been a non-cascading change and
505+ // it might not. Unfortunately, the interface hash has been updated or
506+ // compromised, so we don't actually know anymore; we have to
507+ // conservatively assume the changes could affect other files.
508+ DepGraph.markTransitive (Dependents, FinishedCmd);
509+ break ;
510+ case Job::Condition::CheckDependencies:
511+ // If the only reason we're running this is because something else
512+ // changed, then we can trust the dependency graph as to whether it's
513+ // a cascading or non-cascading change. That is, if whatever /caused/
514+ // the error isn't supposed to affect other files, and whatever
515+ // /fixes/ the error isn't supposed to affect other files, then
516+ // there's no need to recompile any other inputs. If either of those
517+ // are false, we /do/ need to recompile other inputs.
518+ break ;
519+ }
520+ }
521+ }
522+
459523 if (ReturnCode != EXIT_SUCCESS) {
460524 // The task failed, so return true without performing any further
461525 // dependency analysis.
@@ -481,39 +545,10 @@ int Compilation::performJobsImpl() {
481545 // might have been blocked.
482546 markFinished (FinishedCmd);
483547
484- // In order to handle both old dependencies that have disappeared and new
485- // dependencies that have arisen, we need to reload the dependency file.
486- if (getIncrementalBuildEnabled ()) {
487- const CommandOutput &Output = FinishedCmd->getOutput ();
488- StringRef DependenciesFile =
489- Output.getAdditionalOutputForType (types::TY_SwiftDeps);
490- if (!DependenciesFile.empty ()) {
491- SmallVector<const Job *, 16 > Dependents;
492- bool wasCascading = DepGraph.isMarked (FinishedCmd);
493-
494- switch (DepGraph.loadFromPath (FinishedCmd, DependenciesFile)) {
495- case DependencyGraphImpl::LoadResult::HadError:
496- disableIncrementalBuild ();
497- for (const Job *Cmd : DeferredCommands)
498- scheduleCommandIfNecessaryAndPossible (Cmd);
499- DeferredCommands.clear ();
500- Dependents.clear ();
501- break ;
502- case DependencyGraphImpl::LoadResult::UpToDate:
503- if (!wasCascading)
504- break ;
505- SWIFT_FALLTHROUGH;
506- case DependencyGraphImpl::LoadResult::AffectsDownstream:
507- DepGraph.markTransitive (Dependents, FinishedCmd);
508- break ;
509- }
510-
511- for (const Job *Cmd : Dependents) {
512- DeferredCommands.erase (Cmd);
513- noteBuilding (Cmd, " because of dependencies discovered later" );
514- scheduleCommandIfNecessaryAndPossible (Cmd);
515- }
516- }
548+ for (const Job *Cmd : Dependents) {
549+ DeferredCommands.erase (Cmd);
550+ noteBuilding (Cmd, " because of dependencies discovered later" );
551+ scheduleCommandIfNecessaryAndPossible (Cmd);
517552 }
518553
519554 return TaskFinishedResponse::ContinueExecution;
0 commit comments