Skip to content

Commit bbbcb49

Browse files
committed
Zip Resource handling for xcframeworks (#5093)
1 parent 716b045 commit bbbcb49

File tree

4 files changed

+60
-42
lines changed

4 files changed

+60
-42
lines changed

ZipBuilder/Sources/ZipBuilder/CarthageUtils.swift

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -109,24 +109,6 @@ extension CarthageUtils {
109109
}
110110
}
111111

112-
// Make updates to all frameworks to make Carthage happy. We don't worry about xcframeworks
113-
// here.
114-
let allFileObjects = FileManager.default.enumerator(atPath: fullPath.path)?.allObjects
115-
guard let allFiles = allFileObjects as? [String] else {
116-
fatalError("Failed to get file list for Carthage construction at \(fullPath.path)")
117-
}
118-
let frameworks = allFiles.filter { $0.hasSuffix(".framework") }
119-
for framework in frameworks {
120-
let plistPath = fullPath.appendingPathComponents([framework, "Info.plist"])
121-
// Drop the extension of the framework name.
122-
let plist = generatePlistContents(forName: framework.components(separatedBy: ".").first!)
123-
do {
124-
try plist.write(to: plistPath)
125-
} catch {
126-
fatalError("Could not copy plist for \(framework) for Carthage release. \(error)")
127-
}
128-
}
129-
130112
// Analytics includes all the Core frameworks and Firebase module, do extra work to package
131113
// it.
132114
if product == "FirebaseAnalytics" {
@@ -266,7 +248,7 @@ extension CarthageUtils {
266248
}
267249
}
268250

