@@ -31,9 +31,19 @@ public struct ExplicitModuleBuildHandler {
3131 /// The toolchain to be used for frontend job generation.
3232 private let toolchain : Toolchain
3333
34- public init ( dependencyGraph: InterModuleDependencyGraph , toolchain: Toolchain ) throws {
34+ /// The file system which we should interact with.
35+ private let fileSystem : FileSystem
36+
37+ /// Path to the directory that will contain the temporary files.
38+ /// e.g. Explicit Swift module artifact files
39+ private let temporaryDirectory : AbsolutePath
40+
41+ public init ( dependencyGraph: InterModuleDependencyGraph , toolchain: Toolchain ,
42+ fileSystem: FileSystem ) throws {
3543 self . dependencyGraph = dependencyGraph
3644 self . toolchain = toolchain
45+ self . fileSystem = fileSystem
46+ self . temporaryDirectory = try determineTempDirectory ( )
3747 }
3848
3949 /// Generate build jobs for all dependencies of the main module.
@@ -97,17 +107,10 @@ public struct ExplicitModuleBuildHandler {
97107 /// - Generate Job: S1
98108 ///
99109 mutating public func generateExplicitModuleDependenciesBuildJobs( ) throws -> [ Job ] {
100- for moduleId in dependencyGraph. mainModule. directDependencies {
101- switch moduleId {
102- case . swift:
103- try genSwiftModuleBuildJob ( moduleId: moduleId)
104- case . clang:
105- try genClangModuleBuildJob ( moduleId: moduleId,
106- pcmArgs: try dependencyGraph. swiftModulePCMArgs (
107- of: . swift( dependencyGraph. mainModuleName) ) )
108- }
109- }
110-
110+ var mainModuleInputs : [ TypedVirtualPath ] = [ ]
111+ var mainModuleCommandLine : [ Job . ArgTemplate ] = [ ]
112+ try resolveMainModuleDependencies ( inputs: & mainModuleInputs,
113+ commandLine: & mainModuleCommandLine)
111114 return Array ( swiftModuleBuildCache. values) + clangTargetModuleBuildCache. allJobs
112115 }
113116
@@ -167,7 +170,6 @@ public struct ExplicitModuleBuildHandler {
167170 mutating private func genClangModuleBuildJob( moduleId: ModuleDependencyId ,
168171 pcmArgs: [ String ] ) throws {
169172 let moduleInfo = try dependencyGraph. moduleInfo ( of: moduleId)
170-
171173 var inputs : [ TypedVirtualPath ] = [ ]
172174 var outputs : [ TypedVirtualPath ] = [ ]
173175 var commandLine : [ Job . ArgTemplate ] = [ ]
@@ -207,6 +209,19 @@ public struct ExplicitModuleBuildHandler {
207209 )
208210 }
209211
212+ /// Store the output file artifacts for a given module in a JSON file, return the file's path.
213+ private func serializeModuleDependencies( for moduleId: ModuleDependencyId ,
214+ dependencyArtifacts: [ SwiftModuleArtifactInfo ]
215+ ) throws -> AbsolutePath {
216+ let dependencyFilePath =
217+ temporaryDirectory. appending ( component: " \( moduleId. moduleName) -dependencies.json " )
218+ let encoder = JSONEncoder ( )
219+ encoder. outputFormatting = [ . prettyPrinted]
220+ let contents = try encoder. encode ( dependencyArtifacts)
221+ try fileSystem. writeFileContents ( dependencyFilePath, bytes: ByteString ( contents) )
222+ return dependencyFilePath
223+ }
224+
210225 /// For the specified module, update the given command line flags and inputs
211226 /// to use explicitly-built module dependencies.
212227 ///
@@ -220,24 +235,45 @@ public struct ExplicitModuleBuildHandler {
220235 // Prohibit the frontend from implicitly building textual modules into binary modules.
221236 commandLine. appendFlags ( " -disable-implicit-swift-modules " , " -Xcc " , " -Xclang " , " -Xcc " ,
222237 " -fno-implicit-modules " )
238+ var swiftDependencyArtifacts : [ SwiftModuleArtifactInfo ] = [ ]
223239 try addModuleDependencies ( moduleId: moduleId, pcmArgs: pcmArgs, inputs: & inputs,
224- commandLine: & commandLine)
240+ commandLine: & commandLine,
241+ swiftDependencyArtifacts: & swiftDependencyArtifacts)
242+
243+ if !swiftDependencyArtifacts. isEmpty {
244+ let dependencyFile = try serializeModuleDependencies ( for: moduleId,
245+ dependencyArtifacts: swiftDependencyArtifacts)
246+ commandLine. appendFlag ( " -explicit-swift-module-map-file " )
247+ commandLine. appendPath ( dependencyFile)
248+ inputs. append ( TypedVirtualPath ( file: try VirtualPath ( path: dependencyFile. pathString) ,
249+ type: . jsonSwiftArtifacts) )
250+ // Each individual moduel binary is still an "input" to ensure the build system gets the
251+ // order correctly.
252+ for dependencyModule in swiftDependencyArtifacts {
253+ inputs. append ( TypedVirtualPath ( file: try VirtualPath ( path: dependencyModule. modulePath) ,
254+ type: . swiftModule) )
255+ }
256+ }
225257 }
226258
227259 /// Add a specific module dependency as an input and a corresponding command
228260 /// line flag. Dispatches to clang and swift-specific variants.
229261 mutating private func addModuleDependencies( moduleId: ModuleDependencyId ,
230262 pcmArgs: [ String ] ,
231263 inputs: inout [ TypedVirtualPath ] ,
232- commandLine: inout [ Job . ArgTemplate ] ) throws {
264+ commandLine: inout [ Job . ArgTemplate ] ,
265+ swiftDependencyArtifacts: inout [ SwiftModuleArtifactInfo ]
266+ ) throws {
233267 for dependencyId in try dependencyGraph. moduleInfo ( of: moduleId) . directDependencies {
234268 switch dependencyId {
235269 case . swift:
236270 try addSwiftModuleDependency ( moduleId: moduleId, dependencyId: dependencyId,
237- pcmArgs: pcmArgs, inputs: & inputs, commandLine: & commandLine)
271+ pcmArgs: pcmArgs, inputs: & inputs, commandLine: & commandLine,
272+ swiftDependencyArtifacts: & swiftDependencyArtifacts)
238273 case . clang:
239274 try addClangModuleDependency ( moduleId: moduleId, dependencyId: dependencyId,
240- pcmArgs: pcmArgs, inputs: & inputs, commandLine: & commandLine)
275+ pcmArgs: pcmArgs, inputs: & inputs, commandLine: & commandLine,
276+ swiftDependencyArtifacts: & swiftDependencyArtifacts)
241277 }
242278 }
243279 }
@@ -250,7 +286,9 @@ public struct ExplicitModuleBuildHandler {
250286 dependencyId: ModuleDependencyId ,
251287 pcmArgs: [ String ] ,
252288 inputs: inout [ TypedVirtualPath ] ,
253- commandLine: inout [ Job . ArgTemplate ] ) throws {
289+ commandLine: inout [ Job . ArgTemplate ] ,
290+ swiftDependencyArtifacts: inout [ SwiftModuleArtifactInfo ]
291+ ) throws {
254292 // Generate a build job for the dependency module, if not already generated
255293 if swiftModuleBuildCache [ dependencyId] == nil {
256294 try genSwiftModuleBuildJob ( moduleId: dependencyId)
@@ -261,13 +299,17 @@ public struct ExplicitModuleBuildHandler {
261299 let dependencyInfo = try dependencyGraph. moduleInfo ( of: dependencyId)
262300 let swiftModulePath = TypedVirtualPath ( file: try VirtualPath ( path: dependencyInfo. modulePath) ,
263301 type: . swiftModule)
264- commandLine. appendFlags ( " -swift-module-file " )
265- commandLine. appendPath ( swiftModulePath. file)
266- inputs. append ( swiftModulePath)
302+
303+ // Collect the requried information about this module
304+ // TODO: add .swiftdoc and .swiftsourceinfo for this module.
305+ swiftDependencyArtifacts. append (
306+ SwiftModuleArtifactInfo ( name: dependencyId. moduleName,
307+ modulePath: swiftModulePath. file. description) )
267308
268309 // Process all transitive dependencies as direct
269- try addModuleDependencies ( moduleId: dependencyId, pcmArgs: pcmArgs, inputs: & inputs,
270- commandLine: & commandLine)
310+ try addModuleDependencies ( moduleId: dependencyId, pcmArgs: pcmArgs,
311+ inputs: & inputs, commandLine: & commandLine,
312+ swiftDependencyArtifacts: & swiftDependencyArtifacts)
271313 }
272314
273315 /// Add a specific Clang module dependency as an input and a corresponding command
@@ -278,7 +320,9 @@ public struct ExplicitModuleBuildHandler {
278320 dependencyId: ModuleDependencyId ,
279321 pcmArgs: [ String ] ,
280322 inputs: inout [ TypedVirtualPath ] ,
281- commandLine: inout [ Job . ArgTemplate ] ) throws {
323+ commandLine: inout [ Job . ArgTemplate ] ,
324+ swiftDependencyArtifacts: inout [ SwiftModuleArtifactInfo ]
325+ ) throws {
282326 // Generate a build job for the dependency module at the given target, if not already generated
283327 if clangTargetModuleBuildCache [ ( dependencyId, pcmArgs) ] == nil {
284328 try genClangModuleBuildJob ( moduleId: dependencyId, pcmArgs: pcmArgs)
@@ -302,8 +346,9 @@ public struct ExplicitModuleBuildHandler {
302346 inputs. append ( clangModuleMapPath)
303347
304348 // Process all transitive dependencies as direct
305- try addModuleDependencies ( moduleId: dependencyId, pcmArgs: pcmArgs, inputs: & inputs,
306- commandLine: & commandLine)
349+ try addModuleDependencies ( moduleId: dependencyId, pcmArgs: pcmArgs,
350+ inputs: & inputs, commandLine: & commandLine,
351+ swiftDependencyArtifacts: & swiftDependencyArtifacts)
307352 }
308353}
309354
0 commit comments