Skip to content

Commit 68af9d5

Browse files
committed
Merge remote-tracking branch 'origin/master' into master-next
2 parents 646bfba + e2b554d commit 68af9d5

File tree

14 files changed

+274
-69
lines changed

14 files changed

+274
-69
lines changed

include/swift/ClangImporter/ClangImporter.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ namespace clang {
4343
class Type;
4444
class VisibleDeclConsumer;
4545
class DeclarationName;
46+
class CompilerInvocation;
47+
namespace tooling {
48+
namespace dependencies {
49+
struct FullDependenciesResult;
50+
}
51+
}
4652
}
4753

4854
namespace swift {
@@ -148,6 +154,14 @@ class ClangImporter final : public ClangModuleLoader {
148154
std::string swiftPCHHash = "", DependencyTracker *tracker = nullptr,
149155
DWARFImporterDelegate *dwarfImporterDelegate = nullptr);
150156

157+
static std::vector<std::string>
158+
getClangArguments(ASTContext &ctx, const ClangImporterOptions &importerOpts);
159+
160+
static std::unique_ptr<clang::CompilerInvocation>
161+
createClangInvocation(ClangImporter *importer,
162+
const ClangImporterOptions &importerOpts,
163+
ArrayRef<std::string> invocationArgStrs,
164+
std::vector<std::string> *CC1Args = nullptr);
151165
ClangImporter(const ClangImporter &) = delete;
152166
ClangImporter(ClangImporter &&) = delete;
153167
ClangImporter &operator=(const ClangImporter &) = delete;
@@ -369,6 +383,10 @@ class ClangImporter final : public ClangModuleLoader {
369383

370384
void verifyAllModules() override;
371385

386+
void recordModuleDependencies(
387+
ModuleDependenciesCache &cache,
388+
const clang::tooling::dependencies::FullDependenciesResult &clangDependencies);
389+
372390
Optional<ModuleDependencies> getModuleDependencies(
373391
StringRef moduleName, ModuleDependenciesCache &cache,
374392
InterfaceSubContextDelegate &delegate) override;
@@ -460,6 +478,12 @@ class ClangImporter final : public ClangModuleLoader {
460478
ImportDecl *createImportDecl(ASTContext &Ctx, DeclContext *DC, ClangNode ClangN,
461479
ArrayRef<clang::Module *> Exported);
462480

481+
/// Extract the specified-or-defaulted -module-cache-path that winds up in
482+
/// the clang importer, for reuse as the .swiftmodule cache path when
483+
/// building a ModuleInterfaceLoader.
484+
std::string
485+
getModuleCachePathFromClang(const clang::CompilerInstance &Instance);
486+
463487
} // end namespace swift
464488

465489
#endif

include/swift/Frontend/ModuleInterfaceLoader.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,12 +198,6 @@ class ModuleInterfaceLoader : public SerializedModuleLoaderBase {
198198
bool RemarkOnRebuildFromInterface, bool DisableInterfaceFileLock);
199199
};
200200

201-
/// Extract the specified-or-defaulted -module-cache-path that winds up in
202-
/// the clang importer, for reuse as the .swiftmodule cache path when
203-
/// building a ModuleInterfaceLoader.
204-
std::string
205-
getModuleCachePathFromClang(const clang::CompilerInstance &Instance);
206-
207201
struct InterfaceSubContextDelegateImpl: InterfaceSubContextDelegate {
208202
private:
209203
SourceManager &SM;

lib/ClangImporter/ClangImporter.cpp

Lines changed: 67 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -905,15 +905,10 @@ ClangImporter::getOrCreatePCH(const ClangImporterOptions &ImporterOptions,
905905
return PCHFilename.getValue();
906906
}
907907

908-
std::unique_ptr<ClangImporter>
909-
ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts,
910-
std::string swiftPCHHash, DependencyTracker *tracker,
911-
DWARFImporterDelegate *dwarfImporterDelegate) {
912-
std::unique_ptr<ClangImporter> importer{
913-
new ClangImporter(ctx, importerOpts, tracker, dwarfImporterDelegate)};
914-
908+
std::vector<std::string>
909+
ClangImporter::getClangArguments(ASTContext &ctx,
910+
const ClangImporterOptions &importerOpts) {
915911
std::vector<std::string> invocationArgStrs;
916-
917912
// Clang expects this to be like an actual command line. So we need to pass in
918913
// "clang" for argv[0]
919914
invocationArgStrs.push_back("clang");
@@ -927,6 +922,49 @@ ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts,
927922
break;
928923
}
929924
addCommonInvocationArguments(invocationArgStrs, ctx, importerOpts);
925+
return invocationArgStrs;
926+
}
927+
928+
std::unique_ptr<clang::CompilerInvocation>
929+
ClangImporter::createClangInvocation(ClangImporter *importer,
930+
const ClangImporterOptions &importerOpts,
931+
ArrayRef<std::string> invocationArgStrs,
932+
std::vector<std::string> *CC1Args) {
933+
std::vector<const char *> invocationArgs;
934+
invocationArgs.reserve(invocationArgStrs.size());
935+
for (auto &argStr : invocationArgStrs)
936+
invocationArgs.push_back(argStr.c_str());
937+
// Set up a temporary diagnostic client to report errors from parsing the
938+
// command line, which may be important for Swift clients if, for example,
939+
// they're using -Xcc options. Unfortunately this diagnostic engine has to
940+
// use the default options because the /actual/ options haven't been parsed
941+
// yet.
942+
//
943+
// The long-term client for Clang diagnostics is set up below, after the
944+
// clang::CompilerInstance is created.
945+
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> tempDiagOpts{
946+
new clang::DiagnosticOptions
947+
};
948+
949+
ClangDiagnosticConsumer tempDiagClient{importer->Impl, *tempDiagOpts,
950+
importerOpts.DumpClangDiagnostics};
951+
llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> tempClangDiags =
952+
clang::CompilerInstance::createDiagnostics(tempDiagOpts.get(),
953+
&tempDiagClient,
954+
/*owned*/false);
955+
956+
return clang::createInvocationFromCommandLine(invocationArgs, tempClangDiags,
957+
nullptr, false, CC1Args);
958+
}
959+
960+
std::unique_ptr<ClangImporter>
961+
ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts,
962+
std::string swiftPCHHash, DependencyTracker *tracker,
963+
DWARFImporterDelegate *dwarfImporterDelegate) {
964+
std::unique_ptr<ClangImporter> importer{
965+
new ClangImporter(ctx, importerOpts, tracker, dwarfImporterDelegate)};
966+
importer->Impl.ClangArgs = getClangArguments(ctx, importerOpts);
967+
ArrayRef<std::string> invocationArgStrs = importer->Impl.ClangArgs;
930968

931969
if (importerOpts.DumpClangDiagnostics) {
932970
llvm::errs() << "'";
@@ -936,10 +974,7 @@ ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts,
936974
llvm::errs() << "'\n";
937975
}
938976

939-
std::vector<const char *> invocationArgs;
940-
invocationArgs.reserve(invocationArgStrs.size());
941-
for (auto &argStr : invocationArgStrs)
942-
invocationArgs.push_back(argStr.c_str());
977+
943978

944979
if (llvm::sys::path::extension(importerOpts.BridgingHeader)
945980
.endswith(file_types::getExtension(file_types::TY_PCH))) {
@@ -957,27 +992,9 @@ ClangImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts,
957992

958993
// Create a new Clang compiler invocation.
959994
{
960-
// Set up a temporary diagnostic client to report errors from parsing the
961-
// command line, which may be important for Swift clients if, for example,
962-
// they're using -Xcc options. Unfortunately this diagnostic engine has to
963-
// use the default options because the /actual/ options haven't been parsed
964-
// yet.
965-
//
966-
// The long-term client for Clang diagnostics is set up below, after the
967-
// clang::CompilerInstance is created.
968-
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> tempDiagOpts{
969-
new clang::DiagnosticOptions
970-
};
971-
972-
ClangDiagnosticConsumer tempDiagClient{importer->Impl, *tempDiagOpts,
973-
importerOpts.DumpClangDiagnostics};
974-
llvm::IntrusiveRefCntPtr<clang::DiagnosticsEngine> tempClangDiags =
975-
clang::CompilerInstance::createDiagnostics(tempDiagOpts.get(),
976-
&tempDiagClient,
977-
/*owned*/false);
978-
979-
importer->Impl.Invocation =
980-
clang::createInvocationFromCommandLine(invocationArgs, tempClangDiags);
995+
importer->Impl.Invocation = createClangInvocation(importer.get(),
996+
importerOpts,
997+
invocationArgStrs);
981998
if (!importer->Impl.Invocation)
982999
return nullptr;
9831000
}
@@ -3994,3 +4011,20 @@ bool ClangImporter::isInOverlayModuleForImportedModule(
39944011
return !clangModule->ExportAsModule.empty() &&
39954012
clangModule->ExportAsModule == overlayModule->getName().str();
39964013
}
4014+
4015+
/// Extract the specified-or-defaulted -module-cache-path that winds up in
4016+
/// the clang importer, for reuse as the .swiftmodule cache path when
4017+
/// building a ModuleInterfaceLoader.
4018+
std::string
4019+
swift::getModuleCachePathFromClang(const clang::CompilerInstance &Clang) {
4020+
if (!Clang.hasPreprocessor())
4021+
return "";
4022+
std::string SpecificModuleCachePath =
4023+
Clang.getPreprocessor().getHeaderSearchInfo().getModuleCachePath().str();
4024+
4025+
// The returned-from-clang module cache path includes a suffix directory
4026+
// that is specific to the clang version and invocation; we want the
4027+
// directory above that.
4028+
return llvm::sys::path::parent_path(SpecificModuleCachePath).str();
4029+
}
4030+

lib/ClangImporter/ClangModuleDependencyScanner.cpp

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,48 @@ static ClangModuleDependenciesCacheImpl *getOrCreateClangImpl(
188188
return clangImpl;
189189
}
190190

191+
static std::string getModuleFilePath(StringRef moduleCacheDir,
192+
StringRef moduleName,
193+
StringRef contextHash) {
194+
SmallString<128> outputPath(moduleCacheDir);
195+
llvm::sys::path::append(outputPath, (llvm::Twine(moduleName)
196+
+ "-" + contextHash + ".pcm").str());
197+
return outputPath.str().str();
198+
}
199+
200+
static std::string getModuleFilePath(StringRef moduleCacheDir,
201+
const ModuleDeps &dep) {
202+
return getModuleFilePath(moduleCacheDir, dep.ModuleName, dep.ContextHash);
203+
}
204+
191205
/// Record the module dependencies we found by scanning Clang modules into
192206
/// the module dependencies cache.
193-
static void recordModuleDependencies(
207+
void ClangImporter::recordModuleDependencies(
194208
ModuleDependenciesCache &cache,
195209
const FullDependenciesResult &clangDependencies) {
210+
struct ModuleInfo {
211+
std::string PCMPath;
212+
std::string ModuleMapPath;
213+
};
214+
auto ModuleCacheDir = swift::getModuleCachePathFromClang(getClangInstance());
215+
216+
// A map keyed by module name and context hash.
217+
llvm::StringMap<llvm::StringMap<ModuleInfo>> moduleInfoMap;
218+
219+
// Traverse all Clang modules to populate moduleInfoMap for cross
220+
// referencing later.
221+
for (const auto &clangModuleDep : clangDependencies.DiscoveredModules) {
222+
moduleInfoMap[clangModuleDep.ModuleName][clangModuleDep.ContextHash] =
223+
{
224+
// Keep track of pcm path for output.
225+
getModuleFilePath(ModuleCacheDir, clangModuleDep),
226+
// Keep track of modulemap file for input.
227+
clangModuleDep.ClangModuleMapFile
228+
};
229+
}
196230
for (const auto &clangModuleDep : clangDependencies.DiscoveredModules) {
231+
assert(moduleInfoMap[clangModuleDep.ModuleName]
232+
.count(clangModuleDep.ContextHash));
197233
// If we've already cached this information, we're done.
198234
if (cache.hasDependencies(clangModuleDep.ModuleName,
199235
ModuleDependenciesKind::Clang))
@@ -204,14 +240,58 @@ static void recordModuleDependencies(
204240
for (const auto &fileDep : clangModuleDep.FileDeps) {
205241
fileDeps.push_back(fileDep.getKey().str());
206242
}
243+
// Inherit all Clang driver args when creating the clang importer.
244+
std::vector<std::string> allArgs = Impl.ClangArgs;
245+
ClangImporterOptions Opts;
246+
std::vector<std::string> cc1Args;
247+
248+
// Calling this to convert driver args to CC1 args.
249+
createClangInvocation(this, Opts, allArgs, &cc1Args);
250+
std::vector<std::string> swiftArgs;
251+
// We are using Swift frontend mode.
252+
swiftArgs.push_back("-frontend");
253+
auto addClangArg = [&](StringRef arg) {
254+
swiftArgs.push_back("-Xcc");
255+
swiftArgs.push_back("-Xclang");
256+
swiftArgs.push_back("-Xcc");
257+
swiftArgs.push_back(arg);
258+
};
259+
// Add all args inheritted from creating the importer.
260+
for (auto arg: cc1Args) {
261+
addClangArg(arg);
262+
}
263+
// Add all args reported from the Clang dependencies scanner.
264+
for(auto arg: clangModuleDep.NonPathCommandLine) {
265+
addClangArg(arg);
266+
}
207267

268+
// Add -fmodule-map-file and -fmodule-file for direct dependencies.
269+
for (auto &dep: clangModuleDep.ClangModuleDeps) {
270+
assert(moduleInfoMap[dep.ModuleName].count(dep.ContextHash));
271+
addClangArg((llvm::Twine("-fmodule-map-file=")
272+
+ moduleInfoMap[dep.ModuleName][dep.ContextHash].ModuleMapPath).str());
273+
addClangArg((llvm::Twine("-fmodule-file=")
274+
+ moduleInfoMap[dep.ModuleName][dep.ContextHash].PCMPath).str());
275+
}
276+
// Swift frontend action: -emit-pcm
277+
swiftArgs.push_back("-emit-pcm");
278+
swiftArgs.push_back("-module-name");
279+
swiftArgs.push_back(clangModuleDep.ModuleName);
280+
281+
// Swift frontend option for output file path (Foo.pcm).
282+
swiftArgs.push_back("-o");
283+
swiftArgs.push_back(moduleInfoMap[clangModuleDep.ModuleName]
284+
[clangModuleDep.ContextHash].PCMPath);
285+
286+
// Swift frontend option for input file path (Foo.modulemap).
287+
swiftArgs.push_back(clangModuleDep.ClangModuleMapFile);
208288
// Module-level dependencies.
209289
llvm::StringSet<> alreadyAddedModules;
210290
auto dependencies = ModuleDependencies::forClangModule(
211291
clangModuleDep.ImplicitModulePCMPath,
212292
clangModuleDep.ClangModuleMapFile,
213293
clangModuleDep.ContextHash,
214-
clangModuleDep.NonPathCommandLine,
294+
swiftArgs,
215295
fileDeps);
216296
for (const auto &moduleName : clangModuleDep.ClangModuleDeps) {
217297
dependencies.addModuleDependency(moduleName.ModuleName, alreadyAddedModules);

lib/ClangImporter/ImporterImpl.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,8 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
390390
/// Clang parser, which is used to load textual headers.
391391
std::unique_ptr<clang::MangleContext> Mangler;
392392

393+
/// Clang arguments used to create the Clang invocation.
394+
std::vector<std::string> ClangArgs;
393395
public:
394396
/// Mapping of already-imported declarations.
395397
llvm::DenseMap<std::pair<const clang::Decl *, Version>, Decl *> ImportedDecls;

lib/Frontend/ModuleInterfaceLoader.cpp

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,22 +41,6 @@
4141
using namespace swift;
4242
using FileDependency = SerializationOptions::FileDependency;
4343

44-
/// Extract the specified-or-defaulted -module-cache-path that winds up in
45-
/// the clang importer, for reuse as the .swiftmodule cache path when
46-
/// building a ModuleInterfaceLoader.
47-
std::string
48-
swift::getModuleCachePathFromClang(const clang::CompilerInstance &Clang) {
49-
if (!Clang.hasPreprocessor())
50-
return "";
51-
std::string SpecificModuleCachePath =
52-
Clang.getPreprocessor().getHeaderSearchInfo().getModuleCachePath().str();
53-
54-
// The returned-from-clang module cache path includes a suffix directory
55-
// that is specific to the clang version and invocation; we want the
56-
// directory above that.
57-
return llvm::sys::path::parent_path(SpecificModuleCachePath).str();
58-
}
59-
6044
#pragma mark - Forwarding Modules
6145

6246
namespace {
@@ -1048,6 +1032,7 @@ void ModuleInterfaceLoader::collectVisibleTopLevelModuleNames(
10481032
void InterfaceSubContextDelegateImpl::inheritOptionsForBuildingInterface(
10491033
const SearchPathOptions &SearchPathOpts,
10501034
const LangOptions &LangOpts) {
1035+
GenericArgs.push_back("-frontend");
10511036
// Start with a SubInvocation that copies various state from our
10521037
// invoking ASTContext.
10531038
GenericArgs.push_back("-compile-module-from-interface");
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//===--------------- BuildModulesFromGraph.swift --------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
import Foundation
13+
14+
let fileName = CommandLine.arguments[1]
15+
let swiftPath = CommandLine.arguments[2]
16+
let moduleName = CommandLine.arguments[3]
17+
let data = try! Data(contentsOf: URL(fileURLWithPath: fileName))
18+
19+
let decoder = JSONDecoder()
20+
let moduleDependencyGraph = try! decoder.decode(
21+
ModuleDependencyGraph.self, from: data)
22+
23+
func findModuleBuildingCommand(_ moduleName: String) -> [String]? {
24+
for (_, dep) in moduleDependencyGraph.modules {
25+
if dep.modulePath.hasSuffix(moduleName) {
26+
switch dep.details {
27+
case .swift(let details):
28+
return details.commandLine
29+
case .clang(let details):
30+
return details.commandLine
31+
}
32+
} else {
33+
continue
34+
}
35+
}
36+
return nil
37+
}
38+
39+
if let command = findModuleBuildingCommand(moduleName) {
40+
var result = swiftPath
41+
command.forEach { result += " \($0)"}
42+
print(result)
43+
exit(0)
44+
} else {
45+
fatalError("cannot find module building commands for \(moduleName)")
46+
}

0 commit comments

Comments
 (0)