@@ -45,6 +45,8 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
4545  /// Whether we are using the integrated driver via libSwiftDriver shared lib
4646  private  let  integratedDriver :  Bool 
4747  private  let  mainModuleName :  String ? 
48+   private  let  enableCAS :  Bool 
49+   private  let  swiftScanOracle :  InterModuleDependencyOracle 
4850
4951  /// Clang PCM names contain a hash of the command-line arguments that were used to build them.
5052  /// We avoid re-running the hash computation with the use of this cache
@@ -55,14 +57,18 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
5557
5658  public  init ( dependencyGraph:  InterModuleDependencyGraph , 
5759              toolchain:  Toolchain , 
60+               dependencyOracle:  InterModuleDependencyOracle , 
5861              integratedDriver:  Bool  =  true , 
59-               supportsExplicitInterfaceBuild:  Bool  =  false )  throws  { 
62+               supportsExplicitInterfaceBuild:  Bool  =  false , 
63+               enableCAS:  Bool  =  false )  throws  { 
6064    self . dependencyGraph =  dependencyGraph
6165    self . toolchain =  toolchain
66+     self . swiftScanOracle =  dependencyOracle
6267    self . integratedDriver =  integratedDriver
6368    self . mainModuleName =  dependencyGraph. mainModuleName
6469    self . reachabilityMap =  try . computeTransitiveClosure ( ) 
6570    self . supportsExplicitInterfaceBuild =  supportsExplicitInterfaceBuild
71+     self . enableCAS =  enableCAS
6672  } 
6773
6874  /// Generate build jobs for all dependencies of the main module.
@@ -136,7 +142,8 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
136142      // Resolve all dependency module inputs for this Swift module
137143      try resolveExplicitModuleDependencies ( moduleId:  moduleId, 
138144                                            inputs:  & inputs, 
139-                                             commandLine:  & commandLine) 
145+                                             commandLine:  & commandLine, 
146+                                             isMainModule:  false ) 
140147
141148      // Build the .swiftinterfaces file using a list of command line options specified in the
142149      // `details` field.
@@ -192,7 +199,8 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
192199
193200      // Resolve all dependency module inputs for this Clang module
194201      try resolveExplicitModuleDependencies ( moduleId:  moduleId,  inputs:  & inputs, 
195-                                             commandLine:  & commandLine) 
202+                                             commandLine:  & commandLine, 
203+                                             isMainModule:  false ) 
196204
197205      let  moduleMapPath  =  moduleDetails. moduleMapPath. path
198206      let  modulePCMPath  =  moduleInfo. modulePath
@@ -221,7 +229,8 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
221229  /// to use explicitly-built module dependencies.
222230  private  mutating  func  resolveExplicitModuleDependencies( moduleId:  ModuleDependencyId , 
223231                                                          inputs:  inout  [ TypedVirtualPath ] , 
224-                                                           commandLine:  inout  [ Job . ArgTemplate ] )  throws  { 
232+                                                           commandLine:  inout  [ Job . ArgTemplate ] , 
233+                                                           isMainModule:  Bool )  throws  { 
225234    // Prohibit the frontend from implicitly building textual modules into binary modules.
226235    var  swiftDependencyArtifacts :  [ SwiftModuleArtifactInfo ]  =  [ ] 
227236    var  clangDependencyArtifacts :  [ ClangModuleArtifactInfo ]  =  [ ] 
@@ -256,15 +265,24 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
256265
257266    // Swift Main Module dependencies are passed encoded in a JSON file as described by
258267    // SwiftModuleArtifactInfo
259-     if  moduleId. moduleName ==  mainModuleName { 
260-       let  dependencyFile  = 
261-         try serializeModuleDependencies ( for:  moduleId, 
262-                                         swiftDependencyArtifacts:  swiftDependencyArtifacts, 
263-                                         clangDependencyArtifacts:  clangDependencyArtifacts) 
264-       commandLine. appendFlag ( " -explicit-swift-module-map-file " ) 
265-       commandLine. appendPath ( dependencyFile) 
266-       inputs. append ( TypedVirtualPath ( file:  dependencyFile. intern ( ) , 
267-                                      type:  . jsonSwiftArtifacts) ) 
268+     if  isMainModule { 
269+       if  enableCAS { 
270+         let  dependencyFile  = 
271+           try serializeModuleDependenciesToCAS ( for:  moduleId, 
272+                                                swiftDependencyArtifacts:  swiftDependencyArtifacts, 
273+                                                clangDependencyArtifacts:  clangDependencyArtifacts) 
274+         commandLine. appendFlag ( " -explicit-swift-module-map-file " ) 
275+         commandLine. appendFlag ( dependencyFile) 
276+       }  else  { 
277+         let  dependencyFile  = 
278+           try serializeModuleDependencies ( for:  moduleId, 
279+                                           swiftDependencyArtifacts:  swiftDependencyArtifacts, 
280+                                           clangDependencyArtifacts:  clangDependencyArtifacts) 
281+         commandLine. appendFlag ( " -explicit-swift-module-map-file " ) 
282+         commandLine. appendPath ( dependencyFile) 
283+         inputs. append ( TypedVirtualPath ( file:  dependencyFile. intern ( ) , 
284+                                        type:  . jsonSwiftArtifacts) ) 
285+       } 
268286    } 
269287  } 
270288
@@ -280,13 +298,15 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
280298        let  isFramework :  Bool 
281299        swiftModulePath =  . init( file:  dependencyInfo. modulePath. path, 
282300                                type:  . swiftModule) 
283-         isFramework =  try . swiftModuleDetails ( of:  dependencyId) . isFramework ??  false 
301+         let  swiftModuleDetails  =  try . swiftModuleDetails ( of:  dependencyId) 
302+         isFramework =  swiftModuleDetails. isFramework ??  false 
284303        // Accumulate the required information about this dependency
285304        // TODO: add .swiftdoc and .swiftsourceinfo for this module.
286305        swiftDependencyArtifacts. append ( 
287306          SwiftModuleArtifactInfo ( name:  dependencyId. moduleName, 
288307                                  modulePath:  TextualVirtualPath ( path:  swiftModulePath. fileHandle) , 
289-                                   isFramework:  isFramework) ) 
308+                                   isFramework:  isFramework, 
309+                                   moduleCacheKey:  swiftModuleDetails. moduleCacheKey) ) 
290310      case  . clang: 
291311        let  dependencyInfo  =  try . moduleInfo ( of:  dependencyId) 
292312        let  dependencyClangModuleDetails  = 
@@ -295,7 +315,8 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
295315        clangDependencyArtifacts. append ( 
296316          ClangModuleArtifactInfo ( name:  dependencyId. moduleName, 
297317                                  modulePath:  TextualVirtualPath ( path:  dependencyInfo. modulePath. path) , 
298-                                   moduleMapPath:  dependencyClangModuleDetails. moduleMapPath) ) 
318+                                   moduleMapPath:  dependencyClangModuleDetails. moduleMapPath, 
319+                                   moduleCacheKey:  dependencyClangModuleDetails. moduleCacheKey) ) 
299320      case  . swiftPrebuiltExternal: 
300321        let  prebuiltModuleDetails  =  try . swiftPrebuiltDetails ( of:  dependencyId) 
301322        let  compiledModulePath  =  prebuiltModuleDetails. compiledModulePath
@@ -308,7 +329,8 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
308329          SwiftModuleArtifactInfo ( name:  dependencyId. moduleName, 
309330                                  modulePath:  TextualVirtualPath ( path:  swiftModulePath. fileHandle) , 
310331                                  headerDependencies:  prebuiltModuleDetails. headerDependencyPaths, 
311-                                   isFramework:  isFramework) ) 
332+                                   isFramework:  isFramework, 
333+                                   moduleCacheKey:  prebuiltModuleDetails. moduleCacheKey) ) 
312334      case  . swiftPlaceholder: 
313335        fatalError ( " Unresolved placeholder dependencies at planning stage:  \( dependencyId)  of  \( moduleId) " ) 
314336    } 
@@ -354,24 +376,25 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
354376  public  mutating  func  resolveMainModuleDependencies( inputs:  inout  [ TypedVirtualPath ] , 
355377                                                     commandLine:  inout  [ Job . ArgTemplate ] )  throws  { 
356378    let  mainModuleId :  ModuleDependencyId  =  . swift( dependencyGraph. mainModuleName) 
379+ 
380+     let  mainModuleDetails  =  try . swiftModuleDetails ( of:  mainModuleId) 
381+     if  let  additionalArgs =  mainModuleDetails. commandLine { 
382+       additionalArgs. forEach  {  commandLine. appendFlag ( $0)  } 
383+     } 
357384    commandLine. appendFlags ( " -disable-implicit-swift-modules " , 
358385                            " -Xcc " ,  " -fno-implicit-modules " , 
359386                            " -Xcc " ,  " -fno-implicit-module-maps " ) 
360387    try resolveExplicitModuleDependencies ( moduleId:  mainModuleId, 
361388                                          inputs:  & inputs, 
362-                                           commandLine:  & commandLine) 
389+                                           commandLine:  & commandLine, 
390+                                           isMainModule:  true ) 
363391  } 
364392
365393  /// Resolve all module dependencies of the main module and add them to the lists of
366394  /// inputs and command line flags.
367395  public  mutating  func  resolveBridgingHeaderDependencies( inputs:  inout  [ TypedVirtualPath ] , 
368396                                                         commandLine:  inout  [ Job . ArgTemplate ] )  throws  { 
369397    let  mainModuleId :  ModuleDependencyId  =  . swift( dependencyGraph. mainModuleName) 
370-     // Prohibit the frontend from implicitly building textual modules into binary modules.
371-     commandLine. appendFlags ( " -disable-implicit-swift-modules " , 
372-                             " -Xcc " ,  " -fno-implicit-modules " , 
373-                             " -Xcc " ,  " -fno-implicit-module-maps " ) 
374- 
375398    var  swiftDependencyArtifacts :  [ SwiftModuleArtifactInfo ]  =  [ ] 
376399    var  clangDependencyArtifacts :  [ ClangModuleArtifactInfo ]  =  [ ] 
377400    let  mainModuleDetails  =  try . swiftModuleDetails ( of:  mainModuleId) 
@@ -409,14 +432,34 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
409432      inputs. append ( clangModuleMapPath) 
410433    } 
411434
412-     let  dependencyFile  = 
413-     try serializeModuleDependencies ( for:  mainModuleId, 
414-                                     swiftDependencyArtifacts:  swiftDependencyArtifacts, 
415-                                     clangDependencyArtifacts:  clangDependencyArtifacts) 
416-     commandLine. appendFlag ( " -explicit-swift-module-map-file " ) 
417-     commandLine. appendPath ( dependencyFile) 
418-     inputs. append ( TypedVirtualPath ( file:  dependencyFile. intern ( ) , 
419-                                    type:  . jsonSwiftArtifacts) ) 
435+     // Return if depscanner provided build commands.
436+     if  enableCAS,  let  scannerPCHArgs =  mainModuleDetails. bridgingPchCommandLine { 
437+       scannerPCHArgs. forEach  {  commandLine. appendFlag ( $0)  } 
438+       return 
439+     } 
440+ 
441+     // Prohibit the frontend from implicitly building textual modules into binary modules.
442+     commandLine. appendFlags ( " -disable-implicit-swift-modules " , 
443+                             " -Xcc " ,  " -fno-implicit-modules " , 
444+                             " -Xcc " ,  " -fno-implicit-module-maps " ) 
445+ 
446+     if  enableCAS { 
447+       let  dependencyFile  = 
448+       try serializeModuleDependenciesToCAS ( for:  mainModuleId, 
449+                                            swiftDependencyArtifacts:  swiftDependencyArtifacts, 
450+                                            clangDependencyArtifacts:  clangDependencyArtifacts) 
451+       commandLine. appendFlag ( " -explicit-swift-module-map-file " ) 
452+       commandLine. appendFlag ( dependencyFile) 
453+     }  else  { 
454+       let  dependencyFile  = 
455+       try serializeModuleDependencies ( for:  mainModuleId, 
456+                                       swiftDependencyArtifacts:  swiftDependencyArtifacts, 
457+                                       clangDependencyArtifacts:  clangDependencyArtifacts) 
458+       commandLine. appendFlag ( " -explicit-swift-module-map-file " ) 
459+       commandLine. appendPath ( dependencyFile) 
460+       inputs. append ( TypedVirtualPath ( file:  dependencyFile. intern ( ) , 
461+                                      type:  . jsonSwiftArtifacts) ) 
462+     } 
420463  } 
421464
422465  /// Store the output file artifacts for a given module in a JSON file, return the file's path.
@@ -433,6 +476,22 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT
433476    return  VirtualPath . createUniqueTemporaryFileWithKnownContents ( . init( " \( moduleId. moduleName) -dependencies.json " ) ,  contents) 
434477  } 
435478
479+   private  func  serializeModuleDependenciesToCAS( for moduleId:  ModuleDependencyId , 
480+                                            swiftDependencyArtifacts:  [ SwiftModuleArtifactInfo ] , 
481+                                            clangDependencyArtifacts:  [ ClangModuleArtifactInfo ] 
482+   )  throws  ->  String  { 
483+     // The module dependency map in CAS needs to be stable.
484+     // Sort the dependencies by name.
485+     let  allDependencyArtifacts :  [ ModuleDependencyArtifactInfo ]  = 
486+       swiftDependencyArtifacts. sorted ( ) . map  { ModuleDependencyArtifactInfo . swift ( $0) }  + 
487+       clangDependencyArtifacts. sorted ( ) . map  { ModuleDependencyArtifactInfo . clang ( $0) } 
488+     let  encoder  =  JSONEncoder ( ) 
489+     // Use sorted key to ensure the order of the keys is stable.
490+     encoder. outputFormatting =  [ . prettyPrinted,  . sortedKeys] 
491+     let  contents  =  try . encode ( allDependencyArtifacts) 
492+     return  try . store ( data:  contents) 
493+   } 
494+ 
436495  private  func  getPCMHashParts( pcmArgs:  [ String ] ,  contextHash:  String )  ->  [ String ]  { 
437496    var  results :  [ String ]  =  [ ] 
438497    results. append ( contextHash) 
0 commit comments