Skip to content

Commit 7cb81ab

Browse files
authored
Merge pull request #67068 from artemcm/ExplicitPCH🍒
[5.9 🍒][Dependency Scanning] Record header dependencies of binary Swift module dependencies
2 parents 74f5b39 + e8c40d9 commit 7cb81ab

File tree

15 files changed

+228
-65
lines changed

15 files changed

+228
-65
lines changed

‎include/swift-c/DependencyScan/DependencyScan.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ SWIFTSCAN_PUBLIC swiftscan_string_ref_t
168168
swiftscan_swift_binary_detail_get_module_source_info_path(
169169
swiftscan_module_details_t details);
170170

171+
SWIFTSCAN_PUBLIC swiftscan_string_set_t *
172+
swiftscan_swift_binary_detail_get_header_dependencies(
173+
swiftscan_module_details_t details);
174+
171175
SWIFTSCAN_PUBLIC bool
172176
swiftscan_swift_binary_detail_get_is_framework(
173177
swiftscan_module_details_t details);

‎include/swift/AST/ModuleDependencies.h

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,14 @@ class ModuleDependencyInfoStorageBase {
9898
public:
9999
const ModuleDependencyKind dependencyKind;
100100

101+
ModuleDependencyInfoStorageBase(ModuleDependencyKind dependencyKind)
102+
: dependencyKind(dependencyKind),
103+
resolved(false) { }
104+
101105
ModuleDependencyInfoStorageBase(ModuleDependencyKind dependencyKind,
102-
bool resolved = false)
103-
: dependencyKind(dependencyKind), resolved(resolved) { }
106+
const std::vector<std::string> &moduleImports)
107+
: dependencyKind(dependencyKind), moduleImports(moduleImports),
108+
resolved(false) {}
104109

105110
virtual ModuleDependencyInfoStorageBase *clone() const = 0;
106111

@@ -245,11 +250,13 @@ class SwiftBinaryModuleDependencyStorage : public ModuleDependencyInfoStorageBas
245250
SwiftBinaryModuleDependencyStorage(const std::string &compiledModulePath,
246251
const std::string &moduleDocPath,
247252
const std::string &sourceInfoPath,
253+
const std::vector<std::string> &moduleImports,
254+
const std::vector<std::string> &headerImports,
248255
const bool isFramework)
249-
: ModuleDependencyInfoStorageBase(ModuleDependencyKind::SwiftBinary),
250-
compiledModulePath(compiledModulePath),
251-
moduleDocPath(moduleDocPath),
252-
sourceInfoPath(sourceInfoPath),
256+
: ModuleDependencyInfoStorageBase(ModuleDependencyKind::SwiftBinary,
257+
moduleImports),
258+
compiledModulePath(compiledModulePath), moduleDocPath(moduleDocPath),
259+
sourceInfoPath(sourceInfoPath), preCompiledBridgingHeaderPaths(headerImports),
253260
isFramework(isFramework) {}
254261

255262
ModuleDependencyInfoStorageBase *clone() const override {
@@ -265,6 +272,9 @@ class SwiftBinaryModuleDependencyStorage : public ModuleDependencyInfoStorageBas
265272
/// The path to the .swiftSourceInfo file.
266273
const std::string sourceInfoPath;
267274

275+
/// The paths of all the .pch dependencies of this module.
276+
const std::vector<std::string> preCompiledBridgingHeaderPaths;
277+
268278
/// A flag that indicates this dependency is a framework
269279
const bool isFramework;
270280

@@ -400,10 +410,13 @@ class ModuleDependencyInfo {
400410
const std::string &compiledModulePath,
401411
const std::string &moduleDocPath,
402412
const std::string &sourceInfoPath,
413+
const std::vector<std::string> &moduleImports,
414+
const std::vector<std::string> &headerImports,
403415
bool isFramework) {
404416
return ModuleDependencyInfo(
405417
std::make_unique<SwiftBinaryModuleDependencyStorage>(
406-
compiledModulePath, moduleDocPath, sourceInfoPath, isFramework));
418+
compiledModulePath, moduleDocPath, sourceInfoPath,
419+
moduleImports, headerImports, isFramework));
407420
}
408421