269-
private static func generatePlistContents(forName name: String) -> Data {
251+
static func generatePlistContents(forName name: String) -> Data {
270252
let plist: [String: String] = ["CFBundleIdentifier": "com.firebase.Firebase",
271253
"CFBundleInfoDictionaryVersion": "6.0",
272254
"CFBundlePackageType": "FMWK",

ZipBuilder/Sources/ZipBuilder/FrameworkBuilder.swift

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -509,18 +509,13 @@ struct FrameworkBuilder {
509509

510510
// Move all the Resources into .bundle directories in the destination Resources dir. The
511511
// Resources live are contained within the folder structure:
512-
// `projectDir/arch/Release-platform/FrameworkName`
512+
// `projectDir/arch/Release-platform/FrameworkName`.
513+
// The Resources are stored at the top-level of the .framework or .xcframework directory.
514+
// For Firebase distributions, they are propagated one level higher in the final distribution.
513515

514-
let contentsDir = projectDir.appendingPathComponents([anyArch.rawValue,
515-
"Release-\(anyArch.platform.rawValue)",
516-
framework])
517-
let resourceDir = frameworkDir.appendingPathComponent("Resources")
518-
do {
519-
try ResourcesManager.moveAllBundles(inDirectory: contentsDir, to: resourceDir)
520-
} catch {
521-
fatalError("Could not move bundles into Resources directory while building \(framework): " +
522-
"\(error)")
523-
}
516+
let resourceContents = projectDir.appendingPathComponents([anyArch.rawValue,
517+
"Release-\(anyArch.platform.rawValue)",
518+
framework])
524519

525520
guard let moduleMapContentsTemplate = podInfo.moduleMapContents else {
526521
fatalError("Module map contents missing for framework \(framework)")
@@ -529,6 +524,7 @@ struct FrameworkBuilder {
529524
let xcframework = packageXCFramework(withName: framework,
530525
fromFolder: frameworkDir,
531526
thinArchives: thinArchives,
527+
resourceContents: resourceContents,
532528
moduleMapContents: moduleMapContents)
533529

534530
var carthageFramework: URL?
@@ -545,6 +541,7 @@ struct FrameworkBuilder {
545541
carthageFramework = packageCarthageFramework(withName: framework,
546542
fromFolder: frameworkDir,
547543
thinArchives: carthageThinArchives,
544+
resourceContents: resourceContents,
548545
moduleMapContents: moduleMapContents)
549546
}
550547
// Remove the temporary thin archives.
@@ -697,10 +694,12 @@ struct FrameworkBuilder {
697694
/// - Parameter withName: The framework name.
698695
/// - Parameter fromFolder: The almost complete framework folder. Includes everything but the binary.
699696
/// - Parameter thinArchives: All the thin archives.
697+
/// - Parameter resourceContents: Location of the resources for this xcframework.
700698
/// - Parameter moduleMapContents: Module map contents for all frameworks in this pod.
701699
private func packageXCFramework(withName framework: String,
702700
fromFolder: URL,
703701
thinArchives: [Architecture: URL],
702+
resourceContents: URL,
704703
moduleMapContents: String) -> URL {
705704
let fileManager = FileManager.default
706705

@@ -784,6 +783,17 @@ struct FrameworkBuilder {
784783
case .success:
785784
print("XCFramework for \(framework) built successfully at \(xcframework).")
786785
}
786+
// xcframework resources are packaged at top of xcframework. We do a copy instead of a move
787+
// because the resources may also be copied for the Carthage distribution.
788+
let resourceDir = xcframework.appendingPathComponent("Resources")
789+
do {
790+
try ResourcesManager.moveAllBundles(inDirectory: resourceContents,
791+
to: resourceDir,
792+
keepOriginal: true)
793+
} catch {
794+
fatalError("Could not move bundles into Resources directory while building \(framework): " +
795+
"\(error)")
796+
}
787797

788798
return xcframework
789799
}
@@ -792,10 +802,12 @@ struct FrameworkBuilder {
792802
/// - Parameter withName: The framework name.
793803
/// - Parameter fromFolder: The almost complete framework folder. Includes everything but the binary.
794804
/// - Parameter thinArchives: All the thin archives.
805+
/// - Parameter resourceContents: Location of the resources for this Carthage framework.
795806
/// - Parameter moduleMapContents: Module map contents for all frameworks in this pod.
796807
private func packageCarthageFramework(withName framework: String,
797808
fromFolder: URL,
798809
thinArchives: [Architecture: URL],
810+
resourceContents: URL,
799811
moduleMapContents: String) -> URL {
800812
let fileManager = FileManager.default
801813

@@ -814,12 +826,31 @@ struct FrameworkBuilder {
814826
let slices = thinArchives.filter { $0.key != Architecture.x86_64h }
815827

816828
// Package a normal .framework with the given slices.
817-
let destination = platformFrameworksDir.appendingPathComponent(fromFolder.lastPathComponent)
829+
let frameworkDir = platformFrameworksDir.appendingPathComponent(fromFolder.lastPathComponent)
818830
packageFramework(withName: framework,
819831
fromFolder: fromFolder,
820832
thinArchives: slices,
821-
destination: destination,
833+
destination: frameworkDir,
822834
moduleMapContents: moduleMapContents)
823-
return destination
835+
836+
// Add Info.plist frameworks to make Carthage happy.
837+
let plistPath = frameworkDir.appendingPathComponents(["Info.plist"])
838+
// Drop the extension of the framework name.
839+
let plist = CarthageUtils.generatePlistContents(forName: framework)
840+
do {
841+
try plist.write(to: plistPath)
842+
} catch {
843+
fatalError("Could not copy plist for \(frameworkDir) for Carthage release. \(error)")
844+
}
845+
846+
// Carthage Resources are packaged in the framework.
847+
let resourceDir = frameworkDir.appendingPathComponent("Resources")
848+
do {
849+
try ResourcesManager.moveAllBundles(inDirectory: resourceContents, to: resourceDir)
850+
} catch {
851+
fatalError("Could not move bundles into Resources directory while building \(framework): " +
852+
"\(error)")
853+
}
854+
return frameworkDir
824855
}
825856
}

ZipBuilder/Sources/ZipBuilder/ResourcesManager.swift

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,10 +159,13 @@ extension ResourcesManager {
159159
/// - dir: The directory to search for Resource bundles.
160160
/// - resourceDir: The destination Resources directory. This function will create the Resources
161161
/// directory if it doesn't exist.
162+
/// - keepOriginal: Do a copy instead of a move.
162163
/// - Returns: An array of URLs pointing to the newly located bundles.
163164
/// - Throws: Any file system errors that occur.
164165
@discardableResult
165-
static func moveAllBundles(inDirectory dir: URL, to resourceDir: URL) throws -> [URL] {
166+
static func moveAllBundles(inDirectory dir: URL,
167+
to resourceDir: URL,
168+
keepOriginal: Bool = false) throws -> [URL] {
166169
let fileManager = FileManager.default
167170
let allBundles = try fileManager.recursivelySearch(for: .bundles, in: dir)
168171

@@ -171,7 +174,7 @@ extension ResourcesManager {
171174
guard !allBundles.isEmpty else { return [] }
172175

173176
// Move the found bundles into the Resources directory.
174-
let bundlesMoved = try moveAllFiles(allBundles, toDir: resourceDir)
177+
let bundlesMoved = try moveAllFiles(allBundles, toDir: resourceDir, keepOriginal: keepOriginal)
175178

176179
// Remove any empty Resources directories left over as part of the move.
177180
removeEmptyResourcesDirectories(in: dir)
@@ -290,9 +293,11 @@ extension ResourcesManager {
290293
/// - files: URLs to files to move.
291294
/// - destinationDir: Destination directory to move all the files. Creates the directory if it
292295
/// doesn't exist.
296+
/// - keepOriginal: Do a copy instead of a move.
293297
/// - Throws: Any file system errors that occur.
294298
@discardableResult
295-
private static func moveAllFiles(_ files: [URL], toDir destinationDir: URL) throws -> [URL] {
299+
private static func moveAllFiles(_ files: [URL], toDir destinationDir: URL,
300+
keepOriginal: Bool = false) throws -> [URL] {
296301
let fileManager = FileManager.default
297302
if !fileManager.directoryExists(at: destinationDir) {
298303
try fileManager.createDirectory(at: destinationDir, withIntermediateDirectories: true)
@@ -303,7 +308,11 @@ extension ResourcesManager {
303308
// Create the destination URL by using the filename of the file but prefix of the
304309
// destinationDir.
305310
let destination = destinationDir.appendingPathComponent(file.lastPathComponent)
306-
try fileManager.moveItem(at: file, to: destination)
311+
if keepOriginal {
312+
try fileManager.copyItem(at: file, to: destination)
313+
} else {
314+
try fileManager.moveItem(at: file, to: destination)
315+
}
307316
filesMoved.append(destination)
308317
}
309318

ZipBuilder/Sources/ZipBuilder/ZipBuilder.swift

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -658,16 +658,12 @@ struct ZipBuilder {
658658
// Create the temporary directory we'll be storing the build/assembled frameworks in, and remove
659659
// the Resources directory if it already exists.
660660
let tempDir = fileManager.temporaryDirectory(withName: "all_frameworks")
661-
let tempResourceDir = tempDir.appendingPathComponent("Resources")
662661
do {
663662
try fileManager.createDirectory(at: tempDir,
664663
withIntermediateDirectories: true,
665664
attributes: nil)
666-
if fileManager.directoryExists(at: tempResourceDir) {
667-
try fileManager.removeItem(at: tempResourceDir)
668-
}
669665
} catch {
670-
fatalError("Cannot create temporary directory to store frameworks and resources from the " +
666+
fatalError("Cannot create temporary directory to store frameworks from the " +
671667
"full build: \(error)")
672668
}
673669

0 commit comments

Comments
 (0)