@@ -456,6 +456,69 @@ 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+ DepGraph.markTransitive (Dependents, FinishedCmd);
487+ break ;
488+ }
489+ } else {
490+ // If there's a crash, assume the worst.
491+ switch (FinishedCmd->getCondition ()) {
492+ case Job::Condition::NewlyAdded:
493+ // The job won't be treated as newly added next time. Conservatively
494+ // mark it as affecting other jobs, because some of them may have
495+ // completed already.
496+ DepGraph.markTransitive (Dependents, FinishedCmd);
497+ break ;
498+ case Job::Condition::Always:
499+ // This applies to non-incremental tasks as well, but any incremental
500+ // task that shows up here has already been marked.
501+ break ;
502+ case Job::Condition::RunWithoutCascading:
503+ // If this file changed, it might have been a non-cascading change and
504+ // it might not. Unfortunately, the interface hash has been updated or
505+ // compromised, so we don't actually know anymore; we have to
506+ // conservatively assume the changes could affect other files.
507+ DepGraph.markTransitive (Dependents, FinishedCmd);
508+ break ;
509+ case Job::Condition::CheckDependencies:
510+ // If the only reason we're running this is because something else
511+ // changed, then we can trust the dependency graph as to whether it's
512+ // a cascading or non-cascading change. That is, if whatever /caused/
513+ // the error isn't supposed to affect other files, and whatever
514+ // /fixes/ the error isn't supposed to affect other files, then
515+ // there's no need to recompile any other inputs. If either of those
516+ // are false, we /do/ need to recompile other inputs.
517+ break ;
518+ }
519+ }
520+ }
521+
459522 if (ReturnCode != EXIT_SUCCESS) {
460523 // The task failed, so return true without performing any further
461524 // dependency analysis.
@@ -481,39 +544,10 @@ int Compilation::performJobsImpl() {
481544 // might have been blocked.
482545 markFinished (FinishedCmd);
483546
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- }
547+ for (const Job *Cmd : Dependents) {
548+ DeferredCommands.erase (Cmd);
549+ noteBuilding (Cmd, " because of dependencies discovered later" );
550+ scheduleCommandIfNecessaryAndPossible (Cmd);
517551 }
518552
519553 return TaskFinishedResponse::ContinueExecution;
0 commit comments