10
10
//
11
11
// ===----------------------------------------------------------------------===//
12
12
13
+ #include " swift/Basic/Platform.h"
13
14
#include " swift/Serialization/SerializedModuleLoader.h"
14
15
#include " swift/AST/ASTContext.h"
15
16
#include " swift/AST/DiagnosticSuppression.h"
@@ -21,6 +22,92 @@ using namespace swift;
21
22
using llvm::ErrorOr;
22
23
23
24
namespace {
25
+ static Optional<StringRef>
26
+ computePrebuiltModulePathDefault (ASTContext &ctx,
27
+ StringRef interfacePath,
28
+ StringRef prebuiltCacheDir,
29
+ StringRef moduleName,
30
+ StringRef modulePath,
31
+ llvm::SmallString<256 > &scratch) {
32
+ namespace path = llvm::sys::path;
33
+ StringRef sdkPath = ctx.SearchPathOpts .SDKPath ;
34
+ auto &fs = *ctx.SourceMgr .getFileSystem ();
35
+ // Check if the interface file comes from the SDK
36
+ if (sdkPath.empty () || !hasPrefix (path::begin (interfacePath),
37
+ path::end (interfacePath),
38
+ path::begin (sdkPath),
39
+ path::end (sdkPath)))
40
+ return None;
41
+
42
+ // Assemble the expected path: $PREBUILT_CACHE/Foo.swiftmodule or
43
+ // $PREBUILT_CACHE/Foo.swiftmodule/arch.swiftmodule. Note that there's no
44
+ // cache key here.
45
+ scratch = prebuiltCacheDir;
46
+
47
+ // FIXME: Would it be possible to only have architecture-specific names
48
+ // here? Then we could skip this check.
49
+ StringRef inParentDirName =
50
+ path::filename (path::parent_path (interfacePath));
51
+ if (path::extension (inParentDirName) == " .swiftmodule" ) {
52
+ assert (path::stem (inParentDirName) == moduleName);
53
+ path::append (scratch, inParentDirName);
54
+ }
55
+ path::append (scratch, path::filename (modulePath));
56
+
57
+ // If there isn't a file at this location, skip returning a path.
58
+ if (!fs.exists (scratch))
59
+ return None;
60
+
61
+ return scratch.str ();
62
+ }
63
+
64
+ // / Hack to deal with build systems (including the Swift standard library, at
65
+ // / the time of this comment) that aren't yet using target-specific names for
66
+ // / multi-target swiftmodules, in case the prebuilt cache is.
67
+ static Optional<StringRef>
68
+ computeFallbackPrebuiltModulePath (ASTContext &ctx,
69
+ StringRef interfacePath,
70
+ StringRef prebuiltCacheDir,
71
+ StringRef moduleName,
72
+ StringRef modulePath,
73
+ llvm::SmallString<256 > &scratch) {
74
+ namespace path = llvm::sys::path;
75
+ StringRef sdkPath = ctx.SearchPathOpts .SDKPath ;
76
+ auto &fs = *ctx.SourceMgr .getFileSystem ();
77
+
78
+ // Check if the interface file comes from the SDK
79
+ if (sdkPath.empty () || !hasPrefix (path::begin (interfacePath),
80
+ path::end (interfacePath),
81
+ path::begin (sdkPath),
82
+ path::end (sdkPath)))
83
+ return None;
84
+
85
+ // If the module isn't target-specific, there's no fallback path.
86
+ StringRef inParentDirName =
87
+ path::filename (path::parent_path (interfacePath));
88
+ if (path::extension (inParentDirName) != " .swiftmodule" )
89
+ return None;
90
+
91
+ // If the interface is already using the target-specific name, there's
92
+ // nothing else to try.
93
+ auto normalizedTarget = getTargetSpecificModuleTriple (ctx.LangOpts .Target );
94
+ if (path::stem (modulePath) == normalizedTarget.str ())
95
+ return None;
96
+
97
+ // Assemble the expected path:
98
+ // $PREBUILT_CACHE/Foo.swiftmodule/target.swiftmodule. Note that there's no
99
+ // cache key here.
100
+ scratch = prebuiltCacheDir;
101
+ path::append (scratch, inParentDirName);
102
+ path::append (scratch, normalizedTarget.str ());
103
+ scratch += " .swiftmodule" ;
104
+
105
+ // If there isn't a file at this location, skip returning a path.
106
+ if (!fs.exists (scratch))
107
+ return None;
108
+
109
+ return scratch.str ();
110
+ }
24
111
25
112
// / A module "loader" that looks for .swiftinterface and .swiftmodule files
26
113
// / for the purpose of determining dependencies, but does not attempt to
@@ -94,6 +181,28 @@ class ModuleDependencyScanner : public SerializedModuleLoaderBase {
94
181
};
95
182
}
96
183
184
+ Optional<StringRef>
185
+ swift::computePrebuiltModulePath (ASTContext &ctx,
186
+ StringRef interfacePath,
187
+ StringRef prebuiltCacheDir,
188
+ StringRef moduleName,
189
+ llvm::SmallString<256 > &scratch) {
190
+ llvm::SmallString<64 > modulePath = llvm::sys::path::filename (interfacePath);
191
+ llvm::sys::path::replace_extension (modulePath,
192
+ file_types::getExtension (file_types::TY_SwiftModuleFile));
193
+ auto defaultPath =
194
+ computePrebuiltModulePathDefault (ctx, interfacePath, prebuiltCacheDir,
195
+ moduleName, modulePath, scratch);
196
+ if (defaultPath.hasValue ())
197
+ return defaultPath;
198
+ else
199
+ return computeFallbackPrebuiltModulePath (ctx, interfacePath,
200
+ prebuiltCacheDir,
201
+ moduleName,
202
+ modulePath,
203
+ scratch);
204
+ }
205
+
97
206
ErrorOr<ModuleDependencies> ModuleDependencyScanner::scanInterfaceFile (
98
207
Twine moduleInterfacePath) {
99
208
// Create a module filename.
0 commit comments