409422
/// Describe the main Swift module.

‎include/swift/DependencyScan/DependencyScanImpl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,10 @@ typedef struct {
109109
/// The path to the .swiftSourceInfo file.
110110
swiftscan_string_ref_t module_source_info_path;
111111

112+
/// (Clang) header dependencies of this binary module.
113+
/// Typically pre-compiled bridging header.
114+
swiftscan_string_set_t *header_dependencies;
115+
112116
/// A flag to indicate whether or not this module is a framework.
113117
bool is_framework;
114118
} swiftscan_swift_binary_details_t;

‎include/swift/DependencyScan/SerializedModuleDependencyCacheFormat.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ using SwiftBinaryModuleDetailsLayout =
155155
FileIDField, // compiledModulePath
156156
FileIDField, // moduleDocPath
157157
FileIDField, // moduleSourceInfoPath
158+
ImportArrayIDField, // headerImports
158159
IsFrameworkField // isFramework
159160
>;
160161

‎include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -184,11 +184,13 @@ struct ExplicitSwiftModuleInputInfo {
184184
ExplicitSwiftModuleInputInfo(std::string modulePath,
185185
llvm::Optional<std::string> moduleDocPath,
186186
llvm::Optional<std::string> moduleSourceInfoPath,
187+
llvm::Optional<std::vector<std::string>> headerDependencyPaths,
187188
bool isFramework = false,
188189
bool isSystem = false)
189190
: modulePath(modulePath),
190191
moduleDocPath(moduleDocPath),
191192
moduleSourceInfoPath(moduleSourceInfoPath),
193+
headerDependencyPaths(headerDependencyPaths),
192194
isFramework(isFramework),
193195
isSystem(isSystem) {}
194196
// Path of the .swiftmodule file.
@@ -197,6 +199,8 @@ struct ExplicitSwiftModuleInputInfo {
197199
llvm::Optional<std::string> moduleDocPath;
198200
// Path of the .swiftsourceinfo file.
199201
llvm::Optional<std::string> moduleSourceInfoPath;
202+
// Paths of the precompiled header dependencies of this module.
203+
llvm::Optional<std::vector<std::string>> headerDependencyPaths;
200204
// A flag that indicates whether this module is a framework
201205
bool isFramework = false;
202206
// A flag that indicates whether this module is a system module
@@ -306,30 +310,35 @@ class ExplicitModuleMapParser {
306310
StringRef moduleName;
307311
llvm::Optional<std::string> swiftModulePath, swiftModuleDocPath,
308312
swiftModuleSourceInfoPath;
313+
llvm::Optional<std::vector<std::string>> headerDependencyPaths;
309314
std::string clangModuleMapPath = "", clangModulePath = "";
310315
bool isFramework = false, isSystem = false;
311316
for (auto &entry : *mapNode) {
312317
auto key = getScalaNodeText(entry.getKey());
313-
auto val = getScalaNodeText(entry.getValue());
314-
if (key == "moduleName") {
315-
moduleName = val;
316-
} else if (key == "modulePath") {
317-
swiftModulePath = val.str();
318-
} else if (key == "docPath") {
319-
swiftModuleDocPath = val.str();
320-
} else if (key == "sourceInfoPath") {
321-
swiftModuleSourceInfoPath = val.str();
322-
} else if (key == "isFramework") {
323-
isFramework = parseBoolValue(val);
324-
} else if (key == "isSystem") {
325-
isSystem = parseBoolValue(val);
326-
} else if (key == "clangModuleMapPath") {
327-
clangModuleMapPath = val.str();
328-
} else if (key == "clangModulePath") {
329-
clangModulePath = val.str();
330-
} else {
331-
// Being forgiving for future fields.
318+
if (key == "prebuiltHeaderDependencyPaths") {
332319
continue;
320+
} else {
321+
auto val = getScalaNodeText(entry.getValue());
322+
if (key == "moduleName") {
323+
moduleName = val;
324+
} else if (key == "modulePath") {
325+
swiftModulePath = val.str();
326+
} else if (key == "docPath") {
327+
swiftModuleDocPath = val.str();
328+
} else if (key == "sourceInfoPath") {
329+
swiftModuleSourceInfoPath = val.str();
330+
} else if (key == "isFramework") {
331+
isFramework = parseBoolValue(val);
332+
} else if (key == "isSystem") {
333+
isSystem = parseBoolValue(val);
334+
} else if (key == "clangModuleMapPath") {
335+
clangModuleMapPath = val.str();
336+
} else if (key == "clangModulePath") {
337+
clangModulePath = val.str();
338+
} else {
339+
// Being forgiving for future fields.
340+
continue;
341+
}
333342
}
334343
}
335344
if (moduleName.empty())
@@ -342,6 +351,7 @@ class ExplicitModuleMapParser {
342351
ExplicitSwiftModuleInputInfo entry(swiftModulePath.value(),
343352
swiftModuleDocPath,
344353
swiftModuleSourceInfoPath,
354+
headerDependencyPaths,
345355
isFramework,
346356
isSystem);
347357
swiftModuleMap.try_emplace(moduleName, std::move(entry));

‎include/swift/Serialization/SerializedModuleLoader.h

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -150,15 +150,20 @@ class SerializedModuleLoaderBase : public ModuleLoader {
150150
/// Scan the given serialized module file to determine dependencies.
151151
llvm::ErrorOr<ModuleDependencyInfo> scanModuleFile(Twine modulePath, bool isFramework);
152152

153-
static llvm::ErrorOr<llvm::StringSet<>>
154-
getModuleImportsOfModule(Twine modulePath,
155-
ModuleLoadingBehavior transitiveBehavior,
156-
bool isFramework,
157-
bool isRequiredOSSAModules,
158-
StringRef SDKName,
159-
StringRef packageName,
160-
llvm::vfs::FileSystem *fileSystem,
161-
PathObfuscator &recoverer);
153+
struct BinaryModuleImports {
154+
llvm::StringSet<> moduleImports;
155+
llvm::StringSet<> headerImports;
156+
};
157+
158+
static llvm::ErrorOr<BinaryModuleImports>
159+
getImportsOfModule(Twine modulePath,
160+
ModuleLoadingBehavior transitiveBehavior,
161+
bool isFramework,
162+
bool isRequiredOSSAModules,
163+
StringRef SDKName,
164+
StringRef packageName,
165+
llvm::vfs::FileSystem *fileSystem,
166+
PathObfuscator &recoverer);
162167

163168
/// Load the module file into a buffer and also collect its module name.
164169
static std::unique_ptr<llvm::MemoryBuffer>

‎lib/DependencyScan/ModuleDependencyCacheSerialization.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -413,10 +413,10 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi
413413
"Unexpected SWIFT_BINARY_MODULE_DETAILS_NODE record");
414414
cache.configureForContextHash(getContextHash());
415415
unsigned compiledModulePathID, moduleDocPathID, moduleSourceInfoPathID,
416-
isFramework;
416+
headerImportsArrayID, isFramework;
417417
SwiftBinaryModuleDetailsLayout::readRecord(
418418
Scratch, compiledModulePathID, moduleDocPathID,
419-
moduleSourceInfoPathID, isFramework);
419+
moduleSourceInfoPathID, headerImportsArrayID, isFramework);
420420

421421
auto compiledModulePath = getIdentifier(compiledModulePathID);
422422
if (!compiledModulePath)
@@ -428,13 +428,14 @@ bool ModuleDependenciesCacheDeserializer::readGraph(SwiftDependencyScanningServi
428428
if (!moduleSourceInfoPath)
429429
llvm::report_fatal_error("Bad module source info path");
430430

431+
auto headerImports = getStringArray(headerImportsArrayID);
432+
if (!headerImports)
433+
llvm::report_fatal_error("Bad binary direct dependencies: no header imports");
434+
431435
// Form the dependencies storage object
432436
auto moduleDep = ModuleDependencyInfo::forSwiftBinaryModule(
433-
*compiledModulePath, *moduleDocPath, *moduleSourceInfoPath,
434-
isFramework);
435-
// Add dependencies of this module
436-
for (const auto &moduleName : *currentModuleImports)
437-
moduleDep.addModuleImport(moduleName);
437+
*compiledModulePath, *moduleDocPath, *moduleSourceInfoPath,
438+
*currentModuleImports, *headerImports, isFramework);
438439

439440
cache.recordDependency(currentModuleName, std::move(moduleDep),
440441
getContextHash());
@@ -638,6 +639,7 @@ bool swift::dependencies::module_dependency_cache_serialization::
638639
enum ModuleIdentifierArrayKind : uint8_t {
639640
Empty = 0,
640641
DependencyImports,
642+
DependencyHeaders,
641643
QualifiedModuleDependencyIDs,
642644
CompiledModuleCandidates,
643645
BuildCommandLine,
@@ -894,6 +896,7 @@ void ModuleDependenciesCacheSerializer::writeModuleInfo(
894896
getIdentifier(swiftBinDeps->compiledModulePath),
895897
getIdentifier(swiftBinDeps->moduleDocPath),
896898
getIdentifier(swiftBinDeps->sourceInfoPath),
899+
getArrayID(moduleID, ModuleIdentifierArrayKind::DependencyHeaders),
897900
swiftBinDeps->isFramework);
898901

899902
break;
@@ -1062,6 +1065,8 @@ void ModuleDependenciesCacheSerializer::collectStringsAndArrays(
10621065
addIdentifier(swiftBinDeps->compiledModulePath);
10631066
addIdentifier(swiftBinDeps->moduleDocPath);
10641067
addIdentifier(swiftBinDeps->sourceInfoPath);
1068+
addStringArray(moduleID, ModuleIdentifierArrayKind::DependencyHeaders,
1069+
swiftBinDeps->preCompiledBridgingHeaderPaths);
10651070
break;
10661071
}
10671072
case swift::ModuleDependencyKind::SwiftPlaceholder: {

‎lib/DependencyScan/ScanDependencies.cpp

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ computeTransitiveClosureOfExplicitDependencies(
243243
llvm::set_union(modReachableSet, succReachableSet);
244244
}
245245
}
246+
// For ease of use down-the-line, remove the node's self from its set of reachable nodes
247+
for (const auto &modID : topologicallySortedModuleList)
248+
result[modID].erase(modID);
249+
246250
return result;
247251
}
248252

@@ -272,8 +276,15 @@ resolveExplicitModuleInputs(ModuleDependencyID moduleID,
272276
case swift::ModuleDependencyKind::SwiftBinary: {
273277
auto binaryDepDetails = depInfo->getAsSwiftBinaryModule();
274278
assert(binaryDepDetails && "Expected Swift Binary Module dependency.");
279+
auto &path = binaryDepDetails->compiledModulePath;
275280
commandLine.push_back("-swift-module-file=" + depModuleID.first + "=" +
276-
binaryDepDetails->compiledModulePath);
281+
path);
282+
for (const auto &headerDep : binaryDepDetails->preCompiledBridgingHeaderPaths) {
283+
commandLine.push_back("-Xcc");
284+
commandLine.push_back("-include-pch");
285+
commandLine.push_back("-Xcc");
286+
commandLine.push_back(headerDep);
287+
}
277288
} break;
278289
case swift::ModuleDependencyKind::SwiftPlaceholder: {
279290
auto placeholderDetails = depInfo->getAsPlaceholderDependencyModule();
@@ -942,6 +953,13 @@ static void writeJSON(llvm::raw_ostream &out,
942953
swiftBinaryDeps->module_source_info_path,
943954
/*indentLevel=*/5,
944955
/*trailingComma=*/true);
956+
957+
// Module Header Dependencies
958+
if (swiftBinaryDeps->header_dependencies->count != 0)
959+
writeJSONSingleField(out, "headerDependencies",
960+
swiftBinaryDeps->header_dependencies, 5,
961+
/*trailingComma=*/true);
962+
945963
writeJSONSingleField(out, "isFramework", swiftBinaryDeps->is_framework,
946964
5, /*trailingComma=*/false);
947965
} else {
@@ -1128,6 +1146,7 @@ generateFullDependencyGraph(CompilerInstance &instance,
11281146
create_clone(swiftBinaryDeps->compiledModulePath.c_str()),
11291147
create_clone(swiftBinaryDeps->moduleDocPath.c_str()),
11301148
create_clone(swiftBinaryDeps->sourceInfoPath.c_str()),
1149+
create_set(swiftBinaryDeps->preCompiledBridgingHeaderPaths),
11311150
swiftBinaryDeps->isFramework};
11321151
} else {
11331152
// Clang module details

‎lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1995,7 +1995,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
19951995
const std::vector<std::pair<std::string, std::string>>
19961996
&commandLineExplicitInputs) {
19971997
for (const auto &moduleInput : commandLineExplicitInputs) {
1998-
ExplicitSwiftModuleInputInfo entry(moduleInput.second, {}, {});
1998+
ExplicitSwiftModuleInputInfo entry(moduleInput.second, {}, {}, {});
19991999
ExplicitModuleMap.try_emplace(moduleInput.first, std::move(entry));
20002000
}
20012001
}

‎lib/Serialization/ModuleDependencyScanner.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -194,38 +194,41 @@ ErrorOr<ModuleDependencyInfo> ModuleDependencyScanner::scanInterfaceFile(
194194
});
195195
if (adjacentBinaryModule != compiledCandidates.end()) {
196196
// Required modules.
197-
auto adjacentBinaryModuleRequiredImports = getModuleImportsOfModule(
197+
auto adjacentBinaryModuleRequiredImports = getImportsOfModule(
198198
*adjacentBinaryModule, ModuleLoadingBehavior::Required, isFramework,
199199
isRequiredOSSAModules(), Ctx.LangOpts.SDKName,
200200
Ctx.LangOpts.PackageName, Ctx.SourceMgr.getFileSystem().get(),
201201
Ctx.SearchPathOpts.DeserializedPathRecoverer);
202202
if (!adjacentBinaryModuleRequiredImports)
203203
return adjacentBinaryModuleRequiredImports.getError();
204-
204+
auto adjacentBinaryModuleRequiredModuleImports =
205+
(*adjacentBinaryModuleRequiredImports).moduleImports;
205206
#ifndef NDEBUG
206207
// Verify that the set of required modules read out from the binary
207208
// module is a super-set of module imports identified in the
208209
// textual interface.
209210
for (const auto &requiredImport : Result->getModuleImports()) {
210-
assert(adjacentBinaryModuleRequiredImports->contains(requiredImport) &&
211+
assert(adjacentBinaryModuleRequiredModuleImports.contains(requiredImport) &&
211212
"Expected adjacent binary module's import set to contain all "
212213
"textual interface imports.");
213214
}
214215
#endif
215216

216-
for (const auto &requiredImport : *adjacentBinaryModuleRequiredImports)
217+
for (const auto &requiredImport : adjacentBinaryModuleRequiredModuleImports)
217218
Result->addModuleImport(requiredImport.getKey(),
218219
&alreadyAddedModules);
219220

220221
// Optional modules. Will be looked-up on a best-effort basis
221-
auto adjacentBinaryModuleOptionalImports = getModuleImportsOfModule(
222+
auto adjacentBinaryModuleOptionalImports = getImportsOfModule(
222223
*adjacentBinaryModule, ModuleLoadingBehavior::Optional, isFramework,
223224
isRequiredOSSAModules(), Ctx.LangOpts.SDKName,
224225
Ctx.LangOpts.PackageName, Ctx.SourceMgr.getFileSystem().get(),
225226
Ctx.SearchPathOpts.DeserializedPathRecoverer);
226227
if (!adjacentBinaryModuleOptionalImports)
227228
return adjacentBinaryModuleOptionalImports.getError();
228-
for (const auto &optionalImport : *adjacentBinaryModuleOptionalImports)
229+
auto adjacentBinaryModuleOptionalModuleImports =
230+
(*adjacentBinaryModuleOptionalImports).moduleImports;
231+
for (const auto &optionalImport : adjacentBinaryModuleOptionalModuleImports)
229232
Result->addOptionalModuleImport(optionalImport.getKey(),
230233
&alreadyAddedModules);
231234
}

0 commit comments

Comments
 (0)