@@ -19,11 +19,11 @@ extension Diagnostic.Message {
19
19
}
20
20
}
21
21
22
- internal extension Driver {
22
+ public extension Driver {
23
23
/// Precompute the dependencies for a given Swift compilation, producing a
24
24
/// dependency graph including all Swift and C module files and
25
25
/// source files.
26
- mutating func dependencyScanningJob( ) throws -> Job {
26
+ mutating private func dependencyScanningJob( ) throws -> Job {
27
27
let ( inputs, commandLine) = try dependencyScannerInvocationCommand ( )
28
28
29
29
// Construct the scanning job.
@@ -40,7 +40,7 @@ internal extension Driver {
40
40
41
41
/// Generate a full command-line invocation to be used for the dependency scanning action
42
42
/// on the target module.
43
- mutating func dependencyScannerInvocationCommand( )
43
+ mutating private func dependencyScannerInvocationCommand( )
44
44
throws -> ( [ TypedVirtualPath ] , [ Job . ArgTemplate ] ) {
45
45
// Aggregate the fast dependency scanner arguments
46
46
var inputs : [ TypedVirtualPath ] = [ ]
@@ -66,7 +66,7 @@ internal extension Driver {
66
66
}
67
67
68
68
/// Serialize a map of placeholder (external) dependencies for the dependency scanner.
69
- func serializeExternalDependencyArtifacts( externalBuildArtifacts: ExternalBuildArtifacts )
69
+ private func serializeExternalDependencyArtifacts( externalBuildArtifacts: ExternalBuildArtifacts )
70
70
throws -> VirtualPath {
71
71
let ( externalTargetModulePathMap, externalModuleInfoMap) = externalBuildArtifacts
72
72
var placeholderArtifacts : [ SwiftModuleArtifactInfo ] = [ ]
@@ -94,11 +94,8 @@ internal extension Driver {
94
94
contents)
95
95
}
96
96
97
- mutating func performDependencyScan( ) throws -> InterModuleDependencyGraph {
98
- let scannerJob = try dependencyScanningJob ( )
99
- let forceResponseFiles = parsedOptions. hasArgument ( . driverForceResponseFiles)
100
- let dependencyGraph : InterModuleDependencyGraph
101
-
97
+ /// Returns false if the lib is available and ready to use
98
+ private func initSwiftScanLib( ) throws -> Bool {
102
99
// If `-nonlib-dependency-scanner` was specified or the libSwiftScan library cannot be found,
103
100
// attempt to fallback to using `swift-frontend -scan-dependencies` invocations for dependency
104
101
// scanning.
@@ -110,20 +107,62 @@ internal extension Driver {
110
107
fallbackToFrontend = true
111
108
diagnosticEngine. emit ( . warn_scanner_frontend_fallback( ) )
112
109
}
110
+ return fallbackToFrontend
111
+ }
112
+
113
+ private func sanitizeCommandForLibScanInvocation( _ command: inout [ String ] ) {
114
+ // Remove the tool executable to only leave the arguments. When passing the
115
+ // command line into libSwiftScan, the library is itself the tool and only
116
+ // needs to parse the remaining arguments.
117
+ command. removeFirst ( )
118
+ // We generate full swiftc -frontend -scan-dependencies invocations in order to also be
119
+ // able to launch them as standalone jobs. Frontend's argument parser won't recognize
120
+ // -frontend when passed directly.
121
+ if command. first == " -frontend " {
122
+ command. removeFirst ( )
123
+ }
124
+ }
113
125
114
- if ( !fallbackToFrontend) {
126
+ mutating func performImportPrescan( ) throws -> InterModuleDependencyImports {
127
+ let preScanJob = try importPreScanningJob ( )
128
+ let forceResponseFiles = parsedOptions. hasArgument ( . driverForceResponseFiles)
129
+ let imports : InterModuleDependencyImports
130
+
131
+ let isSwiftScanLibAvailable = !( try initSwiftScanLib ( ) )
132
+ if isSwiftScanLibAvailable {
133
+ let cwd = workingDirectory ?? fileSystem. currentWorkingDirectory!
134
+ var command = try itemizedJobCommand ( of: preScanJob,
135
+ forceResponseFiles: forceResponseFiles,
136
+ using: executor. resolver)
137
+ sanitizeCommandForLibScanInvocation ( & command)
138
+ imports =
139
+ try interModuleDependencyOracle. getImports ( workingDirectory: cwd,
140
+ commandLine: command)
141
+
142
+ } else {
143
+ // Fallback to legacy invocation of the dependency scanner with
144
+ // `swift-frontend -scan-dependencies -import-prescan`
145
+ imports =
146
+ try self . executor. execute ( job: preScanJob,
147
+ capturingJSONOutputAs: InterModuleDependencyImports . self,
148
+ forceResponseFiles: forceResponseFiles,
149
+ recordedInputModificationDates: recordedInputModificationDates)
150
+ }
151
+ return imports
152
+ }
153
+
154
+ mutating internal func performDependencyScan( ) throws -> InterModuleDependencyGraph {
155
+ let scannerJob = try dependencyScanningJob ( )
156
+ let forceResponseFiles = parsedOptions. hasArgument ( . driverForceResponseFiles)
157
+ let dependencyGraph : InterModuleDependencyGraph
158
+
159
+ let isSwiftScanLibAvailable = !( try initSwiftScanLib ( ) )
160
+ if isSwiftScanLibAvailable {
115
161
let cwd = workingDirectory ?? fileSystem. currentWorkingDirectory!
116
162
var command = try itemizedJobCommand ( of: scannerJob,
117
163
forceResponseFiles: forceResponseFiles,
118
164
using: executor. resolver)
119
- // Remove the tool executable to only leave the arguments
120
- command. removeFirst ( )
121
- // We generate full swiftc -frontend -scan-dependencies invocations in order to also be
122
- // able to launch them as standalone jobs. Frontend's argument parser won't recognize
123
- // -frontend when passed directly.
124
- if command. first == " -frontend " {
125
- command. removeFirst ( )
126
- }
165
+ sanitizeCommandForLibScanInvocation ( & command)
127
166
dependencyGraph =
128
167
try interModuleDependencyOracle. getDependencies ( workingDirectory: cwd,
129
168
commandLine: command)
@@ -139,37 +178,19 @@ internal extension Driver {
139
178
return dependencyGraph
140
179
}
141
180
142
- mutating func performBatchDependencyScan( moduleInfos: [ BatchScanModuleInfo ] )
181
+ mutating internal func performBatchDependencyScan( moduleInfos: [ BatchScanModuleInfo ] )
143
182
throws -> [ ModuleDependencyId : [ InterModuleDependencyGraph ] ] {
144
183
let batchScanningJob = try batchDependencyScanningJob ( for: moduleInfos)
145
184
let forceResponseFiles = parsedOptions. hasArgument ( . driverForceResponseFiles)
146
-
147
- // If `-nonlib-dependency-scanner` was specified or the libSwiftScan library cannot be found,
148
- // attempt to fallback to using `swift-frontend -scan-dependencies` invocations for dependency
149
- // scanning.
150
- var fallbackToFrontend = parsedOptions. hasArgument ( . driverScanDependenciesNonLib)
151
- let scanLibPath = try Self . getScanLibPath ( of: toolchain, hostTriple: hostTriple, env: env)
152
- if try interModuleDependencyOracle
153
- . verifyOrCreateScannerInstance ( fileSystem: fileSystem,
154
- swiftScanLibPath: scanLibPath) == false {
155
- fallbackToFrontend = true
156
- diagnosticEngine. emit ( . warn_scanner_frontend_fallback( ) )
157
- }
158
-
159
185
let moduleVersionedGraphMap : [ ModuleDependencyId : [ InterModuleDependencyGraph ] ]
160
- if ( !fallbackToFrontend) {
186
+
187
+ let isSwiftScanLibAvailable = !( try initSwiftScanLib ( ) )
188
+ if isSwiftScanLibAvailable {
161
189
let cwd = workingDirectory ?? fileSystem. currentWorkingDirectory!
162
190
var command = try itemizedJobCommand ( of: batchScanningJob,
163
191
forceResponseFiles: forceResponseFiles,
164
192
using: executor. resolver)
165
- // Remove the tool executable to only leave the arguments
166
- command. removeFirst ( )
167
- // We generate full swiftc -frontend -scan-dependencies invocations in order to also be
168
- // able to launch them as standalone jobs. Frontend's argument parser won't recognize
169
- // -frontend when passed directly.
170
- if command. first == " -frontend " {
171
- command. removeFirst ( )
172
- }
193
+ sanitizeCommandForLibScanInvocation ( & command)
173
194
moduleVersionedGraphMap =
174
195
try interModuleDependencyOracle. getBatchDependencies ( workingDirectory: cwd,
175
196
commandLine: command,
@@ -226,8 +247,36 @@ internal extension Driver {
226
247
return moduleVersionedGraphMap
227
248
}
228
249
250
+ /// Precompute the set of module names as imported by the current module
251
+ mutating private func importPreScanningJob( ) throws -> Job {
252
+ // Aggregate the fast dependency scanner arguments
253
+ var inputs : [ TypedVirtualPath ] = [ ]
254
+ var commandLine : [ Job . ArgTemplate ] = swiftCompilerPrefixArgs. map { Job . ArgTemplate. flag ( $0) }
255
+ commandLine. appendFlag ( " -frontend " )
256
+ commandLine. appendFlag ( " -scan-dependencies " )
257
+ commandLine. appendFlag ( " -import-prescan " )
258
+ try addCommonFrontendOptions ( commandLine: & commandLine, inputs: & inputs,
259
+ bridgingHeaderHandling: . precompiled,
260
+ moduleDependencyGraphUse: . dependencyScan)
261
+ // FIXME: MSVC runtime flags
262
+
263
+ // Pass on the input files
264
+ commandLine. append ( contentsOf: inputFiles. map { . path( $0. file) } )
265
+
266
+ // Construct the scanning job.
267
+ return Job ( moduleName: moduleOutputInfo. name,
268
+ kind: . scanDependencies,
269
+ tool: VirtualPath . absolute ( try toolchain. getToolPath ( . swiftCompiler) ) ,
270
+ commandLine: commandLine,
271
+ displayInputs: inputs,
272
+ inputs: inputs,
273
+ primaryInputs: [ ] ,
274
+ outputs: [ TypedVirtualPath ( file: . standardOutput, type: . jsonDependencies) ] ,
275
+ supportsResponseFiles: true )
276
+ }
277
+
229
278
/// Precompute the dependencies for a given collection of modules using swift frontend's batch scanning mode
230
- mutating func batchDependencyScanningJob( for moduleInfos: [ BatchScanModuleInfo ] ) throws -> Job {
279
+ mutating private func batchDependencyScanningJob( for moduleInfos: [ BatchScanModuleInfo ] ) throws -> Job {
231
280
var inputs : [ TypedVirtualPath ] = [ ]
232
281
233
282
// Aggregate the fast dependency scanner arguments
0 commit comments