@@ -44,6 +44,149 @@ SerializedModuleLoader::~SerializedModuleLoader() = default;
44
44
MemoryBufferSerializedModuleLoader::~MemoryBufferSerializedModuleLoader () =
45
45
default ;
46
46
47
+ void SerializedModuleLoaderBase::collectVisibleTopLevelModuleNamesImpl (
48
+ SmallVectorImpl<Identifier> &names, StringRef extension) const {
49
+ llvm::SmallString<16 > moduleSuffix;
50
+ moduleSuffix += ' .' ;
51
+ moduleSuffix += file_types::getExtension (file_types::TY_SwiftModuleFile);
52
+
53
+ llvm::SmallString<16 > suffix;
54
+ suffix += ' .' ;
55
+ suffix += extension;
56
+
57
+ SmallVector<SmallString<64 >, 3 > targetFiles;
58
+ targetFiles.emplace_back (
59
+ getTargetSpecificModuleTriple (Ctx.LangOpts .Target ).str ());
60
+ targetFiles.back () += suffix;
61
+ targetFiles.emplace_back (Ctx.LangOpts .Target .getArchName ());
62
+ targetFiles.back () += suffix;
63
+
64
+ auto &fs = *Ctx.SourceMgr .getFileSystem ();
65
+
66
+ // Apply \p body for each directory entry in \p dirPath.
67
+ auto forEachDirectoryEntryPath =
68
+ [&](StringRef dirPath, llvm::function_ref<void (StringRef)> body) {
69
+ std::error_code errorCode;
70
+ llvm::vfs::directory_iterator DI = fs.dir_begin (dirPath, errorCode);
71
+ llvm::vfs::directory_iterator End;
72
+ for (; !errorCode && DI != End; DI.increment (errorCode))
73
+ body (DI->path ());
74
+ };
75
+
76
+ // Check whether target specific module file exists or not in given directory.
77
+ // $PATH/{arch}.{extension}
78
+ auto checkTargetFiles = [&](StringRef path) -> bool {
79
+ llvm::SmallString<256 > scratch;
80
+ for (auto targetFile : targetFiles) {
81
+ scratch.clear ();
82
+ llvm::sys::path::append (scratch, path, targetFile);
83
+ // If {arch}.{extension} exists, consider it's visible. Technically, we
84
+ // should check the file type, permission, format, etc., but it's too
85
+ // heavy to do that for each files.
86
+ if (fs.exists (scratch))
87
+ return true ;
88
+ }
89
+ return false ;
90
+ };
91
+
92
+ auto tryImportSearchPath = [&](StringRef searchPath) {
93
+ // Look for:
94
+ // $PATH/{name}.swiftmodule/{arch}.{extension} ; Or
95
+ // $PATH/{name}.{extension}
96
+ forEachDirectoryEntryPath (searchPath, [&](StringRef path) {
97
+ auto pathExt = llvm::sys::path::extension (path);
98
+ if (pathExt != moduleSuffix && pathExt != suffix)
99
+ return ;
100
+
101
+ auto stat = fs.status (path);
102
+ if (!stat)
103
+ return ;
104
+ if (pathExt == moduleSuffix && stat->isDirectory ()) {
105
+ if (!checkTargetFiles (path))
106
+ return ;
107
+ } else if (pathExt != suffix) {
108
+ return ;
109
+ }
110
+ // Extract module name.
111
+ auto name = llvm::sys::path::filename (path).drop_back (pathExt.size ());
112
+ names.push_back (Ctx.getIdentifier (name));
113
+ });
114
+ };
115
+
116
+ auto tryRuntimeLibraryPath = [&](StringRef searchPath) {
117
+ // Look for:
118
+ // (Darwin OS) $PATH/{name}.swiftmodule/{arch}.{extension}
119
+ // (Other OS) $PATH/{name}.{extension}
120
+ bool requireTargetSpecificModule = Ctx.LangOpts .Target .isOSDarwin ();
121
+ forEachDirectoryEntryPath (searchPath, [&](StringRef path) {
122
+ auto pathExt = llvm::sys::path::extension (path);
123
+ if (requireTargetSpecificModule) {
124
+ if (pathExt != moduleSuffix)
125
+ return ;
126
+ if (!checkTargetFiles (path))
127
+ return ;
128
+ } else {
129
+ auto stat = fs.status (path);
130
+ if (!stat || stat->isDirectory ())
131
+ return ;
132
+ if (suffix != pathExt)
133
+ return ;
134
+ }
135
+ // Extract module name.
136
+ auto name = llvm::sys::path::filename (path).drop_back (pathExt.size ());
137
+ names.push_back (Ctx.getIdentifier (name));
138
+ });
139
+ };
140
+
141
+ auto tryFrameworkSearchPath = [&](StringRef searchPath) {
142
+ // Look for:
143
+ // $PATH/{name}.framework/Modules/{name}.swiftmodule/{arch}.{extension}
144
+ forEachDirectoryEntryPath (searchPath, [&](StringRef path) {
145
+ if (llvm::sys::path::extension (path) != " .framework" )
146
+ return ;
147
+
148
+ // Extract Framework name.
149
+ auto name = llvm::sys::path::filename (path).drop_back (
150
+ StringLiteral (" .framework" ).size ());
151
+
152
+ SmallString<128 > moduleDir;
153
+ llvm::sys::path::append (moduleDir, path, " Modules" , name + moduleSuffix);
154
+ if (!checkTargetFiles (moduleDir))
155
+ return ;
156
+
157
+ names.push_back (Ctx.getIdentifier (name));
158
+ });
159
+ };
160
+
161
+ for (const auto &path : Ctx.SearchPathOpts .ImportSearchPaths )
162
+ tryImportSearchPath (path);
163
+
164
+ for (const auto &path : Ctx.SearchPathOpts .FrameworkSearchPaths )
165
+ tryFrameworkSearchPath (path.Path );
166
+
167
+ // Apple platforms have extra implicit framework search paths:
168
+ // $SDKROOT/System/Library/Frameworks/ and $SDKROOT/Library/Frameworks/
169
+ if (Ctx.LangOpts .Target .isOSDarwin ()) {
170
+ SmallString<128 > scratch;
171
+ scratch = Ctx.SearchPathOpts .SDKPath ;
172
+ llvm::sys::path::append (scratch, " System" , " Library" , " Frameworks" );
173
+ tryFrameworkSearchPath (scratch);
174
+
175
+ scratch = Ctx.SearchPathOpts .SDKPath ;
176
+ llvm::sys::path::append (scratch, " Library" , " Frameworks" );
177
+ tryFrameworkSearchPath (scratch);
178
+ }
179
+
180
+ for (auto importPath : Ctx.SearchPathOpts .RuntimeLibraryImportPaths )
181
+ tryRuntimeLibraryPath (importPath);
182
+ }
183
+
184
+ void SerializedModuleLoader::collectVisibleTopLevelModuleNames (
185
+ SmallVectorImpl<Identifier> &names) const {
186
+ collectVisibleTopLevelModuleNamesImpl (
187
+ names, file_types::getExtension (file_types::TY_SwiftModuleFile));
188
+ }
189
+
47
190
std::error_code SerializedModuleLoaderBase::openModuleDocFile (
48
191
AccessPathElem ModuleID, StringRef ModuleDocPath,
49
192
std::unique_ptr<llvm::MemoryBuffer> *ModuleDocBuffer) {
0 commit comments