Skip to content

Commit 163c6f9

Browse files
committed
Allow module aliases to be expressed in the explicit Swift module map JSON file.
For build systems that already generate these files, it makes sense to include the aliases so that the map file serves as a comprehensive index of how the module inputs are referenced.
1 parent 9328d34 commit 163c6f9

File tree

6 files changed

+116
-18
lines changed

6 files changed

+116
-18
lines changed

include/swift/AST/ASTContext.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -595,6 +595,10 @@ class ASTContext final {
595595
/// are the real (physical) module names on disk.
596596
void setModuleAliases(const llvm::StringMap<StringRef> &aliasMap);
597597

598+
/// Adds a given alias to the map of Identifiers between module aliases and
599+
/// their actual names.
600+
void addModuleAlias(StringRef moduleAlias, StringRef realName);
601+
598602
/// Look up option used in \c getRealModuleName when module aliasing is applied.
599603
enum class ModuleAliasLookupOption {
600604
alwaysRealName,

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -318,10 +318,11 @@ class ExplicitModuleMapParser {
318318
public:
319319
ExplicitModuleMapParser(llvm::BumpPtrAllocator &Allocator) : Saver(Allocator) {}
320320

321-
std::error_code
322-
parseSwiftExplicitModuleMap(llvm::MemoryBufferRef BufferRef,
323-
llvm::StringMap<ExplicitSwiftModuleInputInfo> &swiftModuleMap,
324-
llvm::StringMap<ExplicitClangModuleInputInfo> &clangModuleMap) {
321+
std::error_code parseSwiftExplicitModuleMap(
322+
llvm::MemoryBufferRef BufferRef,
323+
llvm::StringMap<ExplicitSwiftModuleInputInfo> &swiftModuleMap,
324+
llvm::StringMap<ExplicitClangModuleInputInfo> &clangModuleMap,
325+
llvm::StringMap<std::string> &moduleAliases) {
325326
using namespace llvm::yaml;
326327
// Use a new source manager instead of the one from ASTContext because we
327328
// don't want the JSON file to be persistent.
@@ -331,7 +332,8 @@ class ExplicitModuleMapParser {
331332
assert(DI != Stream.end() && "Failed to read a document");
332333
if (auto *MN = dyn_cast_or_null<SequenceNode>(DI->getRoot())) {
333334
for (auto &entry : *MN) {
334-
if (parseSingleModuleEntry(entry, swiftModuleMap, clangModuleMap)) {
335+
if (parseSingleModuleEntry(entry, swiftModuleMap, clangModuleMap,
336+
moduleAliases)) {
335337
return std::make_error_code(std::errc::invalid_argument);
336338
}
337339
}
@@ -359,16 +361,19 @@ class ExplicitModuleMapParser {
359361
llvm_unreachable("Unexpected JSON value for isFramework");
360362
}
361363

362-
bool parseSingleModuleEntry(llvm::yaml::Node &node,
363-
llvm::StringMap<ExplicitSwiftModuleInputInfo> &swiftModuleMap,
364-
llvm::StringMap<ExplicitClangModuleInputInfo> &clangModuleMap) {
364+
bool parseSingleModuleEntry(
365+
llvm::yaml::Node &node,
366+
llvm::StringMap<ExplicitSwiftModuleInputInfo> &swiftModuleMap,
367+
llvm::StringMap<ExplicitClangModuleInputInfo> &clangModuleMap,
368+
llvm::StringMap<std::string> &moduleAliases) {
365369
using namespace llvm::yaml;
366370
auto *mapNode = dyn_cast<MappingNode>(&node);
367371
if (!mapNode)
368372
return true;
369373
StringRef moduleName;
370374
std::optional<std::string> swiftModulePath, swiftModuleDocPath,
371-
swiftModuleSourceInfoPath, swiftModuleCacheKey, clangModuleCacheKey;
375+
swiftModuleSourceInfoPath, swiftModuleCacheKey, clangModuleCacheKey,
376+
moduleAlias;
372377
std::optional<std::vector<std::string>> headerDependencyPaths;
373378
std::string clangModuleMapPath = "", clangModulePath = "";
374379
bool isFramework = false, isSystem = false,
@@ -405,6 +410,8 @@ class ExplicitModuleMapParser {
405410
clangModuleCacheKey = val.str();
406411
} else if (key == "isBridgingHeaderDependency") {
407412
isBridgingHeaderDependency = parseBoolValue(val);
413+
} else if (key == "moduleAlias") {
414+
moduleAlias = val.str();
408415
} else {
409416
// Being forgiving for future fields.
410417
continue;
@@ -438,6 +445,9 @@ class ExplicitModuleMapParser {
438445
clangModuleCacheKey);
439446
clangModuleMap.try_emplace(moduleName, std::move(entry));
440447
}
448+
if (moduleAlias.has_value()) {
449+
moduleAliases[*moduleAlias] = moduleName;
450+
}
441451

442452
return false;
443453
}

lib/AST/ASTContext.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2108,16 +2108,20 @@ void ASTContext::setModuleAliases(const llvm::StringMap<StringRef> &aliasMap) {
21082108
for (auto k: aliasMap.keys()) {
21092109
auto v = aliasMap.lookup(k);
21102110
if (!v.empty()) {
2111-
auto key = getIdentifier(k);
2112-
auto val = getIdentifier(v);
2113-
// key is a module alias, val is its corresponding real name
2114-
ModuleAliasMap[key] = std::make_pair(val, true);
2115-
// add an entry with an alias as key for an easier lookup later
2116-
ModuleAliasMap[val] = std::make_pair(key, false);
2111+
addModuleAlias(k, v);
21172112
}
21182113
}
21192114
}
21202115

2116+
void ASTContext::addModuleAlias(StringRef moduleAlias, StringRef realName) {
2117+
auto key = getIdentifier(moduleAlias);
2118+
auto val = getIdentifier(realName);
2119+
// key is a module alias, val is its corresponding real name
2120+
ModuleAliasMap[key] = std::make_pair(val, true);
2121+
// add an entry with an alias as key for an easier lookup later
2122+
ModuleAliasMap[val] = std::make_pair(key, false);
2123+
}
2124+
21212125
Identifier ASTContext::getRealModuleName(Identifier key, ModuleAliasLookupOption option) const {
21222126
auto found = ModuleAliasMap.find(key);
21232127
if (found == ModuleAliasMap.end())

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2284,6 +2284,14 @@ InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName,
22842284
return action(info);
22852285
}
22862286

2287+
static void addModuleAliasesFromExplicitSwiftModuleMap(
2288+
ASTContext &Ctx, llvm::StringMap<std::string> ModuleAliases) {
2289+
for (auto &entry : ModuleAliases) {
2290+
Ctx.addModuleAlias(/*moduleAlias=*/entry.getKey(),
2291+
/*realModule=*/entry.getValue());
2292+
}
2293+
}
2294+
22872295
struct ExplicitSwiftModuleLoader::Implementation {
22882296
ASTContext &Ctx;
22892297
llvm::BumpPtrAllocator Allocator;
@@ -2293,6 +2301,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
22932301
void parseSwiftExplicitModuleMap(StringRef fileName) {
22942302
ExplicitModuleMapParser parser(Allocator);
22952303
llvm::StringMap<ExplicitClangModuleInputInfo> ExplicitClangModuleMap;
2304+
llvm::StringMap<std::string> ModuleAliases;
22962305
// Load the input file.
22972306
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBufOrErr =
22982307
llvm::MemoryBuffer::getFile(fileName);
@@ -2304,7 +2313,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
23042313

23052314
auto hasError = parser.parseSwiftExplicitModuleMap(
23062315
(*fileBufOrErr)->getMemBufferRef(), ExplicitModuleMap,
2307-
ExplicitClangModuleMap);
2316+
ExplicitClangModuleMap, ModuleAliases);
23082317

23092318
if (hasError)
23102319
Ctx.Diags.diagnose(SourceLoc(), diag::explicit_swift_module_map_corrupted,
@@ -2331,6 +2340,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
23312340
.str());
23322341
}
23332342
}
2343+
addModuleAliasesFromExplicitSwiftModuleMap(Ctx, ModuleAliases);
23342344
}
23352345

23362346
void addCommandLineExplicitInputs(
@@ -2563,6 +2573,7 @@ struct ExplicitCASModuleLoader::Implementation {
25632573
void parseSwiftExplicitModuleMap(StringRef ID) {
25642574
ExplicitModuleMapParser parser(Allocator);
25652575
llvm::StringMap<ExplicitClangModuleInputInfo> ExplicitClangModuleMap;
2576+
llvm::StringMap<std::string> ModuleAliases;
25662577
auto buf = loadBuffer(ID);
25672578
if (!buf) {
25682579
Ctx.Diags.diagnose(SourceLoc(), diag::error_cas,
@@ -2578,7 +2589,8 @@ struct ExplicitCASModuleLoader::Implementation {
25782589
llvm::MemoryBuffer::getFile(ID);
25792590

25802591
auto hasError = parser.parseSwiftExplicitModuleMap(
2581-
(*buf)->getMemBufferRef(), ExplicitModuleMap, ExplicitClangModuleMap);
2592+
(*buf)->getMemBufferRef(), ExplicitModuleMap, ExplicitClangModuleMap,
2593+
ModuleAliases);
25822594

25832595
if (hasError)
25842596
Ctx.Diags.diagnose(SourceLoc(), diag::explicit_swift_module_map_corrupted,
@@ -2617,6 +2629,7 @@ struct ExplicitCASModuleLoader::Implementation {
26172629
extraClangArgs.push_back(*cachePath);
26182630
}
26192631
}
2632+
addModuleAliasesFromExplicitSwiftModuleMap(Ctx, ModuleAliases);
26202633
}
26212634

26222635
void addCommandLineExplicitInputs(

lib/Serialization/ScanningLoaders.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ void PlaceholderSwiftModuleScanner::parsePlaceholderModuleMap(
110110
StringRef fileName) {
111111
ExplicitModuleMapParser parser(Allocator);
112112
llvm::StringMap<ExplicitClangModuleInputInfo> ClangDependencyModuleMap;
113+
llvm::StringMap<std::string> ModuleAliases;
113114
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBufOrErr =
114115
llvm::MemoryBuffer::getFile(fileName);
115116
if (!fileBufOrErr) {
@@ -119,7 +120,7 @@ void PlaceholderSwiftModuleScanner::parsePlaceholderModuleMap(
119120
}
120121
auto result = parser.parseSwiftExplicitModuleMap(
121122
(*fileBufOrErr)->getMemBufferRef(), PlaceholderDependencyModuleMap,
122-
ClangDependencyModuleMap);
123+
ClangDependencyModuleMap, ModuleAliases);
123124
if (result == std::errc::invalid_argument) {
124125
Ctx.Diags.diagnose(SourceLoc(),
125126
diag::placeholder_dependency_module_map_corrupted,
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/// Test setting a module alias in the explicit module loader's JSON directly.
2+
// UNSUPPORTED: OS=windows-msvc
3+
// RUN: %empty-directory(%t)
4+
// RUN: mkdir -p %t/inputs
5+
// RUN: mkdir -p %t/outputs
6+
7+
/// Create a module Bar
8+
// RUN: echo 'public func bar() {}' > %t/inputs/FileBar.swift
9+
// RUN: %target-swift-frontend -module-name Bar %t/inputs/FileBar.swift -emit-module -emit-module-path %t/inputs/Bar.swiftmodule
10+
// RUN: %target-swift-emit-pcm -module-name SwiftShims %swift-lib-dir/swift/shims/module.modulemap -o %t/inputs/SwiftShims.pcm
11+
// RUN: %target-swift-emit-pcm -module-name _SwiftConcurrencyShims %swift-lib-dir/swift/shims/module.modulemap -o %t/inputs/_SwiftConcurrencyShims.pcm
12+
13+
/// Check Bar.swiftmodule is created
14+
// RUN: test -f %t/inputs/Bar.swiftmodule
15+
16+
/// Next create an explicit module dependency map to build module Foo
17+
// RUN: echo 'import Cat' > %t/inputs/FileFoo.swift
18+
19+
// RUN: echo "[{" > %/t/inputs/map.json
20+
// RUN: echo "\"moduleName\": \"Bar\"," >> %/t/inputs/map.json
21+
// RUN: echo "\"modulePath\": \"%/t/inputs/Bar.swiftmodule\"," >> %/t/inputs/map.json
22+
// RUN: echo "\"moduleAlias\": \"Cat\"," >> %/t/inputs/map.json
23+
// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json
24+
// RUN: echo "}," >> %/t/inputs/map.json
25+
// RUN: echo "{" >> %/t/inputs/map.json
26+
// RUN: echo "\"moduleName\": \"Swift\"," >> %/t/inputs/map.json
27+
// RUN: echo "\"modulePath\": \"%/stdlib_module\"," >> %/t/inputs/map.json
28+
// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json
29+
// RUN: echo "}," >> %/t/inputs/map.json
30+
// RUN: echo "{" >> %/t/inputs/map.json
31+
// RUN: echo "\"moduleName\": \"SwiftOnoneSupport\"," >> %/t/inputs/map.json
32+
// RUN: echo "\"modulePath\": \"%/ononesupport_module\"," >> %/t/inputs/map.json
33+
// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json
34+
// RUN: echo "}," >> %/t/inputs/map.json
35+
// RUN: echo "{" >> %/t/inputs/map.json
36+
// RUN: echo "\"moduleName\": \"_Concurrency\"," >> %/t/inputs/map.json
37+
// RUN: echo "\"modulePath\": \"%/concurrency_module\"," >> %/t/inputs/map.json
38+
// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json
39+
// RUN: echo "}," >> %/t/inputs/map.json
40+
// RUN: echo "{" >> %/t/inputs/map.json
41+
// RUN: echo "\"moduleName\": \"SwiftShims\"," >> %/t/inputs/map.json
42+
// RUN: echo "\"isFramework\": false," >> %/t/inputs/map.json
43+
// RUN: echo "\"clangModuleMapPath\": \"%swift-lib-dir/swift/shims/module.modulemap\"," >> %/t/inputs/map.json
44+
// RUN: echo "\"clangModulePath\": \"%t/inputs/SwiftShims.pcm\"" >> %/t/inputs/map.json
45+
// RUN: echo "}," >> %/t/inputs/map.json
46+
// RUN: echo "{" >> %/t/inputs/map.json
47+
// RUN: echo "\"moduleName\": \"_SwiftConcurrencyShims\"," >> %/t/inputs/map.json
48+
// RUN: echo "\"isFramework\": false," >> %/t/inputs/map.json
49+
// RUN: echo "\"clangModuleMapPath\": \"%swift-lib-dir/swift/shims/module.modulemap\"," >> %/t/inputs/map.json
50+
// RUN: echo "\"clangModulePath\": \"%t/inputs/_SwiftConcurrencyShims.pcm\"" >> %/t/inputs/map.json
51+
// RUN: echo "}," >> %/t/inputs/map.json
52+
// RUN: echo "{" >> %/t/inputs/map.json
53+
// RUN: echo "\"moduleName\": \"_StringProcessing\"," >> %/t/inputs/map.json
54+
// RUN: echo "\"modulePath\": \"%/string_processing_module\"," >> %/t/inputs/map.json
55+
// RUN: echo "\"isFramework\": false" >> %/t/inputs/map.json
56+
// RUN: echo "}]" >> %/t/inputs/map.json
57+
58+
/// Create a module Foo that imports Cat aliased to Bar in the JSON above
59+
// RUN: %target-swift-frontend -module-name Foo %t/inputs/FileFoo.swift -I %t/inputs -emit-module -emit-module-path %t/outputs/Foo.swiftmodule -disable-implicit-swift-modules -explicit-swift-module-map-file %t/inputs/map.json -Rmodule-loading 2> %t/outputs/load-result.output
60+
61+
// RUN: test -f %t/outputs/Foo.swiftmodule
62+
// RUN: test -f %t/inputs/Bar.swiftmodule
63+
// RUN: not test -f %t/inputs/Cat.swiftmodule
64+
65+
// RUN: %FileCheck %s -input-file %t/outputs/load-result.output -check-prefix CHECK
66+
// CHECK: remark: loaded module {{.*}}Bar.swiftmodule

0 commit comments

Comments
 (0)