Skip to content

Commit e35f060

Browse files
committed
Install Incremental External Dependency Integration Code
An incremental build involving incremental external dependencies behaves as a hybrid between an external dependency and a normal swiftdeps-laden Swift file. In the simplest case, we will fall back to the behavior of a plain external dependency today. That is, we will check its timestamp, then schedule all jobs that involve these external dependencies if it is out of date. Where things get interesting is when cross-module incremental builds are enabled. In such a case, we know that a previous compiler has already emitted serialized swiftdeps information inside of a swiftmodule file. Moreover, we know that that swiftmodule file was loaded by the build of the current swift module. Finally, thanks to the previous stack of commits, we now know exactly how to extract this information from the swiftmodule file. To bring this all home, we unpack incremental dependency information from external dependencies, then integrate them into the current dependency graph - as though they were any other swiftdeps file. This neatly extends the single-module incremental logic to the multi-module case.
1 parent 7917d72 commit e35f060

File tree

1 file changed

+68
-26
lines changed

1 file changed

+68
-26
lines changed

lib/Driver/Compilation.cpp

Lines changed: 68 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,21 +1113,6 @@ namespace driver {
11131113
}
11141114
}
11151115

1116-
void forEachOutOfDateIncrementalExternalDependency(
1117-
const bool forRanges,
1118-
function_ref<void(StringRef)> consumeExternalSwiftDeps) {
1119-
for (StringRef dependency :
1120-
getIncrementalExternalDependencies(forRanges)) {
1121-
// If the dependency has been modified since the oldest built file,
1122-
// or if we can't stat it for some reason (perhaps it's been
1123-
// deleted?), trigger rebuilds through the dependency graph.
1124-
llvm::sys::fs::file_status depStatus;
1125-
if (llvm::sys::fs::status(dependency, depStatus) ||
1126-
Comp.getLastBuildTime() < depStatus.getLastModificationTime())
1127-
consumeExternalSwiftDeps(dependency);
1128-
}
1129-
}
1130-
11311116
CommandSet collectCascadedJobsFromDependencyGraph(
11321117
const CommandSet &InitialCascadingCommands, const bool forRanges) {
11331118
CommandSet CascadedJobs;
@@ -1164,18 +1149,68 @@ namespace driver {
11641149
collectIncrementalExternallyDependentJobsFromDependencyGraph(
11651150
const bool forRanges) {
11661151
SmallVector<const Job *, 16> ExternallyDependentJobs;
1167-
// Check all cross-module dependencies as well.
1168-
forEachOutOfDateIncrementalExternalDependency(
1169-
forRanges, [&](StringRef dependency) {
1170-
// If the dependency has been modified since the oldest built file,
1171-
// or if we can't stat it for some reason (perhaps it's been
1172-
// deleted?), trigger rebuilds through the dependency graph.
1173-
for (const Job *marked :
1174-
markExternalInDepGraph(dependency, forRanges))
1175-
ExternallyDependentJobs.push_back(marked);
1176-
});
1152+
auto fallbackToExternalBehavior = [&](StringRef external) {
1153+
for (const auto cmd :
1154+
markIncrementalExternalInDepGraph(external, forRanges)) {
1155+
ExternallyDependentJobs.push_back(cmd);
1156+
}
1157+
};
1158+
1159+
for (auto external : getFineGrainedDepGraph(forRanges)
1160+
.getIncrementalExternalDependencies()) {
1161+
llvm::sys::fs::file_status depStatus;
1162+
// Can't `stat` this dependency? Treat it as a plain external
1163+
// dependency and drop schedule all of its consuming jobs to run.
1164+
if (llvm::sys::fs::status(external, depStatus)) {
1165+
fallbackToExternalBehavior(external);
1166+
continue;
1167+
}
1168+
1169+
// Is this module out of date? If not, just keep searching.
1170+
if (Comp.getLastBuildTime() >= depStatus.getLastModificationTime())
1171+
continue;
1172+
1173+
// Can we run a cross-module incremental build at all? If not, fallback.
1174+
if (!Comp.getEnableCrossModuleIncrementalBuild()) {
1175+
fallbackToExternalBehavior(external);
1176+
continue;
1177+
}
1178+
1179+
// If loading the buffer fails, the user may have deleted this external
1180+
// dependency or it could have become corrupted. We need to
1181+
// pessimistically schedule a rebuild to get dependent jobs to drop
1182+
// this dependency from their swiftdeps files if possible.
1183+
auto buffer = llvm::MemoryBuffer::getFile(external);
1184+
if (!buffer) {
1185+
fallbackToExternalBehavior(external);
1186+
continue;
1187+
}
1188+
1189+
// Cons up a fake `Job` to satisfy the incremental job tracing
1190+
// code's internal invariants.
1191+
Job fakeJob(Comp.getDerivedOutputFileMap(), external);
1192+
auto subChanges =
1193+
getFineGrainedDepGraph(forRanges).loadFromSwiftModuleBuffer(
1194+
&fakeJob, *buffer.get(), Comp.getDiags());
1195+
1196+
// If the incremental dependency graph failed to load, fall back to
1197+
// treating this as plain external job.
1198+
if (!subChanges.hasValue()) {
1199+
fallbackToExternalBehavior(external);
1200+
continue;
1201+
}
1202+
1203+
for (auto *CMD :
1204+
getFineGrainedDepGraph(forRanges)
1205+
.findJobsToRecompileWhenNodesChange(subChanges.getValue())) {
1206+
if (CMD == &fakeJob) {
1207+
continue;
1208+
}
1209+
ExternallyDependentJobs.push_back(CMD);
1210+
}
1211+
}
11771212
noteBuildingJobs(ExternallyDependentJobs, forRanges,
1178-
"because of external dependencies");
1213+
"because of incremental external dependencies");
11791214
return ExternallyDependentJobs;
11801215
}
11811216

@@ -1645,6 +1680,13 @@ namespace driver {
16451680
.findExternallyDependentUntracedJobs(externalDependency);
16461681
}
16471682

1683+
std::vector<const Job *>
1684+
markIncrementalExternalInDepGraph(StringRef externalDependency,
1685+
const bool forRanges) {
1686+
return getFineGrainedDepGraph(forRanges)
1687+
.findIncrementalExternallyDependentUntracedJobs(externalDependency);
1688+
}
1689+
16481690
std::vector<const Job *> findJobsToRecompileWhenWholeJobChanges(
16491691
const Job *Cmd, const bool forRanges) {
16501692
return getFineGrainedDepGraph(forRanges)

0 commit comments

Comments
 (0)