Skip to content

Commit 6328a04

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 bfc072f commit 6328a04

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

607+
/// Adds a given alias to the map of Identifiers between module aliases and
608+
/// their actual names.
609+
void addModuleAlias(StringRef moduleAlias, StringRef realName);
610+
607611
/// Look up option used in \c getRealModuleName when module aliasing is applied.
608612
enum class ModuleAliasLookupOption {
609613
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
@@ -2293,6 +2293,14 @@ InterfaceSubContextDelegateImpl::runInSubCompilerInstance(StringRef moduleName,
22932293
return action(info);
22942294
}
22952295

2296+
static void addModuleAliasesFromExplicitSwiftModuleMap(
2297+
ASTContext &Ctx, llvm::StringMap<std::string> ModuleAliases) {
2298+
for (auto &entry : ModuleAliases) {
2299+
Ctx.addModuleAlias(/*moduleAlias=*/entry.getKey(),
2300+
/*realModule=*/entry.getValue());
2301+
}
2302+
}
2303+
22962304
struct ExplicitSwiftModuleLoader::Implementation {
22972305
ASTContext &Ctx;
22982306
llvm::BumpPtrAllocator Allocator;
@@ -2302,6 +2310,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
23022310
void parseSwiftExplicitModuleMap(StringRef fileName) {
23032311
ExplicitModuleMapParser parser(Allocator);
23042312
llvm::StringMap<ExplicitClangModuleInputInfo> ExplicitClangModuleMap;
2313+
llvm::StringMap<std::string> ModuleAliases;
23052314
// Load the input file.
23062315
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBufOrErr =
23072316
llvm::MemoryBuffer::getFile(fileName);
@@ -2313,7 +2322,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
23132322

23142323
auto hasError = parser.parseSwiftExplicitModuleMap(
23152324
(*fileBufOrErr)->getMemBufferRef(), ExplicitModuleMap,
2316-
ExplicitClangModuleMap);
2325+
ExplicitClangModuleMap, ModuleAliases);
23172326

23182327
if (hasError)
23192328
Ctx.Diags.diagnose(SourceLoc(), diag::explicit_swift_module_map_corrupted,
@@ -2340,6 +2349,7 @@ struct ExplicitSwiftModuleLoader::Implementation {
23402349
.str());
23412350
}
23422351
}
2352+
addModuleAliasesFromExplicitSwiftModuleMap(Ctx, ModuleAliases);
23432353
}
23442354

23452355
void addCommandLineExplicitInputs(
@@ -2572,6 +2582,7 @@ struct ExplicitCASModuleLoader::Implementation {
25722582
void parseSwiftExplicitModuleMap(StringRef ID) {
25732583
ExplicitModuleMapParser parser(Allocator);
25742584
llvm::StringMap<ExplicitClangModuleInputInfo> ExplicitClangModuleMap;
2585+
llvm::StringMap<std::string> ModuleAliases;
25752586
auto buf = loadBuffer(ID);
25762587
if (!buf) {
25772588
Ctx.Diags.diagnose(SourceLoc(), diag::error_cas,
@@ -2587,7 +2598,8 @@ struct ExplicitCASModuleLoader::Implementation {
25872598
llvm::MemoryBuffer::getFile(ID);
25882599

25892600
auto hasError = parser.parseSwiftExplicitModuleMap(
2590-
(*buf)->getMemBufferRef(), ExplicitModuleMap, ExplicitClangModuleMap);
2601+
(*buf)->getMemBufferRef(), ExplicitModuleMap, ExplicitClangModuleMap,
2602+
ModuleAliases);
25912603

25922604
if (hasError)
25932605
Ctx.Diags.diagnose(SourceLoc(), diag::explicit_swift_module_map_corrupted,
@@ -2626,6 +2638,7 @@ struct ExplicitCASModuleLoader::Implementation {
26262638
extraClangArgs.push_back(*cachePath);
26272639
}
26282640
}
2641+
addModuleAliasesFromExplicitSwiftModuleMap(Ctx, ModuleAliases);
26292642
}
26302643

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