@@ -24,6 +24,9 @@ extension Driver {
2424 var commandLine : [ Job . ArgTemplate ] = swiftCompilerPrefixArgs. map { Job . ArgTemplate. flag ( $0) }
2525 commandLine. appendFlag ( " -frontend " )
2626 commandLine. appendFlag ( " -scan-dependencies " )
27+ if parsedOptions. hasArgument ( . parseStdlib) {
28+ commandLine. appendFlag ( . disableObjcAttrRequiresFoundationModule)
29+ }
2730 try addCommonFrontendOptions ( commandLine: & commandLine, inputs: & inputs,
2831 bridgingHeaderHandling: . precompiled,
2932 moduleDependencyGraphUse: . dependencyScan)
@@ -72,105 +75,65 @@ extension Driver {
7275 return placeholderMapFilePath
7376 }
7477
75- mutating func performBatchDependencyScan( moduleInfos: [ BatchScanModuleInfo ] )
76- throws -> [ ModuleDependencyId : [ InterModuleDependencyGraph ] ] {
77- let batchScanningJob = try batchDependencyScanningJob ( for: moduleInfos)
78- let forceResponseFiles = parsedOptions. hasArgument ( . driverForceResponseFiles)
79- let batchScanResult =
80- try self . executor. execute ( job: batchScanningJob,
81- forceResponseFiles: forceResponseFiles,
82- recordedInputModificationDates: recordedInputModificationDates)
83- let success = batchScanResult. exitStatus == . terminated( code: EXIT_SUCCESS)
84- guard success else {
85- throw JobExecutionError . jobFailedWithNonzeroExitCode (
86- SwiftDriverExecutor . computeReturnCode ( exitStatus: batchScanResult. exitStatus) ,
87- try batchScanResult. utf8stderrOutput ( ) )
88- }
89-
90- // Decode the resulting dependency graphs and build a dictionary from a moduleId to
91- // a set of dependency graphs that were built for it
92- let moduleVersionedGraphMap =
93- try moduleInfos. reduce ( into: [ ModuleDependencyId: [ InterModuleDependencyGraph] ] ( ) ) {
94- let moduleId : ModuleDependencyId
95- let dependencyGraphPath : VirtualPath
96- switch $1 {
97- case . swift( let swiftModuleBatchScanInfo) :
98- moduleId = . swift( swiftModuleBatchScanInfo. swiftModuleName)
99- dependencyGraphPath = try VirtualPath ( path: swiftModuleBatchScanInfo. output)
100- case . clang( let clangModuleBatchScanInfo) :
101- moduleId = . clang( clangModuleBatchScanInfo. clangModuleName)
102- dependencyGraphPath = try VirtualPath ( path: clangModuleBatchScanInfo. output)
103- }
104- let contents = try fileSystem. readFileContents ( dependencyGraphPath)
105- let decodedGraph = try JSONDecoder ( ) . decode ( InterModuleDependencyGraph . self,
106- from: Data ( contents. contents) )
107- if $0 [ moduleId] != nil {
108- $0 [ moduleId] !. append ( decodedGraph)
109- } else {
110- $0 [ moduleId] = [ decodedGraph]
111- }
112- }
113- return moduleVersionedGraphMap
114- }
115-
116- /// Precompute the dependencies for a given collection of modules using swift frontend's batch scanning mode
117- mutating func batchDependencyScanningJob( for moduleInfos: [ BatchScanModuleInfo ] ) throws -> Job {
78+ /// Compute the dependencies for a given Clang module, by invoking the Clang dependency scanning action
79+ /// with the given module's name and a set of arguments (including the target version)
80+ mutating func clangDependencyScanningJob( moduleId: ModuleDependencyId ,
81+ pcmArgs: [ String ] ) throws -> Job {
11882 var inputs : [ TypedVirtualPath ] = [ ]
11983
12084 // Aggregate the fast dependency scanner arguments
12185 var commandLine : [ Job . ArgTemplate ] = swiftCompilerPrefixArgs. map { Job . ArgTemplate. flag ( $0) }
12286 commandLine. appendFlag ( " -frontend " )
123- // The dependency scanner automatically operates in batch mode if -batch-scan-input-file
124- // is present.
125- commandLine. appendFlag ( " -scan-dependencies " )
87+ commandLine. appendFlag ( " -scan-clang-dependencies " )
88+
12689 try addCommonFrontendOptions ( commandLine: & commandLine, inputs: & inputs,
12790 bridgingHeaderHandling: . precompiled,
12891 moduleDependencyGraphUse: . dependencyScan)
12992
130- let batchScanInputFilePath = try serializeBatchScanningModuleArtifacts ( moduleInfos: moduleInfos)
131- commandLine. appendFlag ( " -batch-scan-input-file " )
132- commandLine. appendPath ( batchScanInputFilePath)
93+ // Ensure the `-target` option is inherited from the dependent Swift module's PCM args
94+ if let targetOptionIndex = pcmArgs. firstIndex ( of: Option . target. spelling) {
95+ // PCM args are formulated as Clang command line options specified with:
96+ // -Xcc <option> -Xcc <option_value>
97+ assert ( pcmArgs. count > targetOptionIndex + 1 && pcmArgs [ targetOptionIndex + 1 ] == " -Xcc " )
98+ let pcmArgTriple = Triple ( pcmArgs [ targetOptionIndex + 2 ] )
99+ // Override the invocation's default target argument by appending the one extracted from
100+ // the pcmArgs
101+ commandLine. appendFlag ( . target)
102+ commandLine. appendFlag ( pcmArgTriple. triple)
103+ }
104+
105+ // Add the PCM args specific to this scan
106+ pcmArgs. forEach { commandLine. appendFlags ( $0) }
133107
134108 // This action does not require any input files, but all frontend actions require
135109 // at least one input so pick any input of the current compilation.
136110 let inputFile = inputFiles. first { $0. type == . swift }
137111 commandLine. appendPath ( inputFile!. file)
138112 inputs. append ( inputFile!)
139113
140- // This job's outputs are defined as a set of dependency graph json files
141- let outputs : [ TypedVirtualPath ] = try moduleInfos. map {
142- switch $0 {
143- case . swift( let swiftModuleBatchScanInfo) :
144- return TypedVirtualPath ( file: try VirtualPath ( path: swiftModuleBatchScanInfo. output) ,
145- type: . jsonDependencies)
146- case . clang( let clangModuleBatchScanInfo) :
147- return TypedVirtualPath ( file: try VirtualPath ( path: clangModuleBatchScanInfo. output) ,
148- type: . jsonDependencies)
149- }
150- }
151-
114+ commandLine. appendFlags ( " -module-name " , moduleId. moduleName)
152115 // Construct the scanning job.
153116 return Job ( moduleName: moduleOutputInfo. name,
154- kind: . scanDependencies ,
117+ kind: . scanClangDependencies ,
155118 tool: VirtualPath . absolute ( try toolchain. getToolPath ( . swiftCompiler) ) ,
156119 commandLine: commandLine,
157120 displayInputs: inputs,
158121 inputs: inputs,
159- outputs: outputs ,
122+ outputs: [ TypedVirtualPath ( file : . standardOutput , type : . jsonDependencies ) ] ,
160123 supportsResponseFiles: true )
161124 }
162125
163- /// Serialize a collection of modules into an input format expected by the batch module dependency scanner.
164- func serializeBatchScanningModuleArtifacts( moduleInfos: [ BatchScanModuleInfo ] )
165- throws -> AbsolutePath {
166- let temporaryDirectory = try determineTempDirectory ( )
167- let batchScanInputFilePath =
168- temporaryDirectory. appending ( component: " \( moduleOutputInfo. name) -batch-module-scan.json " )
126+ mutating func scanClangModule( moduleId: ModuleDependencyId , pcmArgs: [ String ] )
127+ throws -> InterModuleDependencyGraph {
128+ let clangDependencyScannerJob = try clangDependencyScanningJob ( moduleId: moduleId,
129+ pcmArgs: pcmArgs)
130+ let forceResponseFiles = parsedOptions. hasArgument ( . driverForceResponseFiles)
169131
170- let encoder = JSONEncoder ( )
171- encoder. outputFormatting = [ . prettyPrinted]
172- let contents = try encoder. encode ( moduleInfos)
173- try fileSystem. writeFileContents ( batchScanInputFilePath, bytes: ByteString ( contents) )
174- return batchScanInputFilePath
132+ let dependencyGraph =
133+ try self . executor. execute ( job: clangDependencyScannerJob,
134+ capturingJSONOutputAs: InterModuleDependencyGraph . self,
135+ forceResponseFiles: forceResponseFiles,
136+ recordedInputModificationDates: recordedInputModificationDates)
137+ return dependencyGraph
175138 }
176139}
0 commit comments