@@ -496,6 +496,110 @@ extension Driver {
496
496
return try explicitDependencyBuildPlanner!. generateExplicitModuleDependenciesBuildJobs ( )
497
497
}
498
498
499
+
500
+ public mutating func generatePrebuitModuleGenerationJobs( _ inputMap: [ String : [ TypedVirtualPath ] ] ,
501
+ _ prebuiltModuleDir: AbsolutePath ) throws -> [ Job ] {
502
+ guard let rawSdkPath = frontendTargetInfo. sdkPath? . path else {
503
+ // cannot proceed without SDK path
504
+ return [ ]
505
+ }
506
+ let sdkPath = VirtualPath . lookup ( rawSdkPath)
507
+ // Run the dependency scanner and update the dependency oracle with the results
508
+ let dependencyGraph = try gatherModuleDependencies ( )
509
+ var jobs : [ Job ] = [ ]
510
+
511
+ // Create directories for each Swift module
512
+ try inputMap. forEach {
513
+ assert ( !$0. value. isEmpty)
514
+ try localFileSystem. createDirectory ( prebuiltModuleDir
515
+ . appending ( RelativePath ( $0. key + " .swiftmodule " ) ) )
516
+ }
517
+
518
+ let outputMap : [ String : [ TypedVirtualPath ] ] =
519
+ Dictionary . init ( uniqueKeysWithValues: inputMap. map { key, value in
520
+ let outputPaths : [ TypedVirtualPath ] = value. map {
521
+ let path = prebuiltModuleDir. appending ( RelativePath ( key + " .swiftmodule " ) )
522
+ . appending ( RelativePath ( $0. file. basenameWithoutExt + " .swiftmodule " ) )
523
+ return TypedVirtualPath ( file: VirtualPath . absolute ( path) . intern ( ) ,
524
+ type: . swiftModule)
525
+ }
526
+ return ( key, outputPaths)
527
+ } )
528
+
529
+ func isIosMac( _ path: TypedVirtualPath ) -> Bool {
530
+ return path. file. basenameWithoutExt. contains ( " macabi " )
531
+ }
532
+
533
+ func getDependenciesPaths( _ module: String , _ iosMac: Bool ) throws -> [ TypedVirtualPath ] {
534
+ var results : [ TypedVirtualPath ] = [ ]
535
+ let info = dependencyGraph. modules [ . swift( module) ] !
536
+ guard let dependencies = info. directDependencies else {
537
+ return results
538
+ }
539
+
540
+ for dep in dependencies {
541
+ if case let . swift( moduleName) = dep {
542
+ if let outputs = outputMap [ moduleName] {
543
+ results. append ( contentsOf: outputs. filter { isIosMac ( $0) == iosMac } )
544
+ }
545
+ }
546
+ }
547
+ return results
548
+ }
549
+
550
+ let iosMacFrameworks = sdkPath
551
+ . appending ( component: " System " )
552
+ . appending ( component: " iOSSupport " )
553
+ . appending ( component: " System " )
554
+ . appending ( component: " Library " )
555
+ . appending ( component: " Frameworks " )
556
+ let moduleInfo = dependencyGraph. mainModule
557
+ if let dependencies = moduleInfo. directDependencies {
558
+ for dep in dependencies {
559
+ let moduleName = dep. moduleName
560
+ if let inputPaths = inputMap [ moduleName] {
561
+ let outputPaths = outputMap [ moduleName] !
562
+ assert ( inputPaths. count == outputPaths. count)
563
+ assert ( !inputPaths. isEmpty)
564
+ for i in 0 ..< inputPaths. count {
565
+ let inputPath = inputPaths [ i]
566
+ let outputPath = outputPaths [ i]
567
+ var commandLine : [ Job . ArgTemplate ] = [ ]
568
+ commandLine. appendFlag ( . compileModuleFromInterface)
569
+ commandLine. appendFlag ( . sdk)
570
+ commandLine. append ( . path( sdkPath) )
571
+ commandLine. appendFlag ( . prebuiltModuleCachePath)
572
+ commandLine. appendPath ( prebuiltModuleDir)
573
+ commandLine. appendFlag ( . moduleName)
574
+ commandLine. appendFlag ( moduleName)
575
+ commandLine. appendFlag ( . o)
576
+ commandLine. appendPath ( outputPath. file)
577
+ commandLine. appendPath ( inputPath. file)
578
+ if moduleName == " Swift " {
579
+ commandLine. appendFlag ( . parseStdlib)
580
+ }
581
+ if isIosMac ( inputPath) {
582
+ commandLine. appendFlag ( . Fsystem)
583
+ commandLine. append ( . path( iosMacFrameworks) )
584
+ }
585
+ commandLine. appendFlag ( . serializeParseableModuleInterfaceDependencyHashes)
586
+ jobs. append ( Job (
587
+ moduleName: moduleName,
588
+ kind: . compile,
589
+ tool: . absolute( try toolchain. getToolPath ( . swiftCompiler) ) ,
590
+ commandLine: commandLine,
591
+ inputs: try getDependenciesPaths ( moduleName, isIosMac ( inputPath) ) ,
592
+ primaryInputs: [ ] ,
593
+ outputs: [ outputPath]
594
+ ) )
595
+ }
596
+ }
597
+ }
598
+ }
599
+
600
+ return jobs
601
+ }
602
+
499
603
private mutating func gatherModuleDependencies( )
500
604
throws -> InterModuleDependencyGraph {
501
605
var dependencyGraph = try performDependencyScan ( )
@@ -551,6 +655,99 @@ extension Driver {
551
655
552
656
}
553
657
658
+ public struct SDKPrebuiltModuleInputsCollector {
659
+ let sdkPath : AbsolutePath
660
+ let nonFrameworkDirs = [ RelativePath ( " usr/lib/swift " ) ,
661
+ RelativePath ( " System/iOSSupport/usr/lib/swift " ) ]
662
+ let frameworkDirs = [ RelativePath ( " System/Library/Frameworks " ) ,
663
+ RelativePath ( " System/iOSSupport/System/Library/Frameworks " ) ]
664
+ let sdkInfo : DarwinToolchain . DarwinSDKInfo
665
+ let diagEngine : DiagnosticsEngine
666
+ public init ( _ sdkPath: AbsolutePath , _ diagEngine: DiagnosticsEngine ) {
667
+ self . sdkPath = sdkPath
668
+ self . sdkInfo = DarwinToolchain . readSDKInfo ( localFileSystem,
669
+ VirtualPath . absolute ( sdkPath) . intern ( ) ) !
670
+ self . diagEngine = diagEngine
671
+ }
672
+
673
+ public var targetTriple : String {
674
+ let canonicalName = sdkInfo. canonicalName
675
+ func extractVersion( _ platform: String ) -> Substring ? {
676
+ if canonicalName. starts ( with: platform) {
677
+ return canonicalName. suffix ( from: canonicalName. index ( canonicalName. startIndex,
678
+ offsetBy: platform. count) )
679
+ }
680
+ return nil
681
+ }
682
+
683
+ if let version = extractVersion ( " macosx " ) {
684
+ return " x86_64-apple-macosx \( version) "
685
+ } else if let version = extractVersion ( " iphoneos " ) {
686
+ return " arm64-apple-ios \( version) "
687
+ } else {
688
+ diagEngine. emit ( error: " unhandled platform name: \( canonicalName) " )
689
+ return " "
690
+ }
691
+ }
692
+
693
+ public func collectSwiftInterfaceMap( ) throws -> [ String : [ TypedVirtualPath ] ] {
694
+ var results : [ String : [ TypedVirtualPath ] ] = [ : ]
695
+
696
+ func updateResults( _ dir: AbsolutePath ) throws {
697
+ if !localFileSystem. exists ( dir) {
698
+ return
699
+ }
700
+ let moduleName = dir. basenameWithoutExt
701
+ if results [ moduleName] == nil {
702
+ results [ moduleName] = [ ]
703
+ }
704
+
705
+ try localFileSystem. getDirectoryContents ( dir) . forEach {
706
+ let currentFile = AbsolutePath ( dir, try VirtualPath ( path: $0) . relativePath!)
707
+ if currentFile. extension == " swiftinterface " {
708
+ let currentBaseName = currentFile. basenameWithoutExt
709
+ let interfacePath = TypedVirtualPath ( file: VirtualPath . absolute ( currentFile) . intern ( ) ,
710
+ type: . swiftInterface)
711
+ if !results[ moduleName] !. contains ( where: { $0. file. basenameWithoutExt == currentBaseName } ) {
712
+ results [ moduleName] !. append ( interfacePath)
713
+ }
714
+ }
715
+ }
716
+ }
717
+ for dir in frameworkDirs {
718
+ let frameDir = AbsolutePath ( sdkPath, dir)
719
+ if !localFileSystem. exists ( frameDir) {
720
+ continue
721
+ }
722
+ try localFileSystem. getDirectoryContents ( frameDir) . forEach {
723
+ let frameworkPath = try VirtualPath ( path: $0)
724
+ if frameworkPath. extension != " framework " {
725
+ return
726
+ }
727
+ let moduleName = frameworkPath. basenameWithoutExt
728
+ let swiftModulePath = frameworkPath
729
+ . appending ( component: " Modules " )
730
+ . appending ( component: moduleName + " .swiftmodule " ) . relativePath!
731
+ try updateResults ( AbsolutePath ( frameDir, swiftModulePath) )
732
+ }
733
+ }
734
+ for dir in nonFrameworkDirs {
735
+ let swiftModuleDir = AbsolutePath ( sdkPath, dir)
736
+ if !localFileSystem. exists ( swiftModuleDir) {
737
+ continue
738
+ }
739
+ try localFileSystem. getDirectoryContents ( swiftModuleDir) . forEach {
740
+ let swiftModulePath = try VirtualPath ( path: $0) . relativePath!
741
+ if swiftModulePath. extension != " swiftmodule " {
742
+ return
743
+ }
744
+ try updateResults ( AbsolutePath ( swiftModuleDir, swiftModulePath) )
745
+ }
746
+ }
747
+ return results
748
+ }
749
+ }
750
+
554
751
/// MARK: Planning
555
752
extension Driver {
556
753
/// Create a job if needed for simple requests that can be immediately
0 commit comments