Skip to content

Commit cd7ed4e

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 8cf352b commit cd7ed4e

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
@@ -603,6 +603,10 @@ class ASTContext final {
603603
/// are the real (physical) module names on disk.
604604
void setModuleAliases(const llvm::StringMap<StringRef> &aliasMap);
605605

606+
/// Adds a given alias to the map of Identifiers between module aliases and
607+
/// their actual names.
608+
void addModuleAlias(StringRef moduleAlias, StringRef realName);
609+
606610
/// Look up option used in \c getRealModuleName when module aliasing is applied.
607611
enum class ModuleAliasLookupOption {
608612
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;
@@ -439,6 +446,9 @@ class ExplicitModuleMapParser {
439446
clangModuleCacheKey);
440447
didInsert = clangModuleMap.try_emplace(moduleName, std::move(entry)).second;
441448
}
449+
if (didInsert && moduleAlias.has_value()) {
450+
moduleAliases[*moduleAlias] = moduleName;
451+
}
442452
// Prevent duplicate module names.
443453
return !didInsert;
444454
}

lib/AST/ASTContext.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2130,16 +2130,20 @@ void ASTContext::setModuleAliases(const llvm::StringMap<StringRef> &aliasMap) {
21302130
for (auto k: aliasMap.keys()) {
21312131
auto v = aliasMap.lookup(k);
21322132
if (!v.empty()) {
2133-
auto key = getIdentifier(k);
2134-
auto val = getIdentifier(v);
2135-
// key is a module alias, val is its corresponding real name
2136-
ModuleAliasMap[key] = std::make_pair(val, true);
2137-
// add an entry with an alias as key for an easier lookup later
2138-
ModuleAliasMap[val] = std::make_pair(key, false);
2133+
addModuleAlias(k, v);
21392134
}
21402135
}
21412136
}
21422137

2138+
void ASTContext::addModuleAlias(StringRef moduleAlias, StringRef realName) {
2139+
auto key = getIdentifier(moduleAlias);
2140+
auto val = getIdentifier(realName);
2141+
// key is a module alias, val is its corresponding real name
2142+
ModuleAliasMap[key] = std::make_pair(val, true);
2143+
// add an entry with an alias as key for an easier lookup later
2144+
ModuleAliasMap[val] = std::make_pair(key, false);
2145+
}
2146+
21432147
Identifier ASTContext::getRealModuleName(Identifier key, ModuleAliasLookupOption option) const {
21442148
auto found = ModuleAliasMap.find(key);
21452149
if (found == ModuleAliasMap.end())

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2297,6 +2297,14 @@ InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName,
22972297
return action(info);
22982298
}
22992299

2300+
static void addModuleAliasesFromExplicitSwiftModuleMap(
2301+
ASTContext &Ctx, llvm::StringMap<std::string> ModuleAliases) {
2302+
for (auto &entry : ModuleAliases) {
2303+
Ctx.addModuleAlias(/*moduleAlias=*/entry.getKey(),
2304+
/*realModule=*/entry.getValue());
2305+
}
2306+
}
2307+
23002308
struct ExplicitSwiftModuleLoader::Implementation {
23012309
ASTContext &Ctx;
23022310
llvm::BumpPtrAllocator Allocator;
@@ -2306,6 +2314,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
23062314
void parseSwiftExplicitModuleMap(StringRef fileName) {
23072315
ExplicitModuleMapParser parser(Allocator);
23082316
llvm::StringMap<ExplicitClangModuleInputInfo> ExplicitClangModuleMap;
2317+
llvm::StringMap<std::string> ModuleAliases;
23092318
// Load the input file.
23102319
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBufOrErr =
23112320
llvm::MemoryBuffer::getFile(fileName);
@@ -2317,7 +2326,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
23172326

23182327
auto hasError = parser.parseSwiftExplicitModuleMap(
23192328
(*fileBufOrErr)->getMemBufferRef(), ExplicitModuleMap,
2320-
ExplicitClangModuleMap);
2329+
ExplicitClangModuleMap, ModuleAliases);
23212330

23222331
if (hasError)
23232332
Ctx.Diags.diagnose(SourceLoc(), diag::explicit_swift_module_map_corrupted,
@@ -2344,6 +2353,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
23442353
.str());
23452354
}
23462355
}
2356+
addModuleAliasesFromExplicitSwiftModuleMap(Ctx, ModuleAliases);
23472357
}
23482358

23492359
void addCommandLineExplicitInputs(
@@ -2576,6 +2586,7 @@ struct ExplicitCASModuleLoader::Implementation {
25762586
void parseSwiftExplicitModuleMap(StringRef ID) {
25772587
ExplicitModuleMapParser parser(Allocator);
25782588
llvm::StringMap<ExplicitClangModuleInputInfo> ExplicitClangModuleMap;
2589+
llvm::StringMap<std::string> ModuleAliases;
25792590
auto buf = loadBuffer(ID);
25802591
if (!buf) {
25812592
Ctx.Diags.diagnose(SourceLoc(), diag::error_cas,
@@ -2591,7 +2602,8 @@ struct ExplicitCASModuleLoader::Implementation {
25912602
llvm::MemoryBuffer::getFile(ID);
25922603

25932604
auto hasError = parser.parseSwiftExplicitModuleMap(
2594-
(*buf)->getMemBufferRef(), ExplicitModuleMap, ExplicitClangModuleMap);
2605+
(*buf)->getMemBufferRef(), ExplicitModuleMap, ExplicitClangModuleMap,
2606+
ModuleAliases);
25952607

25962608
if (hasError)
25972609
Ctx.Diags.diagnose(SourceLoc(), diag::explicit_swift_module_map_corrupted,
@@ -2630,6 +2642,7 @@ struct ExplicitCASModuleLoader::Implementation {
26302642
extraClangArgs.push_back(*cachePath);
26312643
}
26322644
}
2645+
addModuleAliasesFromExplicitSwiftModuleMap(Ctx, ModuleAliases);
26332646
}
26342647

26352648
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)