Skip to content

Commit b5af62f

Browse files
committed
Add new dependency kind (swiftExternal) to model external dependencies.
1 parent c52982c commit b5af62f

File tree

6 files changed

+154
-45
lines changed

6 files changed

+154
-45
lines changed

include/swift/AST/ModuleDependencies.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class SwiftModuleDependenciesStorage : public ModuleDependenciesStorageBase {
116116
}
117117

118118
static bool classof(const ModuleDependenciesStorageBase *base) {
119-
return base->isSwiftModule;
119+
return base->isSwiftModule && !base->isExternalSwiftModuleStub;
120120
}
121121
};
122122

@@ -244,8 +244,11 @@ class ModuleDependencies {
244244
bool isSwiftModule() const;
245245

246246
ModuleDependenciesKind getKind() const {
247-
return isSwiftModule() ? ModuleDependenciesKind::Swift
248-
: ModuleDependenciesKind::Clang;
247+
if (isExternalSwiftModuleStub())
248+
return ModuleDependenciesKind::SwiftExternal;
249+
else
250+
return isSwiftModule() ? ModuleDependenciesKind::Swift
251+
: ModuleDependenciesKind::Clang;
249252
}
250253
/// Retrieve the dependencies for a Swift module.
251254
const SwiftModuleDependenciesStorage *getAsSwiftModule() const;

lib/AST/ModuleDependencies.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ bool ModuleDependenciesCache::hasDependencies(
126126
Optional<ModuleDependenciesKind> kind) const {
127127
if (!kind) {
128128
return hasDependencies(moduleName, ModuleDependenciesKind::Swift) ||
129+
hasDependencies(moduleName, ModuleDependenciesKind::SwiftExternal) ||
129130
hasDependencies(moduleName, ModuleDependenciesKind::Clang);
130131
}
131132

@@ -140,8 +141,11 @@ Optional<ModuleDependencies> ModuleDependenciesCache::findDependencies(
140141
if (auto swiftDep = findDependencies(
141142
moduleName, ModuleDependenciesKind::Swift))
142143
return swiftDep;
143-
144-
return findDependencies(moduleName, ModuleDependenciesKind::Clang);
144+
else if (auto swiftExternalDep = findDependencies(
145+
moduleName, ModuleDependenciesKind::SwiftExternal))
146+
return swiftExternalDep;
147+
else
148+
return findDependencies(moduleName, ModuleDependenciesKind::Clang);
145149
}
146150

147151
const auto &map = getDependenciesMap(*kind);

lib/AST/ModuleLoader.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ ModuleDependencies::collectCrossImportOverlayNames(ASTContext &ctx,
165165
using namespace llvm::sys;
166166
using namespace file_types;
167167
Optional<std::string> modulePath;
168+
// A map from secondary module name to a vector of overlay names.
169+
llvm::StringMap<llvm::SmallSetVector<Identifier, 4>> result;
168170
// Mimic getModuleDefiningPath() for Swift and Clang module.
169171
if (auto *swiftDep = dyn_cast<SwiftModuleDependenciesStorage>(storage.get())) {
170172
// Prefer interface path to binary module path if we have it.
@@ -176,12 +178,12 @@ ModuleDependencies::collectCrossImportOverlayNames(ASTContext &ctx,
176178
if (llvm::sys::path::extension(parentDir) == ".swiftmodule") {
177179
modulePath = parentDir.str();
178180
}
179-
} else {
180-
modulePath = cast<ClangModuleDependenciesStorage>(storage.get())->moduleMapFile;
181+
} else if (auto *clangDep = dyn_cast<ClangModuleDependenciesStorage>(storage.get())){
182+
modulePath = clangDep->moduleMapFile;
181183
assert(modulePath.hasValue());
184+
} else { // ExternalSwiftModuleDependency
185+
return result;
182186
}
183-
// A map from secondary module name to a vector of overlay names.
184-
llvm::StringMap<llvm::SmallSetVector<Identifier, 4>> result;
185187
findOverlayFilesInternal(ctx, *modulePath, moduleName, SourceLoc(),
186188
[&](StringRef file) {
187189
StringRef bystandingModule;

lib/Driver/Driver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ static void validateDependencyScanningArgs(DiagnosticEngine &diags,
168168
const Arg *ExternalDependencyMap = args.getLastArg(options::OPT_external_dependency_module_map);
169169
const Arg *ScanDependencies = args.getLastArg(options::OPT_scan_dependencies);
170170
if (ExternalDependencyMap && !ScanDependencies) {
171-
diags.diagnose(SourceLoc(), diag::error_conflicting_options,
171+
diags.diagnose(SourceLoc(), diag::error_requirement_not_met,
172172
"-external-dependency-module-map-file", "-scan-dependencies");
173173
}
174174
}

lib/FrontendTool/ScanDependencies.cpp

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,17 @@ namespace {
221221
const ModuleDependencyID &module,
222222
unsigned indentLevel) {
223223
out << "{\n";
224+
std::string moduleKind;
225+
if (module.second == ModuleDependenciesKind::Swift)
226+
moduleKind = "swift";
227+
else if (module.second == ModuleDependenciesKind::SwiftExternal)
228+
moduleKind = "swiftExternal";
229+
else
230+
moduleKind = "clang";
224231

225232
writeJSONSingleField(
226233
out,
227-
module.second == ModuleDependenciesKind::Swift ? "swift" : "clang",
234+
moduleKind,
228235
module.first,
229236
indentLevel + 1,
230237
/*trailingComma=*/false);
@@ -317,27 +324,33 @@ static void writeJSON(llvm::raw_ostream &out,
317324
out.indent(2 * 2);
318325
out << "{\n";
319326

327+
auto externalSwiftDep = moduleDeps.getAsExternalDependencyModuleStub();
328+
auto swiftDeps = moduleDeps.getAsSwiftModule();
329+
auto clangDeps = moduleDeps.getAsClangModule();
330+
320331
// Module path.
321332
const char *modulePathSuffix =
322333
moduleDeps.isSwiftModule() ? ".swiftmodule" : ".pcm";
323-
std::string modulePath = module.first + modulePathSuffix;
334+
335+
std::string modulePath = externalSwiftDep
336+
? externalSwiftDep->compiledModulePath
337+
: module.first + modulePathSuffix;
324338
writeJSONSingleField(out, "modulePath", modulePath, /*indentLevel=*/3,
325339
/*trailingComma=*/true);
326340

327341
// Source files.
328-
auto swiftDeps = moduleDeps.getAsSwiftModule();
329-
auto clangDeps = moduleDeps.getAsClangModule();
330342
if (swiftDeps) {
331343
writeJSONSingleField(out, "sourceFiles", swiftDeps->sourceFiles, 3,
332-
/*trailingComma=*/true);
333-
} else {
344+
/*trailingComma=*/true);
345+
} else if (clangDeps) {
334346
writeJSONSingleField(out, "sourceFiles", clangDeps->fileDependencies, 3,
335347
/*trailingComma=*/true);
336348
}
337349

338350
// Direct dependencies.
339-
writeJSONSingleField(out, "directDependencies", directDependencies,
340-
3, /*trailingComma=*/true);
351+
if (swiftDeps || clangDeps)
352+
writeJSONSingleField(out, "directDependencies", directDependencies, 3,
353+
/*trailingComma=*/true);
341354

342355
// Swift and Clang-specific details.
343356
out.indent(3 * 2);
@@ -358,6 +371,7 @@ static void writeJSON(llvm::raw_ostream &out,
358371
out.indent(5 * 2);
359372
out << "\"commandLine\": [\n";
360373
for (auto &arg :swiftDeps->buildCommandLine) {
374+
361375
out.indent(6 * 2);
362376
out << "\"" << arg << "\"";
363377
if (&arg != &swiftDeps->buildCommandLine.back())
@@ -386,7 +400,7 @@ static void writeJSON(llvm::raw_ostream &out,
386400
if (!swiftDeps->extraPCMArgs.empty()) {
387401
out.indent(5 * 2);
388402
out << "\"extraPcmArgs\": [\n";
389-
for (auto &arg :swiftDeps->extraPCMArgs) {
403+
for (auto &arg : swiftDeps->extraPCMArgs) {
390404
out.indent(6 * 2);
391405
out << "\"" << arg << "\"";
392406
if (&arg != &swiftDeps->extraPCMArgs.back())
@@ -400,42 +414,53 @@ static void writeJSON(llvm::raw_ostream &out,
400414
if (swiftDeps->bridgingHeaderFile) {
401415
out.indent(5 * 2);
402416
out << "\"bridgingHeader\": {\n";
403-
writeJSONSingleField(out, "path",
404-
*swiftDeps->bridgingHeaderFile, 6,
417+
writeJSONSingleField(out, "path", *swiftDeps->bridgingHeaderFile, 6,
405418
/*trailingComma=*/true);
406-
writeJSONSingleField(out, "sourceFiles",
407-
swiftDeps->bridgingSourceFiles, 6,
419+
writeJSONSingleField(out, "sourceFiles", swiftDeps->bridgingSourceFiles,
420+
6,
408421
/*trailingComma=*/true);
409422
writeJSONSingleField(out, "moduleDependencies",
410423
swiftDeps->bridgingModuleDependencies, 6,
411424
/*trailingComma=*/false);
412425
out.indent(5 * 2);
413426
out << "}\n";
414427
}
428+
} else if (externalSwiftDep) {
429+
out << "\"swiftExternal\": {\n";
430+
431+
// Module doc file
432+
if (externalSwiftDep->moduleDocPath != "")
433+
writeJSONSingleField(out, "moduleDocPath",
434+
externalSwiftDep->moduleDocPath,
435+
/*indentLevel=*/5,
436+
/*trailingComma=*/true);
437+
438+
// Module Source Info file
439+
if (externalSwiftDep->moduleDocPath != "")
440+
writeJSONSingleField(out, "moduleSourceInfoPath",
441+
externalSwiftDep->sourceInfoPath,
442+
/*indentLevel=*/5,
443+
/*trailingComma=*/true);
415444
} else {
416445
out << "\"clang\": {\n";
417446

418447
// Module map file.
419-
writeJSONSingleField(out, "moduleMapPath",
420-
clangDeps->moduleMapFile, 5,
448+
writeJSONSingleField(out, "moduleMapPath", clangDeps->moduleMapFile, 5,
421449
/*trailingComma=*/true);
422450

423451
// Context hash.
424-
writeJSONSingleField(out, "contextHash",
425-
clangDeps->contextHash, 5,
452+
writeJSONSingleField(out, "contextHash", clangDeps->contextHash, 5,
426453
/*trailingComma=*/true);
427454

428455
// Command line.
429-
writeJSONSingleField(out, "commandLine",
430-
clangDeps->nonPathCommandLine, 5,
456+
writeJSONSingleField(out, "commandLine", clangDeps->nonPathCommandLine, 5,
431457
/*trailingComma=*/false);
432458
}
433459

434460
out.indent(4 * 2);
435461
out << "}\n";
436462
out.indent(3 * 2);
437463
out << "}\n";
438-
439464
out.indent(2 * 2);
440465
out << "}";
441466

@@ -584,8 +609,7 @@ bool swift::scanDependencies(CompilerInstance &instance) {
584609
depTracker->addDependency(sourceFile, /*IsSystem=*/false);
585610
for (const auto &bridgingSourceFile : swiftDeps->bridgingSourceFiles)
586611
depTracker->addDependency(bridgingSourceFile, /*IsSystem=*/false);
587-
} else {
588-
auto clangDeps = deps->getAsClangModule();
612+
} else if (auto clangDeps = deps->getAsClangModule()) {
589613
if (!clangDeps->moduleMapFile.empty())
590614
depTracker->addDependency(clangDeps->moduleMapFile, /*IsSystem=*/false);
591615
for (const auto &sourceFile : clangDeps->fileDependencies)

lib/Serialization/ModuleDependencyScanner.cpp

Lines changed: 89 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,17 @@ class ModuleDependencyScanner : public SerializedModuleLoaderBase {
3737
public:
3838
Optional<ModuleDependencies> dependencies;
3939

40-
ModuleDependencyScanner(ASTContext &ctx, ModuleLoadingMode LoadMode,
41-
Identifier moduleName,
42-
InterfaceSubContextDelegate &astDelegate)
40+
/// Describes the kind of dependencies this scanner is able to identify
41+
ModuleDependenciesKind dependencyKind;
42+
43+
ModuleDependencyScanner(
44+
ASTContext &ctx, ModuleLoadingMode LoadMode, Identifier moduleName,
45+
InterfaceSubContextDelegate &astDelegate,
46+
ModuleDependenciesKind dependencyKind = ModuleDependenciesKind::Swift)
4347
: SerializedModuleLoaderBase(ctx, nullptr, LoadMode,
4448
/*IgnoreSwiftSourceInfoFile=*/true),
45-
moduleName(moduleName), astDelegate(astDelegate) { }
49+
moduleName(moduleName), astDelegate(astDelegate),
50+
dependencyKind(dependencyKind) {}
4651

4752
virtual std::error_code findModuleFilesInDirectory(
4853
AccessPathElem ModuleID,
@@ -86,6 +91,73 @@ class ModuleDependencyScanner : public SerializedModuleLoaderBase {
8691
llvm_unreachable("Not used");
8792
}
8893
};
94+
95+
/// A ModuleLoader that loads external dependency module stubs specified in
96+
/// -external-dependency-module-map-file
97+
/// This loader is used only in dependency scanning to inform the scanner that a
98+
/// set of modules constitute external dependencies that are not visible to the
99+
/// scanner but will nevertheless be provided by the scanner's clients.
100+
/// This "loader" will not attempt to load any module files.
101+
class ExternalSwiftModuleStubLoader : public ModuleDependencyScanner {
102+
/// Scan the given external module map
103+
void parseExternalModuleMap(StringRef fileName);
104+
llvm::StringMap<ExplicitModuleInfo> ExternalDependencyModuleMap;
105+
106+
public:
107+
ExternalSwiftModuleStubLoader(ASTContext &ctx, ModuleLoadingMode LoadMode,
108+
Identifier moduleName,
109+
StringRef ExternalDependencyModuleMap,
110+
InterfaceSubContextDelegate &astDelegate)
111+
: ModuleDependencyScanner(ctx, LoadMode, moduleName, astDelegate,
112+
ModuleDependenciesKind::SwiftExternal) {
113+
114+
// FIXME: Find a better place for this map to live, to avoid
115+
// doing the parsing on every module.
116+
parseExternalModuleMap(ExternalDependencyModuleMap);
117+
}
118+
119+
std::error_code findModuleFilesInDirectory(
120+
AccessPathElem ModuleID, const SerializedModuleBaseName &BaseName,
121+
SmallVectorImpl<char> *ModuleInterfacePath,
122+
std::unique_ptr<llvm::MemoryBuffer> *ModuleBuffer,
123+
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer,
124+
std::unique_ptr<llvm::MemoryBuffer> *ModuleSourceInfoBuffer) override {
125+
StringRef moduleName = ModuleID.Item.str();
126+
auto it = ExternalDependencyModuleMap.find(moduleName);
127+
// If no external module stub path is given matches the name, return with an
128+
// error code.
129+
if (it == ExternalDependencyModuleMap.end()) {
130+
return std::make_error_code(std::errc::not_supported);
131+
}
132+
auto &moduleInfo = it->getValue();
133+
assert(!moduleInfo.moduleBuffer &&
134+
"External dependency module stubs cannot have an associated buffer");
135+
136+
auto dependencies = ModuleDependencies::forExternalSwiftModuleStub(
137+
moduleInfo.modulePath, moduleInfo.moduleDocPath,
138+
moduleInfo.moduleSourceInfoPath);
139+
this->dependencies = std::move(dependencies);
140+
return std::error_code{};
141+
}
142+
143+
public:
144+
static std::unique_ptr<ExternalSwiftModuleStubLoader>
145+
create(ASTContext &ctx, DependencyTracker *tracker,
146+
ModuleLoadingMode loadMode, StringRef ExternalDependencyModuleMap,
147+
bool IgnoreSwiftSourceInfoFile);
148+
};
149+
} // namespace
150+
151+
void ExternalSwiftModuleStubLoader::parseExternalModuleMap(StringRef fileName) {
152+
ExplicitModuleMapParser parser(Ctx);
153+
auto result =
154+
parser.parseSwiftExplicitModuleMap(fileName, ExternalDependencyModuleMap);
155+
if (result == std::errc::invalid_argument)
156+
Ctx.Diags.diagnose(
157+
SourceLoc(), diag::external_dependency_module_map_corrupted, fileName);
158+
else if (result == std::errc::no_such_file_or_directory)
159+
Ctx.Diags.diagnose(SourceLoc(),
160+
diag::external_dependency_module_map_missing, fileName);
89161
}
90162

91163
static std::vector<std::string> getCompiledCandidates(ASTContext &ctx,
@@ -153,15 +225,19 @@ Optional<ModuleDependencies> SerializedModuleLoaderBase::getModuleDependencies(
153225
if (auto found = cache.findDependencies(
154226
moduleName, ModuleDependenciesKind::Swift))
155227
return found;
228+
if (auto found =
229+
cache.findDependencies(moduleName, ModuleDependenciesKind::SwiftExternal))
230+
return found;
156231

157232
// Check whether there is a module with this name that we can import.
158-
auto moduleId = Ctx.getIdentifier(moduleName);
159-
ModuleDependencyScanner scanner(Ctx, LoadMode, moduleId, delegate);
160-
if (!scanner.canImportModule({moduleId, SourceLoc()}))
161-
return None;
162-
163-
// Record the dependencies.
164-
cache.recordDependencies(moduleName, *scanner.dependencies,
165-
ModuleDependenciesKind::Swift);
166-
return std::move(scanner.dependencies);
233+
for (auto &scanner : scanners) {
234+
if (scanner->canImportModule({moduleId, SourceLoc()})) {
235+
// Record the dependencies.
236+
cache.recordDependencies(moduleName, *(scanner->dependencies),
237+
scanner->dependencyKind);
238+
return std::move(scanner->dependencies);
239+
}
240+
}
241+
242+
return None;
167243
}

0 commit comments

Comments
 (0)