@@ -28,20 +28,15 @@ struct FrameworkBuilder {
28
28
/// Flag for building dynamic frameworks instead of static frameworks.
29
29
private let dynamicFrameworks : Bool
30
30
31
- /// Flag for whether or not Carthage artifacts should be built as well.
32
- private let buildCarthage : Bool
33
-
34
31
/// The Pods directory for building the framework.
35
32
private var podsDir : URL {
36
33
return projectDir. appendingPathComponent ( " Pods " , isDirectory: true )
37
34
}
38
35
39
36
/// Default initializer.
40
- init ( projectDir: URL , platform: Platform , includeCarthage: Bool ,
41
- dynamicFrameworks: Bool ) {
37
+ init ( projectDir: URL , platform: Platform , dynamicFrameworks: Bool ) {
42
38
self . projectDir = projectDir
43
39
targetPlatforms = platform. platformTargets
44
- buildCarthage = includeCarthage && platform == . iOS
45
40
self . dynamicFrameworks = dynamicFrameworks
46
41
}
47
42
@@ -52,11 +47,13 @@ struct FrameworkBuilder {
52
47
///
53
48
/// - Parameter framework: The name of the framework to be built.
54
49
/// - Parameter logsOutputDir: The path to the directory to place build logs.
50
+ /// - Parameter setCarthage: Set Carthage diagnostics flag in build.
55
51
/// - Parameter moduleMapContents: Module map contents for all frameworks in this pod.
56
- /// - Returns: A path to the newly compiled frameworks, the Carthage frameworks, and Resources.
52
+ /// - Returns: A path to the newly compiled frameworks, and Resources.
57
53
func compileFrameworkAndResources( withName framework: String ,
58
54
logsOutputDir: URL ? = nil ,
59
- podInfo: CocoaPodUtils . PodInfo ) -> ( [ URL ] , URL ? , URL ? ) {
55
+ setCarthage: Bool ,
56
+ podInfo: CocoaPodUtils . PodInfo ) -> ( [ URL ] , URL ? ) {
60
57
let fileManager = FileManager . default
61
58
let outputDir = fileManager. temporaryDirectory ( withName: " frameworks_being_built " )
62
59
let logsDir = logsOutputDir ?? fileManager. temporaryDirectory ( withName: " build_logs " )
@@ -78,10 +75,15 @@ struct FrameworkBuilder {
78
75
79
76
if dynamicFrameworks {
80
77
return ( buildDynamicFrameworks ( withName: framework, logsDir: logsDir, outputDir: outputDir) ,
81
- nil , nil )
78
+ nil )
82
79
} else {
83
- return buildStaticFrameworks ( withName: framework, logsDir: logsDir, outputDir: outputDir,
84
- podInfo: podInfo)
80
+ return buildStaticFrameworks (
81
+ withName: framework,
82
+ logsDir: logsDir,
83
+ outputDir: outputDir,
84
+ setCarthage: setCarthage,
85
+ podInfo: podInfo
86
+ )
85
87
}
86
88
}
87
89
@@ -149,7 +151,7 @@ struct FrameworkBuilder {
149
151
/// - Returns: A dictionary of URLs to the built thin libraries keyed by platform.
150
152
private func buildFrameworksForAllPlatforms( withName framework: String ,
151
153
logsDir: URL ,
152
- setCarthage: Bool = false ) -> [ TargetPlatform : URL ] {
154
+ setCarthage: Bool ) -> [ TargetPlatform : URL ] {
153
155
// Build every architecture and save the locations in an array to be assembled.
154
156
var slicedFrameworks = [ TargetPlatform: URL] ( )
155
157
for targetPlatform in targetPlatforms {
@@ -327,13 +329,15 @@ struct FrameworkBuilder {
327
329
/// - Parameter framework: The name of the framework to be built.
328
330
/// - Parameter logsDir: The path to the directory to place build logs.
329
331
/// - Parameter moduleMapContents: Module map contents for all frameworks in this pod.
330
- /// - Returns: A path to the newly compiled framework, the Carthage version, and the Resource URL.
332
+ /// - Returns: A path to the newly compiled framework, and the Resource URL.
331
333
private func buildStaticFrameworks( withName framework: String ,
332
334
logsDir: URL ,
333
335
outputDir: URL ,
334
- podInfo: CocoaPodUtils . PodInfo ) -> ( [ URL ] , URL ? , URL ) {
336
+ setCarthage: Bool ,
337
+ podInfo: CocoaPodUtils . PodInfo ) -> ( [ URL ] , URL ) {
335
338
// Build every architecture and save the locations in an array to be assembled.
336
- let slicedFrameworks = buildFrameworksForAllPlatforms ( withName: framework, logsDir: logsDir)
339
+ let slicedFrameworks = buildFrameworksForAllPlatforms ( withName: framework, logsDir: logsDir,
340
+ setCarthage: setCarthage)
337
341
338
342
// Create the framework directory in the filesystem for the thin archives to go.
339
343
let fileManager = FileManager . default
@@ -354,6 +358,17 @@ struct FrameworkBuilder {
354
358
// Get the framework Headers directory. On macOS, it's a symbolic link.
355
359
let headersDir = archivePath. appendingPathComponent ( " Headers " ) . resolvingSymlinksInPath ( )
356
360
361
+ // The macOS Headers directory can have a Headers file in it symbolically linked to nowhere.
362
+ // Delete it here to avoid putting it in the zip or crashing the Carthage hash generation.
363
+ // For example,in the 8.0.0 zip distribution see
364
+ // Firebase/FirebaseAnalytics/PromisesObjC.xcframework/macos-arm64_x86_64/PromisesObjc
365
+ // .framework/Headers/Headers
366
+ do {
367
+ try fileManager. removeItem ( at: headersDir. appendingPathComponent ( " Headers " ) )
368
+ } catch {
369
+ // Ignore
370
+ }
371
+
357
372
// Find CocoaPods generated umbrella header.
358
373
var umbrellaHeader = " "
359
374
if framework == " gRPC-Core " || framework == " TensorFlowLiteObjC " {
@@ -427,27 +442,11 @@ struct FrameworkBuilder {
427
442
}
428
443
let moduleMapContents = moduleMapContentsTemplate. get ( umbrellaHeader: umbrellaHeader)
429
444
let frameworks = groupFrameworks ( withName: framework,
445
+ isCarthage: setCarthage,
430
446
fromFolder: frameworkDir,
431
447
slicedFrameworks: slicedFrameworks,
432
448
moduleMapContents: moduleMapContents)
433
449
434
- var carthageFramework : URL ?
435
- if buildCarthage {
436
- var carthageThinArchives : [ TargetPlatform : URL ]
437
- if framework == " FirebaseCoreDiagnostics " {
438
- // FirebaseCoreDiagnostics needs to be built with a different ifdef for the Carthage distro.
439
- carthageThinArchives = buildFrameworksForAllPlatforms ( withName: framework,
440
- logsDir: logsDir,
441
- setCarthage: true )
442
- } else {
443
- carthageThinArchives = slicedFrameworks
444
- }
445
- carthageFramework = packageCarthageFramework ( withName: framework,
446
- fromFolder: frameworkDir,
447
- slicedFrameworks: carthageThinArchives,
448
- resourceContents: resourceContents,
449
- moduleMapContents: moduleMapContents)
450
- }
451
450
// Remove the temporary thin archives.
452
451
for slicedFramework in slicedFrameworks. values {
453
452
do {
@@ -463,7 +462,7 @@ struct FrameworkBuilder {
463
462
""" )
464
463
}
465
464
}
466
- return ( frameworks, carthageFramework , resourceContents)
465
+ return ( frameworks, resourceContents)
467
466
}
468
467
469
468
/// Parses CocoaPods config files or uses the passed in `moduleMapContents` to write the
@@ -478,7 +477,7 @@ struct FrameworkBuilder {
478
477
// Instead it use build options to specify them. For the zip build, we need the module maps to
479
478
// include the dependent frameworks and libraries. Therefore we reconstruct them by parsing
480
479
// the CocoaPods config files and add them here.
481
- // Currently we only to the construction for Objective C since Swift Module directories require
480
+ // Currently we only do the construction for Objective C since Swift Module directories require
482
481
// several other files. See https://github.com/firebase/firebase-ios-sdk/pull/5040.
483
482
// Therefore, for Swift we do a simple copy of the Modules files from an Xcode build.
484
483
// This is sufficient for the testing done so far, but more testing is required to determine
@@ -594,19 +593,22 @@ struct FrameworkBuilder {
594
593
595
594
/// Groups slices for each platform into a minimal set of frameworks.
596
595
/// - Parameter withName: The framework name.
596
+ /// - Parameter isCarthage: Name the temp directory differently for Carthage.
597
597
/// - Parameter fromFolder: The almost complete framework folder. Includes Headers, Info.plist,
598
598
/// and Resources.
599
599
/// - Parameter slicedFrameworks: All the frameworks sliced by platform.
600
600
/// - Parameter moduleMapContents: Module map contents for all frameworks in this pod.
601
601
private func groupFrameworks( withName framework: String ,
602
+ isCarthage: Bool ,
602
603
fromFolder: URL ,
603
604
slicedFrameworks: [ TargetPlatform : URL ] ,
604
605
moduleMapContents: String ) -> ( [ URL ] ) {
605
606
let fileManager = FileManager . default
606
607
607
608
// Create a `.framework` for each of the thinArchives using the `fromFolder` as the base.
608
- let platformFrameworksDir =
609
- fileManager. temporaryDirectory ( withName: " platform_frameworks " )
609
+ let platformFrameworksDir = fileManager. temporaryDirectory (
610
+ withName: isCarthage ? " carthage_frameworks " : " platform_frameworks "
611
+ )
610
612
if !fileManager. directoryExists ( at: platformFrameworksDir) {
611
613
do {
612
614
try fileManager. createDirectory ( at: platformFrameworksDir,
@@ -704,172 +706,4 @@ struct FrameworkBuilder {
704
706
}
705
707
return xcframework
706
708
}
707
-
708
- /// Packages a Carthage framework. Carthage does not yet support xcframeworks, so we exclude the
709
- /// Catalyst slice.
710
- /// - Parameter withName: The framework name.
711
- /// - Parameter fromFolder: The almost complete framework folder. Includes Headers, Info.plist,
712
- /// and Resources.
713
- /// - Parameter slicedFrameworks: All the frameworks sliced by platform.
714
- /// - Parameter resourceContents: Location of the resources for this Carthage framework.
715
- /// - Parameter moduleMapContents: Module map contents for all frameworks in this pod.
716
- private func packageCarthageFramework( withName framework: String ,
717
- fromFolder: URL ,
718
- slicedFrameworks: [ TargetPlatform : URL ] ,
719
- resourceContents: URL ,
720
- moduleMapContents: String ) -> URL ? {
721
- let fileManager = FileManager . default
722
-
723
- // Create a `.framework` for each of the thinArchives using the `fromFolder` as the base.
724
- let platformFrameworksDir = fileManager. temporaryDirectory ( withName: " carthage_frameworks " )
725
- if !fileManager. directoryExists ( at: platformFrameworksDir) {
726
- do {
727
- try fileManager. createDirectory ( at: platformFrameworksDir,
728
- withIntermediateDirectories: true )
729
- } catch {
730
- fatalError ( " Could not create a temp directory to store all thin frameworks: \( error) " )
731
- }
732
- }
733
-
734
- // The frameworks include the arm64 simulator slice which will conflict with the arm64 device
735
- // slice. Until Carthage can use XCFrameworks natively, extract the supported thin slices.
736
- let thinSlices : [ Architecture : URL ] =
737
- slicedBinariesForCarthage ( fromFrameworks: slicedFrameworks,
738
- workingDir: platformFrameworksDir)
739
-
740
- // Copy the framework in the appropriate directory structure.
741
- let frameworkDir = platformFrameworksDir. appendingPathComponent ( fromFolder. lastPathComponent)
742
- do {
743
- try fileManager. copyItem ( at: fromFolder, to: frameworkDir)
744
- } catch {
745
- fatalError ( " Could not create .framework needed to build \( framework) for Carthage: \( error) " )
746
- }
747
-
748
- // Build the fat archive using the `lipo` command to make one fat binary that Carthage can use
749
- // in the framework. We need the full archive path.
750
- let fatArchive = frameworkDir. appendingPathComponent ( framework)
751
- let result = FrameworkBuilder . syncExec (
752
- command: " /usr/bin/lipo " ,
753
- args: [ " -create " , " -output " , fatArchive. path] + thinSlices. map { $0. value. path }
754
- )
755
- switch result {
756
- case let . error( code, output) :
757
- fatalError ( """
758
- lipo command exited with \( code) when trying to build \( framework) . Output:
759
- \( output)
760
- """ )
761
- case . success:
762
- print ( " lipo command for \( framework) succeeded. " )
763
- }
764
-
765
- // Package the modulemaps. The build architecture does not support constructing Swift module
766
- // maps for the Carthage distribution, so skip this pod if there is any Swift.
767
- let foundSwift = packageModuleMaps ( inFrameworks: slicedFrameworks. map { $0. value } ,
768
- moduleMapContents: moduleMapContents,
769
- destination: frameworkDir,
770
- buildingCarthage: true )
771
- if foundSwift {
772
- do {
773
- try fileManager. removeItem ( at: frameworkDir)
774
- } catch {
775
- fatalError ( " Could not remove \( frameworkDir) \( error) " )
776
- }
777
- return nil
778
- }
779
-
780
- // Carthage Resources are packaged in the framework.
781
- // Copy them instead of moving them, since they'll still need to be copied into the xcframework.
782
- let resourceDir = frameworkDir. appendingPathComponent ( " Resources " )
783
- do {
784
- try ResourcesManager . moveAllBundles ( inDirectory: resourceContents,
785
- to: resourceDir,
786
- keepOriginal: true )
787
- } catch {
788
- fatalError ( " Could not move bundles into Resources directory while building \( framework) : " +
789
- " \( error) " )
790
- }
791
- return frameworkDir
792
- }
793
-
794
- /// Takes existing fat frameworks (sliced per platform) and returns thin slices, excluding arm64
795
- /// simulator slices since Carthage can only create a regular framework.
796
- private func slicedBinariesForCarthage( fromFrameworks frameworks: [ TargetPlatform : URL ] ,
797
- workingDir: URL ) -> [ Architecture : URL ] {
798
- // Exclude Catalyst.
799
- let platformsToInclude : [ TargetPlatform ] = frameworks. keys. filter { $0 != . catalyst }
800
- let builtSlices : [ TargetPlatform : URL ] = frameworks
801
- . filter { platformsToInclude. contains ( $0. key) }
802
- . mapValues { frameworkURL in
803
- // Get the path to the sliced binary instead of the framework.
804
- let frameworkName = frameworkURL. lastPathComponent
805
- let binaryName = frameworkName. replacingOccurrences ( of: " .framework " , with: " " )
806
- return frameworkURL. appendingPathComponent ( binaryName)
807
- }
808
-
809
- let fileManager = FileManager . default
810
- let individualSlices = workingDir. appendingPathComponent ( " slices " )
811
- if !fileManager. directoryExists ( at: individualSlices) {
812
- do {
813
- try fileManager. createDirectory ( at: individualSlices,
814
- withIntermediateDirectories: true )
815
- } catch {
816
- fatalError ( " Could not create a temp directory to store sliced binaries: \( error) " )
817
- }
818
- }
819
-
820
- // Loop through and extract the necessary architectures.
821
- var slices : [ Architecture : URL ] = [ : ]
822
- for (platform, binary) in builtSlices {
823
- var archs = platform. archs
824
- var forceLipoOnOneArch = false
825
- if platform == . iOSSimulator {
826
- // Exclude the arm64 slice for simulator since Carthage can't package as an XCFramework.
827
- archs. removeAll ( where: { $0 == . arm64 } )
828
- if binary. lastPathComponent == " FirebaseAppCheck " {
829
- // Exclude i386 slice for iOS 11+ frameworks.
830
- archs. removeAll ( where: { $0 == . i386 } )
831
- forceLipoOnOneArch = true // Still need to run lipo because .x86_64 and arm64 were built.
832
- }
833
- }
834
- if platform == . iOSDevice {
835
- if binary. lastPathComponent == " FirebaseAppCheck " {
836
- // Exclude armv7 slice for iOS 11+ frameworks.
837
- archs. removeAll ( where: { $0 == . armv7 } )
838
- }
839
- }
840
-
841
- // lipo doesn't work if only one architecture.
842
- if archs. count == 1 , !forceLipoOnOneArch {
843
- slices [ archs. first!] = binary
844
- continue
845
- }
846
-
847
- // Loop through the architectures and strip out each by using `lipo`.
848
- for arch in archs {
849
- // Create the path where the thin slice will reside, ensure it's non-existent.
850
- let destination = individualSlices. appendingPathComponent ( " \( arch. rawValue) .a " )
851
- fileManager. removeIfExists ( at: destination)
852
-
853
- // Use lipo to extract the architecture we're looking for.
854
- let result = FrameworkBuilder . syncExec ( command: " /usr/bin/lipo " ,
855
- args: [ binary. path,
856
- " -thin " , arch. rawValue,
857
- " -output " , destination. path] )
858
- switch result {
859
- case let . error( code, output) :
860
- fatalError ( """
861
- lipo command exited with \( code) when trying to extract the \( arch. rawValue) slice \
862
- from \( binary. path) . Output:
863
- \( output)
864
- """ )
865
- case . success:
866
- print ( " lipo successfully extracted the \( arch. rawValue) slice from \( binary. path) " )
867
- }
868
-
869
- slices [ arch] = destination
870
- }
871
- }
872
-
873
- return slices
874
- }
875
709
}
0 commit comments