Skip to content

Commit f9b64be

Browse files
authored
Merge pull request #70817 from artemcm/SerializeInterfacePathWhenBuildBinaryModule
[Serialization] Always serialize module-defining `.swiftinterface`, even if SDK-relative.
2 parents 7e8d8e5 + de626ab commit f9b64be

File tree

6 files changed

+106
-4
lines changed

6 files changed

+106
-4
lines changed

lib/Frontend/ModuleInterfaceBuilder.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,12 @@ std::error_code ExplicitModuleInterfaceBuilder::buildSwiftModuleFromInterface(
275275
!Invocation.getIRGenOptions().ForceLoadSymbolName.empty();
276276
SerializationOpts.UserModuleVersion = FEOpts.UserModuleVersion;
277277
SerializationOpts.AllowableClients = FEOpts.AllowableClients;
278-
279-
// Record any non-SDK module interface files for the debug info.
280278
StringRef SDKPath = Instance.getASTContext().SearchPathOpts.getSDKPath();
281-
if (!getRelativeDepPath(InPath, SDKPath))
279+
280+
auto SDKRelativePath = getRelativeDepPath(InPath, SDKPath);
281+
if (SDKRelativePath.has_value())
282+
SerializationOpts.ModuleInterface = SDKRelativePath.value();
283+
else
282284
SerializationOpts.ModuleInterface = InPath;
283285

284286
SerializationOpts.SDKName = Instance.getASTContext().LangOpts.SDKName;

lib/Serialization/ModuleFile.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,19 @@ static bool isTargetTooNew(const llvm::Triple &moduleTarget,
9191
return ctxTarget.isOSVersionLT(moduleTarget);
9292
}
9393

94+
std::string ModuleFile::resolveModuleDefiningFilename(const ASTContext &ctx) {
95+
if (!Core->ModuleInterfacePath.empty()) {
96+
std::string interfacePath = Core->ModuleInterfacePath.str();
97+
if (llvm::sys::path::is_relative(interfacePath)) {
98+
SmallString<128> absoluteInterfacePath(ctx.SearchPathOpts.getSDKPath());
99+
llvm::sys::path::append(absoluteInterfacePath, interfacePath);
100+
return absoluteInterfacePath.str().str();
101+
} else
102+
return interfacePath;
103+
} else
104+
return getModuleLoadedFilename().str();
105+
}
106+
94107
namespace swift {
95108
namespace serialization {
96109
bool areCompatible(const llvm::Triple &moduleTarget,
@@ -257,6 +270,8 @@ Status ModuleFile::associateWithFileContext(FileUnit *file, SourceLoc diagLoc,
257270
}
258271

259272
ASTContext &ctx = getContext();
273+
// Resolve potentially-SDK-relative module-defining .swiftinterface path
274+
ResolvedModuleDefiningFilename = resolveModuleDefiningFilename(ctx);
260275

261276
llvm::Triple moduleTarget(llvm::Triple::normalize(Core->TargetTriple));
262277
if (!areCompatible(moduleTarget, ctx.LangOpts.Target)) {

lib/Serialization/ModuleFile.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ class ModuleFile
7474
/// The module that this module is an overlay of, if any.
7575
ModuleDecl *UnderlyingModule = nullptr;
7676

77+
/// Once this module file has been associated with the AST node representing
78+
/// it, resolve the potentially-SDK-relative module-defining `.swiftinterface`
79+
/// path to an absolute path.
80+
llvm::Optional<std::string> ResolvedModuleDefiningFilename;
81+
7782
/// The cursor used to lazily load things from the file.
7883
llvm::BitstreamCursor DeclTypeCursor;
7984

@@ -280,6 +285,10 @@ class ModuleFile
280285
ArrayRef<ProtocolConformanceID>
281286
claimLazyConformanceLoaderToken(uint64_t token);
282287

288+
/// If the module-defining `.swiftinterface` file is an SDK-relative path,
289+
/// resolve it to be absolute to the context's SDK.
290+
std::string resolveModuleDefiningFilename(const ASTContext &ctx);
291+
283292
/// Represents an identifier that may or may not have been deserialized yet.
284293
///
285294
/// If \c Ident is empty, the identifier has not been loaded yet.
@@ -849,6 +858,8 @@ class ModuleFile
849858
void getDisplayDecls(SmallVectorImpl<Decl*> &results, bool recursive = false);
850859

851860
StringRef getModuleFilename() const {
861+
if (ResolvedModuleDefiningFilename)
862+
return ResolvedModuleDefiningFilename.value();
852863
if (!Core->ModuleInterfacePath.empty())
853864
return Core->ModuleInterfacePath;
854865
return getModuleLoadedFilename();

lib/Serialization/ModuleFormat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ const uint16_t SWIFTMODULE_VERSION_MAJOR = 0;
5858
/// describe what change you made. The content of this comment isn't important;
5959
/// it just ensures a conflict if two people change the module format.
6060
/// Don't worry about adhering to the 80-column limit for this line.
61-
const uint16_t SWIFTMODULE_VERSION_MINOR = 833; // global_addr with dependency token
61+
const uint16_t SWIFTMODULE_VERSION_MINOR = 834; // relative paths to module-defining .swiftinterface files
6262

6363
/// A standard hash seed used for all string hashes in a serialized module.
6464
///
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/inputs)
3+
// RUN: %empty-directory(%t/test-sdk)
4+
// RUN: %empty-directory(%t/test-sdk/usr/lib/swift)
5+
// RUN: cp -r %platform-module-dir/Swift.swiftmodule %t/test-sdk/usr/lib/swift/Swift.swiftmodule
6+
7+
// RUN: %empty-directory(%t/test-sdk/usr/lib/Foo.swiftmodule)
8+
// RUN: split-file %s %t
9+
10+
// --- Verify that a non-SDK module gets its absolute path serialized into the binary '.swiftmodule'
11+
// RUN: %target-swift-frontend -compile-module-from-interface -module-name Foo %t/modules/Foo.swiftinterface -o %t/inputs/FreestandingFoo.swiftmodule
12+
// RUN: llvm-bcanalyzer -dump %t/inputs/FreestandingFoo.swiftmodule > %t/Foo.freestanding.moduledump.txt
13+
// RUN: cat %t/Foo.freestanding.moduledump.txt | %FileCheck %s -check-prefix CHECK-FREESTANDING-FOO
14+
15+
// --- Verify that an SDK module gets its SDK-relative path serialized into the binary '.swiftmodule'
16+
// RUN: cp %t/modules/Foo.swiftinterface %t/test-sdk/usr/lib/Foo.swiftmodule
17+
// RUN: %target-swift-frontend(mock-sdk: -sdk %t/test-sdk) -compile-module-from-interface -module-name Foo %t/test-sdk/usr/lib/Foo.swiftmodule/Foo.swiftinterface -o %t/inputs/Foo.swiftmodule
18+
// RUN: llvm-bcanalyzer -dump %t/inputs/Foo.swiftmodule > %t/Foo.sdk.moduledump.txt
19+
// RUN: cat %t/Foo.sdk.moduledump.txt | %FileCheck %s -check-prefix CHECK-SDK-FOO
20+
21+
// CHECK-FREESTANDING-FOO: <MODULE_INTERFACE_PATH abbrevid={{[0-9]+}}/> blob data = '{{.*}}{{/|\\}}modules{{/|\\}}Foo.swiftinterface'
22+
// CHECK-SDK-FOO: <MODULE_INTERFACE_PATH abbrevid={{[0-9]+}}/> blob data = 'usr/lib/Foo.swiftmodule/Foo.swiftinterface'
23+
24+
//--- modules/Foo.swiftinterface
25+
// swift-interface-format-version: 1.0
26+
// swift-module-flags: -module-name Foo
27+
public func foo()
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %empty-directory(%t/inputs)
3+
// RUN: %empty-directory(%t/test-sdk)
4+
// RUN: %empty-directory(%t/test-sdk/usr/lib/swift)
5+
// RUN: %empty-directory(%t/test-sdk/usr/lib/Foo.swiftmodule)
6+
// RUN: %empty-directory(%t/test-sdk/usr/lib/Bar.swiftmodule)
7+
// RUN: %empty-directory(%t/test-sdk/usr/lib/_Foo_Bar.swiftmodule)
8+
// RUN: %empty-directory(%t/test-sdk/usr/lib/Foo.swiftcrossimport)
9+
// RUN: cp -r %platform-module-dir/Swift.swiftmodule %t/test-sdk/usr/lib/swift/Swift.swiftmodule
10+
11+
// RUN: split-file %s %t
12+
13+
// --- Precompile interfaces from the "SDK" into binary modules distributed elsewhere
14+
// RUN: %target-swift-frontend(mock-sdk: -sdk %t/test-sdk) -compile-module-from-interface -module-name Foo %t/test-sdk/usr/lib/Foo.swiftmodule/Foo.swiftinterface -o %t/inputs/Foo.swiftmodule
15+
// RUN: %target-swift-frontend(mock-sdk: -sdk %t/test-sdk) -compile-module-from-interface -module-name Bar %t/test-sdk/usr/lib/Bar.swiftmodule/Bar.swiftinterface -o %t/inputs/Bar.swiftmodule
16+
// RUN: %target-swift-frontend(mock-sdk: -sdk %t/test-sdk) -compile-module-from-interface -module-name _Foo_Bar %t/test-sdk/usr/lib/_Foo_Bar.swiftmodule/_Foo_Bar.swiftinterface -o %t/inputs/_Foo_Bar.swiftmodule
17+
18+
// --- Verify that the client is able to resolve the cross-import overlay from the defining interface SDK location
19+
// RUN: %target-swift-frontend(mock-sdk: -sdk %t/test-sdk) -typecheck %t/Test.swift -enable-cross-import-overlays -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -I %t/inputs -Rmodule-loading &> %t/module_remarks.txt
20+
// RUN: cat %t/module_remarks.txt | %FileCheck %s
21+
// CHECK: remark: loaded module '_Foo_Bar'
22+
23+
//--- test-sdk/usr/lib/Foo.swiftmodule/Foo.swiftinterface
24+
// swift-interface-format-version: 1.0
25+
// swift-module-flags: -module-name Foo
26+
public func foo()
27+
28+
//--- test-sdk/usr/lib/Bar.swiftmodule/Bar.swiftinterface
29+
// swift-interface-format-version: 1.0
30+
// swift-module-flags: -module-name Bar
31+
public func bar()
32+
33+
//--- test-sdk/usr/lib/_Foo_Bar.swiftmodule/_Foo_Bar.swiftinterface
34+
// swift-interface-format-version: 1.0
35+
// swift-module-flags: -module-name _Foo_Bar
36+
public func foo_bar()
37+
38+
//--- test-sdk/usr/lib/Foo.swiftcrossimport/Bar.swiftoverlay
39+
---
40+
version: 1
41+
modules:
42+
- name: _Foo_Bar
43+
44+
//--- Test.swift
45+
import Foo
46+
import Bar
47+
public func baz() { foo_bar() }

0 commit comments

Comments
 (0)