Skip to content

Commit 60513d7

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 de6ccb3 commit 60513d7

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

611+
/// Adds a given alias to the map of Identifiers between module aliases and
612+
/// their actual names.
613+
void addModuleAlias(StringRef moduleAlias, StringRef realName);
614+
611615
/// Look up option used in \c getRealModuleName when module aliasing is applied.
612616
enum class ModuleAliasLookupOption {
613617
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
@@ -2139,16 +2139,20 @@ void ASTContext::setModuleAliases(const llvm::StringMap<StringRef> &aliasMap) {
21392139
for (auto k: aliasMap.keys()) {
21402140
auto v = aliasMap.lookup(k);
21412141
if (!v.empty()) {
2142-
auto key = getIdentifier(k);
2143-
auto val = getIdentifier(v);
2144-
// key is a module alias, val is its corresponding real name
2145-
ModuleAliasMap[key] = std::make_pair(val, true);
2146-
// add an entry with an alias as key for an easier lookup later
2147-
ModuleAliasMap[val] = std::make_pair(key, false);
2142+
addModuleAlias(k, v);
21482143
}
21492144
}
21502145
}
21512146

2147+
void ASTContext::addModuleAlias(StringRef moduleAlias, StringRef realName) {
2148+
auto key = getIdentifier(moduleAlias);
2149+
auto val = getIdentifier(realName);
2150+
// key is a module alias, val is its corresponding real name
2151+
ModuleAliasMap[key] = std::make_pair(val, true);
2152+
// add an entry with an alias as key for an easier lookup later
2153+
ModuleAliasMap[val] = std::make_pair(key, false);
2154+
}
2155+
21522156
Identifier ASTContext::getRealModuleName(Identifier key, ModuleAliasLookupOption option) const {
21532157
auto found = ModuleAliasMap.find(key);
21542158
if (found == ModuleAliasMap.end())

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2158,6 +2158,14 @@ InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName,
21582158
return action(info);
21592159
}
21602160

2161+
static void addModuleAliasesFromExplicitSwiftModuleMap(
2162+
ASTContext &Ctx, llvm::StringMap<std::string> ModuleAliases) {
2163+
for (auto &entry : ModuleAliases) {
2164+
Ctx.addModuleAlias(/*moduleAlias=*/entry.getKey(),
2165+
/*realModule=*/entry.getValue());
2166+
}
2167+
}
2168+
21612169
struct ExplicitSwiftModuleLoader::Implementation {
21622170
ASTContext &Ctx;
21632171
llvm::BumpPtrAllocator Allocator;
@@ -2167,6 +2175,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
21672175
void parseSwiftExplicitModuleMap(StringRef fileName) {
21682176
ExplicitModuleMapParser parser(Allocator);
21692177
llvm::StringMap<ExplicitClangModuleInputInfo> ExplicitClangModuleMap;
2178+
llvm::StringMap<std::string> ModuleAliases;
21702179
// Load the input file.
21712180
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBufOrErr =
21722181
llvm::MemoryBuffer::getFile(fileName);
@@ -2178,7 +2187,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
21782187

21792188
auto hasError = parser.parseSwiftExplicitModuleMap(
21802189
(*fileBufOrErr)->getMemBufferRef(), ExplicitModuleMap,
2181-
ExplicitClangModuleMap);
2190+
ExplicitClangModuleMap, ModuleAliases);
21822191

21832192
if (hasError)
21842193
Ctx.Diags.diagnose(SourceLoc(), diag::explicit_swift_module_map_corrupted,
@@ -2205,6 +2214,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
22052214
.str());
22062215
}
22072216
}
2217+
addModuleAliasesFromExplicitSwiftModuleMap(Ctx, ModuleAliases);
22082218
}
22092219

22102220
void addCommandLineExplicitInputs(
@@ -2437,6 +2447,7 @@ struct ExplicitCASModuleLoader::Implementation {
24372447
void parseSwiftExplicitModuleMap(StringRef ID) {
24382448
ExplicitModuleMapParser parser(Allocator);
24392449
llvm::StringMap<ExplicitClangModuleInputInfo> ExplicitClangModuleMap;
2450+
llvm::StringMap<std::string> ModuleAliases;
24402451
auto buf = loadBuffer(ID);
24412452
if (!buf) {
24422453
Ctx.Diags.diagnose(SourceLoc(), diag::error_cas,
@@ -2452,7 +2463,8 @@ struct ExplicitCASModuleLoader::Implementation {
24522463
llvm::MemoryBuffer::getFile(ID);
24532464

24542465
auto hasError = parser.parseSwiftExplicitModuleMap(
2455-
(*buf)->getMemBufferRef(), ExplicitModuleMap, ExplicitClangModuleMap);
2466+
(*buf)->getMemBufferRef(), ExplicitModuleMap, ExplicitClangModuleMap,
2467+
ModuleAliases);
24562468

24572469
if (hasError)
24582470
Ctx.Diags.diagnose(SourceLoc(), diag::explicit_swift_module_map_corrupted,
@@ -2491,6 +2503,7 @@ struct ExplicitCASModuleLoader::Implementation {
24912503
extraClangArgs.push_back(*cachePath);
24922504
}
24932505
}
2506+
addModuleAliasesFromExplicitSwiftModuleMap(Ctx, ModuleAliases);
24942507
}
24952508

24962509
void addCommandLineExplicitInputs(

lib/Serialization/ScanningLoaders.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ void PlaceholderSwiftModuleScanner::parsePlaceholderModuleMap(
112112
StringRef fileName) {
113113
ExplicitModuleMapParser parser(Allocator);
114114
llvm::StringMap<ExplicitClangModuleInputInfo> ClangDependencyModuleMap;
115+
llvm::StringMap<std::string> ModuleAliases;
115116
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBufOrErr =
116117
llvm::MemoryBuffer::getFile(fileName);
117118
if (!fileBufOrErr) {
@@ -121,7 +122,7 @@ void PlaceholderSwiftModuleScanner::parsePlaceholderModuleMap(
121122
}
122123
auto result = parser.parseSwiftExplicitModuleMap(
123124
(*fileBufOrErr)->getMemBufferRef(), PlaceholderDependencyModuleMap,
124-
ClangDependencyModuleMap);
125+
ClangDependencyModuleMap, ModuleAliases);
125126
if (result == std::errc::invalid_argument) {
126127
Ctx.Diags.diagnose(SourceLoc(),
127128
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)