@@ -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,107 @@ 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
+ private func sanitizeInterfaceMap( _ map: [ String : [ TypedVirtualPath ] ] ) -> [ String : [ TypedVirtualPath ] ] {
694
+ return map. filter {
695
+ if $0. value. isEmpty {
696
+ diagEngine. emit ( warning: " \( $0. key) has no associated .swiftinterface files " )
697
+ return false
698
+ }
699
+ return true
700
+ }
701
+ }
702
+
703
+ public func collectSwiftInterfaceMap( ) throws -> [ String : [ TypedVirtualPath ] ] {
704
+ var results : [ String : [ TypedVirtualPath ] ] = [ : ]
705
+
706
+ func updateResults( _ dir: AbsolutePath ) throws {
707
+ if !localFileSystem. exists ( dir) {
708
+ return
709
+ }
710
+ let moduleName = dir. basenameWithoutExt
711
+ if results [ moduleName] == nil {
712
+ results [ moduleName] = [ ]
713
+ }
714
+
715
+ try localFileSystem. getDirectoryContents ( dir) . forEach {
716
+ let currentFile = AbsolutePath ( dir, try VirtualPath ( path: $0) . relativePath!)
717
+ if currentFile. extension == " swiftinterface " {
718
+ let currentBaseName = currentFile. basenameWithoutExt
719
+ let interfacePath = TypedVirtualPath ( file: VirtualPath . absolute ( currentFile) . intern ( ) ,
720
+ type: . swiftInterface)
721
+ if !results[ moduleName] !. contains ( where: { $0. file. basenameWithoutExt == currentBaseName } ) {
722
+ results [ moduleName] !. append ( interfacePath)
723
+ }
724
+ }
725
+ }
726
+ }
727
+ for dir in frameworkDirs {
728
+ let frameDir = AbsolutePath ( sdkPath, dir)
729
+ if !localFileSystem. exists ( frameDir) {
730
+ continue
731
+ }
732
+ try localFileSystem. getDirectoryContents ( frameDir) . forEach {
733
+ let frameworkPath = try VirtualPath ( path: $0)
734
+ if frameworkPath. extension != " framework " {
735
+ return
736
+ }
737
+ let moduleName = frameworkPath. basenameWithoutExt
738
+ let swiftModulePath = frameworkPath
739
+ . appending ( component: " Modules " )
740
+ . appending ( component: moduleName + " .swiftmodule " ) . relativePath!
741
+ try updateResults ( AbsolutePath ( frameDir, swiftModulePath) )
742
+ }
743
+ }
744
+ for dir in nonFrameworkDirs {
745
+ let swiftModuleDir = AbsolutePath ( sdkPath, dir)
746
+ if !localFileSystem. exists ( swiftModuleDir) {
747
+ continue
748
+ }
749
+ try localFileSystem. getDirectoryContents ( swiftModuleDir) . forEach {
750
+ if $0. hasSuffix ( " .swiftmodule " ) {
751
+ try updateResults ( AbsolutePath ( swiftModuleDir, $0) )
752
+ }
753
+ }
754
+ }
755
+ return sanitizeInterfaceMap ( results)
756
+ }
757
+ }
758
+
554
759
/// MARK: Planning
555
760
extension Driver {
556
761
/// Create a job if needed for simple requests that can be immediately
0 commit comments