Skip to content

Commit 082fc48

Browse files
committed
[Dependency Scanning] Refactor dependency scanner to return an in-memory format as a result
This commit refactors ScanDependencies.cpp to split the functionality into two functional groups: - Scan execution code that performs the mechanics of the scan and produces an in-memory result - Dependency scanner entry-points used when the scanning action is invoked as a `swift-frontend` execution mode This commit also adds the aforementioned in-memory dependency scanning result in `FullDependencies.h`, modeled after the InterModuleDependencyGraph representation in swift-driver
1 parent dad1435 commit 082fc48

File tree

7 files changed

+633
-221
lines changed

7 files changed

+633
-221
lines changed

include/swift/DependencyScan/DependencyScanningTool.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616
#include "swift/AST/ModuleDependencies.h"
1717
#include "swift/Frontend/PrintingDiagnosticConsumer.h"
1818
#include "swift/DependencyScan/ScanDependencies.h"
19-
#include "llvm/ADT/StringMap.h"
20-
#include "llvm/ADT/StringRef.h"
2119
#include "llvm/ADT/StringSet.h"
2220
#include "llvm/Support/Error.h"
2321
#include "llvm/Support/StringSaver.h"
@@ -37,7 +35,7 @@ class DependencyScanningTool {
3735
///
3836
/// \returns a \c StringError with the diagnostic output if errors
3937
/// occurred, \c FullDependencies otherwise.
40-
llvm::ErrorOr<std::string>
38+
llvm::ErrorOr<FullDependencies>
4139
getDependencies(ArrayRef<const char *> Command,
4240
const llvm::StringSet<> &PlaceholderModules);
4341

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
//===------------------ FullDependencies.h - Swift Compiler ---------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2020 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+
13+
#ifndef SWIFT_DEPENDENCY_FULL_DEPENDENCIES_H
14+
#define SWIFT_DEPENDENCY_FULL_DEPENDENCIES_H
15+
16+
#include "swift/AST/ModuleDependencies.h"
17+
#include <set>
18+
#include <string>
19+
#include <unordered_map>
20+
#include <vector>
21+
22+
// This file describes the format for in-memory dependency scanning result
23+
// produced by the Swift dependency scanner.
24+
25+
namespace swift {
26+
namespace dependencies {
27+
28+
/// Swift modules to be built from a module interface, may have a bridging
29+
/// header.
30+
struct SwiftTextualModuleDetails {
31+
/// The module interface from which this module was built, if any.
32+
std::string ModuleInterfacePath;
33+
34+
/// The paths of potentially ready-to-use compiled modules for the interface.
35+
std::vector<std::string> CompiledModuleCandidates;
36+
37+
/// The bridging header, if any.
38+
std::string BridgingHeaderPath;
39+
40+
/// The source files referenced by the bridging header.
41+
std::vector<std::string> BridgingSourceFiles;
42+
43+
/// (Clang) modules on which the bridging header depends.
44+
std::vector<std::string> BridgingModuleDependencies;
45+
46+
/// Options to the compile command required to build this module interface
47+
std::vector<std::string> CommandLine;
48+
49+
/// To build a PCM to be used by this Swift module, we need to append these
50+
/// arguments to the generic PCM build arguments reported from the dependency
51+
/// graph.
52+
std::vector<std::string> ExtraPcmArgs;
53+
54+
/// The hash value that will be used for the generated module
55+
std::string ContextHash;
56+
57+
/// A flag to indicate whether or not this module is a framework.
58+
bool IsFramework = false;
59+
};
60+
61+
/// Swift modules with only a binary module file.
62+
struct SwiftBinaryModuleDetails {
63+
/// The path to the pre-compiled binary module
64+
std::string CompiledModulePath;
65+
66+
/// The path to the .swiftModuleDoc file.
67+
std::string ModuleDocPath;
68+
69+
/// The path to the .swiftSourceInfo file.
70+
std::string ModuleSourceInfoPath;
71+
};
72+
73+
/// Swift placeholder modules carry additional details that specify their
74+
/// module doc path and source info paths.
75+
struct SwiftPlaceholderModuleDetails {
76+
/// The path to the pre-compiled binary module
77+
std::string CompiledModulePath;
78+
79+
/// The path to the .swiftModuleDoc file.
80+
std::string ModuleDocPath;
81+
82+
/// The path to the .swiftSourceInfo file.
83+
std::string ModuleSourceInfoPath;
84+
};
85+
86+
/// Clang modules are built from a module map file.
87+
struct ClangModuleDetails {
88+
/// The path to the module map used to build this module.
89+
std::string ModuleMapPath;
90+
91+
/// Set of PCM Arguments of depending modules which
92+
/// are covered by the directDependencies info of this module
93+
// TODO: Should this be modeled here or in the clients?
94+
// const std::set<std::string> DependenciesCapturedPCMArgs;
95+
96+
/// clang-generated context hash
97+
std::string ContextHash;
98+
99+
/// Options to the compile command required to build this clang modulemap
100+
std::vector<std::string> CommandLine;
101+
};
102+
103+
struct ModuleDetails {
104+
ModuleDetails(SwiftTextualModuleDetails Details)
105+
: DetailsKind(ModuleDependenciesKind::SwiftTextual), Value(Details) {}
106+
ModuleDetails(SwiftBinaryModuleDetails Details)
107+
: DetailsKind(ModuleDependenciesKind::SwiftBinary), Value(Details) {}
108+
ModuleDetails(SwiftPlaceholderModuleDetails Details)
109+
: DetailsKind(ModuleDependenciesKind::SwiftPlaceholder), Value(Details) {}
110+
ModuleDetails(ClangModuleDetails Details)
111+
: DetailsKind(ModuleDependenciesKind::Clang), Value(Details) {}
112+
113+
~ModuleDetails() {
114+
switch (DetailsKind) {
115+
case ModuleDependenciesKind::SwiftTextual:
116+
(&Value.TextualDetails)->~SwiftTextualModuleDetails();
117+
break;
118+
case ModuleDependenciesKind::SwiftBinary:
119+
(&Value.BinaryDetails)->~SwiftBinaryModuleDetails();
120+
break;
121+
case ModuleDependenciesKind::SwiftPlaceholder:
122+
(&Value.PlaceholderDetails)->~SwiftPlaceholderModuleDetails();
123+
break;
124+
case ModuleDependenciesKind::Clang:
125+
(&Value.ClangDetails)->~ClangModuleDetails();
126+
break;
127+
}
128+
}
129+
130+
ModuleDetails(const ModuleDetails &src) :
131+
DetailsKind(src.DetailsKind) {
132+
switch (src.DetailsKind) {
133+
case ModuleDependenciesKind::SwiftBinary:
134+
new (&Value.BinaryDetails) auto(src.Value.BinaryDetails);
135+
break;
136+
case ModuleDependenciesKind::SwiftTextual:
137+
new (&Value.TextualDetails) auto(src.Value.TextualDetails);
138+
break;
139+
case ModuleDependenciesKind::SwiftPlaceholder:
140+
new (&Value.PlaceholderDetails) auto(src.Value.PlaceholderDetails);
141+
break;
142+
case ModuleDependenciesKind::Clang:
143+
new (&Value.ClangDetails) auto(src.Value.ClangDetails);
144+
break;
145+
}
146+
}
147+
148+
const SwiftTextualModuleDetails *getAsSwiftTextualModule() const {
149+
return DetailsKind == ModuleDependenciesKind::SwiftTextual
150+
? &Value.TextualDetails
151+
: nullptr;
152+
}
153+
const SwiftPlaceholderModuleDetails *
154+
getAsPlaceholderDependencyModule() const {
155+
return DetailsKind == ModuleDependenciesKind::SwiftPlaceholder
156+
? &Value.PlaceholderDetails
157+
: nullptr;
158+
}
159+
const SwiftBinaryModuleDetails *getAsSwiftBinaryModule() const {
160+
return DetailsKind == ModuleDependenciesKind::SwiftBinary
161+
? &Value.BinaryDetails
162+
: nullptr;
163+
}
164+
const ClangModuleDetails *getAsClangModule() const {
165+
return DetailsKind == ModuleDependenciesKind::Clang ? &Value.ClangDetails
166+
: nullptr;
167+
}
168+
169+
private:
170+
ModuleDependenciesKind DetailsKind;
171+
172+
union ModuleDetailsValue {
173+
SwiftTextualModuleDetails TextualDetails;
174+
SwiftBinaryModuleDetails BinaryDetails;
175+
SwiftPlaceholderModuleDetails PlaceholderDetails;
176+
ClangModuleDetails ClangDetails;
177+
178+
ModuleDetailsValue(SwiftTextualModuleDetails Details)
179+
: TextualDetails(Details) {}
180+
ModuleDetailsValue(SwiftBinaryModuleDetails Details)
181+
: BinaryDetails(Details) {}
182+
ModuleDetailsValue(SwiftPlaceholderModuleDetails Details)
183+
: PlaceholderDetails(Details) {}
184+
ModuleDetailsValue(ClangModuleDetails Details) : ClangDetails(Details) {}
185+
186+
ModuleDetailsValue() {}
187+
~ModuleDetailsValue() {}
188+
} Value;
189+
};
190+
191+
struct ModuleInfo {
192+
/// The ID of the module this info describes
193+
ModuleDependencyID ID;
194+
195+
/// The path for the module.
196+
std::string ModulePath;
197+
198+
/// The source files used to build this module.
199+
std::vector<std::string> SourceFiles;
200+
201+
/// The set of direct module dependencies of this module.
202+
std::vector<ModuleDependencyID> DirectDependencies;
203+
204+
/// Specific details of a particular kind of module.
205+
ModuleDetails Details;
206+
};
207+
208+
struct FullDependencies {
209+
/// The name of the main module for this dependency graph (root node)
210+
const std::string MainModuleName;
211+
212+
/// The complete set of modules discovered
213+
std::vector<ModuleInfo> Modules;
214+
215+
FullDependencies(std::string MainModuleName)
216+
: MainModuleName(MainModuleName), Modules() {}
217+
};
218+
} // namespace dependencies
219+
} // namespace swift
220+
221+
#endif // SWIFT_DEPENDENCY_FULL_DEPENDENCIES_H

include/swift/DependencyScan/ScanDependencies.h

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@
1010
//
1111
//===----------------------------------------------------------------------===//
1212

13-
#ifndef SWIFT_FRONTENDTOOL_SCANDEPENDENCIES_H
14-
#define SWIFT_FRONTENDTOOL_SCANDEPENDENCIES_H
13+
#ifndef SWIFT_DEPENDENCY_SCANDEPENDENCIES_H
14+
#define SWIFT_DEPENDENCY_SCANDEPENDENCIES_H
1515

1616
#include "llvm/ADT/StringRef.h"
17+
#include "llvm/Support/Error.h"
1718

1819
namespace llvm {
1920
class StringSaver;
@@ -27,47 +28,48 @@ class ModuleDependenciesCache;
2728

2829
namespace dependencies {
2930

31+
struct FullDependencies;
3032
struct BatchScanInput {
3133
llvm::StringRef moduleName;
3234
llvm::StringRef arguments;
3335
llvm::StringRef outputPath;
3436
bool isSwift;
3537
};
3638

37-
// MARK: swift-frontend -scan-dependencies entry points
39+
// MARK: FrontendTool dependency scanner entry points
3840
/// Scans the dependencies of the main module of \c instance and writes out
3941
/// the resulting JSON according to the instance's output parameters.
40-
/// This method is used for swift-frontend invocations in dependency scanning mode
41-
/// (-scan-dependencies), where the module dependency cache is not shared.
4242
bool scanDependencies(CompilerInstance &instance);
4343

44+
/// Identify all imports in the translation unit's module.
45+
bool prescanDependencies(CompilerInstance &instance);
46+
4447
/// Batch scan the dependencies for modules specified in \c batchInputFile.
4548
bool batchScanDependencies(CompilerInstance &instance,
4649
llvm::StringRef batchInputFile);
4750

48-
/// Identify all imports in the translation unit's module.
49-
bool prescanMainModuleDependencies(CompilerInstance &instance);
50-
51+
/// Batch prescan the imports of modules specified in \c batchInputFile.
52+
bool batchPrescanDependencies(CompilerInstance &instance,
53+
llvm::StringRef batchInputFile);
5154

52-
// MARK: dependency scanning execution
55+
// MARK: Dependency scanning execution
5356
/// Scans the dependencies of the main module of \c instance.
54-
bool performModuleScan(CompilerInstance &instance,
55-
ModuleDependenciesCache &cache,
56-
llvm::raw_ostream &out);
57+
llvm::ErrorOr<FullDependencies>
58+
performModuleScan(CompilerInstance &instance,
59+
ModuleDependenciesCache &cache);
5760

5861
/// Batch scan the dependencies for modules specified in \c batchInputFile.
59-
bool performBatchModuleScan(CompilerInstance &instance,
60-
ModuleDependenciesCache &cache,
61-
llvm::StringSaver &saver,
62-
const std::vector<BatchScanInput> &BatchInput);
63-
64-
/// Scan for dependencies of a module with a specified name, producing the resulting output
65-
/// at the specified output path.
66-
bool scanBatchModuleEntry(CompilerInstance &instance,
62+
std::vector<llvm::ErrorOr<FullDependencies>>
63+
performBatchModuleScan(CompilerInstance &instance,
64+
ModuleDependenciesCache &cache, llvm::StringSaver &saver,
65+
const std::vector<BatchScanInput> &BatchInput);
66+
67+
/// Batch prescan the imports of modules specified in \c batchInputFile.
68+
std::vector<llvm::ErrorOr<std::vector<std::string>>>
69+
performBatchModulePrescan(CompilerInstance &instance,
6770
ModuleDependenciesCache &cache,
68-
llvm::StringRef moduleName,
69-
bool isClang,
70-
llvm::StringRef outputPath);
71+
llvm::StringSaver &saver,
72+
const std::vector<BatchScanInput> &BatchInput);
7173

7274
} // end namespace dependencies
7375
} // end namespace swift

lib/DependencyScan/DependencyScanningTool.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "swift/DependencyScan/DependencyScanningTool.h"
14-
#include "swift/DependencyScan/ModuleInfo.h"
14+
#include "swift/DependencyScan/FullDependencies.h"
1515
#include "swift/AST/DiagnosticEngine.h"
1616
#include "swift/AST/DiagnosticsFrontend.h"
1717
#include "swift/Basic/LLVMInitialize.h"
@@ -28,7 +28,7 @@ DependencyScanningTool::DependencyScanningTool()
2828
: SharedCache(std::make_unique<ModuleDependenciesCache>()), PDC(), Alloc(),
2929
Saver(Alloc) {}
3030

31-
llvm::ErrorOr<std::string> DependencyScanningTool::getDependencies(
31+
llvm::ErrorOr<FullDependencies> DependencyScanningTool::getDependencies(
3232
ArrayRef<const char *> Command,
3333
const llvm::StringSet<> &PlaceholderModules) {
3434
// The primary instance used to scan the query Swift source-code
@@ -37,13 +37,13 @@ llvm::ErrorOr<std::string> DependencyScanningTool::getDependencies(
3737
return EC;
3838
auto Instance = std::move(*InstanceOrErr);
3939

40-
std::string JSONOutput;
41-
llvm::raw_string_ostream OSS(JSONOutput);
42-
performModuleScan(*Instance.get(), *SharedCache, OSS);
43-
OSS.flush();
40+
// Execute the scanning action, retreiving the in-memory result
41+
auto DependenciesOrErr = performModuleScan(*Instance.get(), *SharedCache);
42+
if (DependenciesOrErr.getError())
43+
return std::make_error_code(std::errc::not_supported);
44+
auto Dependencies = std::move(*DependenciesOrErr);
4445

45-
// TODO: swiftch to an in-memory representation
46-
return JSONOutput;
46+
return Dependencies;
4747
}
4848

4949
std::error_code DependencyScanningTool::getDependencies(

0 commit comments

Comments
 (0)