@@ -97,61 +97,44 @@ namespace {
97
97
};
98
98
}
99
99
100
- Optional<ModuleDependencies> ClangImporter::getModuleDependencies (
101
- StringRef moduleName, ModuleDependenciesCache &cache) {
102
- // Check whether there is already a cached result.
103
- if (auto found = cache.findDependencies (
104
- moduleName, ModuleDependenciesKind::Clang))
105
- return found;
106
-
107
- // Retrieve or create the shared state.
108
- auto clangImpl = cache.getClangImpl ();
109
- if (!clangImpl) {
110
- clangImpl = new ClangModuleDependenciesCacheImpl ();
111
- cache.setClangImpl (clangImpl,
112
- [](ClangModuleDependenciesCacheImpl *ptr) {
113
- delete ptr;
114
- });
115
- }
116
-
117
- // Reform the Clang importer options.
118
- // FIXME: Just save a reference or copy so we can get this back.
119
- ClangImporterOptions importerOpts;
120
-
121
- // Determine the command-line arguments for dependency scanning.
122
- auto &ctx = Impl.SwiftContext ;
123
- std::vector<std::string> commandLineArgs;
124
- commandLineArgs.push_back (" clang" );
125
- importer::getNormalInvocationArguments (commandLineArgs, ctx, importerOpts);
126
- importer::addCommonInvocationArguments (commandLineArgs, ctx, importerOpts);
127
-
128
- // Add search paths.
129
- // Note: This is handled differently for the Clang importer itself, which
130
- // adds search paths to Clang's data structures rather than to its
131
- // command line.
100
+ // Add search paths.
101
+ // Note: This is handled differently for the Clang importer itself, which
102
+ // adds search paths to Clang's data structures rather than to its
103
+ // command line.
104
+ static void addSearchPathInvocationArguments (
105
+ std::vector<std::string> &invocationArgStrs,
106
+ ASTContext &ctx,
107
+ const ClangImporterOptions &importerOpts) {
132
108
SearchPathOptions &searchPathOpts = ctx.SearchPathOpts ;
133
109
for (const auto &framepath : searchPathOpts.FrameworkSearchPaths ) {
134
- commandLineArgs .push_back (framepath.IsSystem ? " -iframework" : " -F" );
135
- commandLineArgs .push_back (framepath.Path );
110
+ invocationArgStrs .push_back (framepath.IsSystem ? " -iframework" : " -F" );
111
+ invocationArgStrs .push_back (framepath.Path );
136
112
}
137
113
138
114
for (auto path : searchPathOpts.ImportSearchPaths ) {
139
- commandLineArgs .push_back (" -I" );
140
- commandLineArgs .push_back (path);
115
+ invocationArgStrs .push_back (" -I" );
116
+ invocationArgStrs .push_back (path);
141
117
}
118
+ }
142
119
143
- // HACK! Replace the module import buffer name with the source file hack.
144
- auto importHackFile = clangImpl->getImportHackFile ();
145
- if (!importHackFile) {
146
- // FIXME: Emit a diagnostic here.
147
- return None;
148
- }
120
+ // / Create the command line for Clang dependency scanning.
121
+ static std::vector<std::string> getClangDepScanningInvocationArguments (
122
+ ASTContext &ctx,
123
+ const ClangImporterOptions &importerOpts,
124
+ StringRef sourceFileName) {
125
+ std::vector<std::string> commandLineArgs;
126
+
127
+ // Form the basic command line.
128
+ commandLineArgs.push_back (" clang" );
129
+ importer::getNormalInvocationArguments (commandLineArgs, ctx, importerOpts);
130
+ importer::addCommonInvocationArguments (commandLineArgs, ctx, importerOpts);
131
+ addSearchPathInvocationArguments (commandLineArgs, ctx, importerOpts);
149
132
150
133
auto sourceFilePos = std::find (
151
134
commandLineArgs.begin (), commandLineArgs.end (),
152
135
" <swift-imported-modules>" );
153
136
assert (sourceFilePos != commandLineArgs.end ());
154
- *sourceFilePos = *importHackFile ;
137
+ *sourceFilePos = sourceFileName ;
155
138
156
139
// HACK! Drop the -fmodule-format= argument and the one that
157
140
// precedes it.
@@ -187,34 +170,36 @@ Optional<ModuleDependencies> ClangImporter::getModuleDependencies(
187
170
commandLineArgs.push_back (" -sys-header-deps" );
188
171
commandLineArgs.push_back (" -Wno-error" );
189
172
190
- // HACK! Trick out a .m file to use to import the module we name.
191
- std::string moduleNameHackDefine =
192
- (" -DHACK_MODULE_NAME=" + moduleName).str ();
193
- commandLineArgs.push_back (moduleNameHackDefine);
194
- commandLineArgs.push_back (" -fmodules-ignore-macro=HACK_MODULE_NAME" );
195
-
196
- std::string workingDir =
197
- ctx.SourceMgr .getFileSystem ()->getCurrentWorkingDirectory ().get ();
198
- CompileCommand command (workingDir, *importHackFile, commandLineArgs, " -" );
199
- SingleCommandCompilationDatabase database (command);
200
-
201
- auto clangDependencies = clangImpl->tool .getFullDependencies (
202
- database, workingDir, clangImpl->alreadySeen );
173
+ return commandLineArgs;
174
+ }
203
175
204
- if (!clangDependencies) {
205
- // FIXME: Route this to a normal diagnostic.
206
- llvm::logAllUnhandledErrors (clangDependencies.takeError (), llvm::errs ());
207
- return None;
176
+ // / Get or create the Clang-specific
177
+ static ClangModuleDependenciesCacheImpl *getOrCreateClangImpl (
178
+ ModuleDependenciesCache &cache) {
179
+ auto clangImpl = cache.getClangImpl ();
180
+ if (!clangImpl) {
181
+ clangImpl = new ClangModuleDependenciesCacheImpl ();
182
+ cache.setClangImpl (clangImpl,
183
+ [](ClangModuleDependenciesCacheImpl *ptr) {
184
+ delete ptr;
185
+ });
208
186
}
209
187
210
- // Record module dependencies for each module we found.
211
- llvm::StringSet<> alreadyAddedModules;
212
- for (const auto &clangModuleDep : clangDependencies->DiscoveredModules ) {
188
+ return clangImpl;
189
+ }
190
+
191
+ // / Record the module dependencies we found by scanning Clang modules into
192
+ // / the module dependencies cache.
193
+ static void recordModuleDependencies (
194
+ ModuleDependenciesCache &cache,
195
+ const FullDependenciesResult &clangDependencies) {
196
+ for (const auto &clangModuleDep : clangDependencies.DiscoveredModules ) {
213
197
// If we've already cached this information, we're done.
214
198
if (cache.hasDependencies (clangModuleDep.ModuleName ,
215
199
ModuleDependenciesKind::Clang))
216
200
continue ;
217
201
202
+ // File dependencies for this module.
218
203
std::vector<std::string> fileDeps;
219
204
for (const auto &fileDep : clangModuleDep.FileDeps ) {
220
205
fileDeps.push_back (fileDep.getKey ());
@@ -223,9 +208,11 @@ Optional<ModuleDependencies> ClangImporter::getModuleDependencies(
223
208
// Create a module filename.
224
209
// FIXME: Query Clang to determine an appropriate hashed name for the
225
210
// module file.
226
- llvm::SmallString<32 > modulePath = moduleName ;
211
+ llvm::SmallString<32 > modulePath (clangModuleDep. ModuleName ) ;
227
212
llvm::sys::path::replace_extension (modulePath, " pcm" );
228
213
214
+ // Module-level dependencies.
215
+ llvm::StringSet<> alreadyAddedModules;
229
216
auto dependencies = ModuleDependencies::forClangModule (
230
217
modulePath.str (), clangModuleDep.ClangModuleMapFile , fileDeps);
231
218
for (const auto &moduleName : clangModuleDep.ClangModuleDeps ) {
@@ -236,6 +223,121 @@ Optional<ModuleDependencies> ClangImporter::getModuleDependencies(
236
223
std::move (dependencies),
237
224
ModuleDependenciesKind::Clang);
238
225
}
226
+ }
227
+
228
+ Optional<ModuleDependencies> ClangImporter::getModuleDependencies (
229
+ StringRef moduleName, ModuleDependenciesCache &cache) {
230
+ // Check whether there is already a cached result.
231
+ if (auto found = cache.findDependencies (
232
+ moduleName, ModuleDependenciesKind::Clang))
233
+ return found;
234
+
235
+ // Retrieve or create the shared state.
236
+ auto clangImpl = getOrCreateClangImpl (cache);
237
+
238
+ // HACK! Replace the module import buffer name with the source file hack.
239
+ auto importHackFile = clangImpl->getImportHackFile ();
240
+ if (!importHackFile) {
241
+ // FIXME: Emit a diagnostic here.
242
+ return None;
243
+ }
244
+
245
+ // Reform the Clang importer options.
246
+ // FIXME: Just save a reference or copy so we can get this back.
247
+ ClangImporterOptions importerOpts;
248
+
249
+ // Determine the command-line arguments for dependency scanning.
250
+ auto &ctx = Impl.SwiftContext ;
251
+ std::vector<std::string> commandLineArgs =
252
+ getClangDepScanningInvocationArguments (
253
+ ctx, importerOpts, *importHackFile);
254
+
255
+ // HACK! Trick out a .m file to use to import the module we name.
256
+ std::string moduleNameHackDefine =
257
+ (" -DHACK_MODULE_NAME=" + moduleName).str ();
258
+ commandLineArgs.push_back (moduleNameHackDefine);
259
+ commandLineArgs.push_back (" -fmodules-ignore-macro=HACK_MODULE_NAME" );
260
+
261
+ std::string workingDir =
262
+ ctx.SourceMgr .getFileSystem ()->getCurrentWorkingDirectory ().get ();
263
+ CompileCommand command (workingDir, *importHackFile, commandLineArgs, " -" );
264
+ SingleCommandCompilationDatabase database (command);
265
+
266
+ auto clangDependencies = clangImpl->tool .getFullDependencies (
267
+ database, workingDir, clangImpl->alreadySeen );
268
+
269
+ if (!clangDependencies) {
270
+ // FIXME: Route this to a normal diagnostic.
271
+ llvm::logAllUnhandledErrors (clangDependencies.takeError (), llvm::errs ());
272
+ return None;
273
+ }
274
+
275
+ // Record module dependencies for each module we found.
276
+ recordModuleDependencies (cache, *clangDependencies);
239
277
240
278
return cache.findDependencies (moduleName, ModuleDependenciesKind::Clang);
241
279
}
280
+
281
+ bool ClangImporter::addBridgingHeaderDependencies (
282
+ StringRef moduleName,
283
+ ModuleDependenciesCache &cache) {
284
+ auto targetModule = *cache.findDependencies (
285
+ moduleName, ModuleDependenciesKind::Swift);
286
+
287
+ // If we've already recorded bridging header dependencies, we're done.
288
+ auto swiftDeps = targetModule.getAsSwiftModule ();
289
+ if (!swiftDeps->bridgingSourceFiles .empty () ||
290
+ !swiftDeps->bridgingModuleDependencies .empty ())
291
+ return false ;
292
+
293
+ // Retrieve or create the shared state.
294
+ auto clangImpl = getOrCreateClangImpl (cache);
295
+
296
+ // Reform the Clang importer options.
297
+ // FIXME: Just save a reference or copy so we can get this back.
298
+ ClangImporterOptions importerOpts;
299
+
300
+ // Retrieve the bridging header.
301
+ std::string bridgingHeader = *targetModule.getBridgingHeader ();
302
+
303
+ // Determine the command-line arguments for dependency scanning.
304
+ auto &ctx = Impl.SwiftContext ;
305
+ std::vector<std::string> commandLineArgs =
306
+ getClangDepScanningInvocationArguments (
307
+ ctx, importerOpts, bridgingHeader);
308
+
309
+ std::string workingDir =
310
+ ctx.SourceMgr .getFileSystem ()->getCurrentWorkingDirectory ().get ();
311
+ CompileCommand command (workingDir, bridgingHeader, commandLineArgs, " -" );
312
+ SingleCommandCompilationDatabase database (command);
313
+
314
+ auto clangDependencies = clangImpl->tool .getFullDependencies (
315
+ database, workingDir, clangImpl->alreadySeen );
316
+
317
+ if (!clangDependencies) {
318
+ // FIXME: Route this to a normal diagnostic.
319
+ llvm::logAllUnhandledErrors (clangDependencies.takeError (), llvm::errs ());
320
+ return true ;
321
+ }
322
+
323
+ // Record module dependencies for each module we found.
324
+ recordModuleDependencies (cache, *clangDependencies);
325
+
326
+ // Record dependencies for the source files the bridging header includes.
327
+ for (const auto &fileDep : clangDependencies->FullDeps .FileDeps )
328
+ targetModule.addBridgingSourceFile (fileDep);
329
+
330
+ // ... and all module dependencies.
331
+ llvm::StringSet<> alreadyAddedModules;
332
+ for (const auto &moduleDep : clangDependencies->FullDeps .ClangModuleDeps ) {
333
+ targetModule.addBridgingModuleDependency (
334
+ moduleDep.ModuleName , alreadyAddedModules);
335
+ }
336
+
337
+ // Update the cache with the new information for the module.
338
+ cache.updateDependencies (
339
+ {moduleName, ModuleDependenciesKind::Swift},
340
+ std::move (targetModule));
341
+
342
+ return false ;
343
+ }
0 commit comments