Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Release Tooling] Consistent approach to resources when building on Xcode 15 #12821

Merged
merged 12 commits into from
Apr 23, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,16 @@ + (NSBundle *)getViewResourceBundle {
NSBundle *containingBundle;
NSURL *bundleURL;
// The containing bundle is different whether FIAM is statically or dynamically linked.
for (containingBundle in @[ [NSBundle mainBundle], [NSBundle bundleForClass:myClass] ]) {
for (containingBundle in @[
// Statically linked.
[NSBundle mainBundle],
// Dynamically linked.
[NSBundle bundleForClass:myClass],
// Embedded static framework (zip distribution).
[NSBundle bundleWithURL:[NSBundle.mainBundle.bundleURL
URLByAppendingPathComponent:
@"Frameworks/FirebaseInAppMessaging.framework"]]
]) {
bundleURL = [containingBundle URLForResource:bundledResource withExtension:@"bundle"];
if (bundleURL != nil) break;
}
Expand Down
61 changes: 27 additions & 34 deletions ReleaseTooling/Sources/ZipBuilder/FrameworkBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,33 @@ struct FrameworkBuilder {
platform == .catalyst || platform == .macOS ? "Resources" : ""
)
.resolvingSymlinksInPath()
processPrivacyManifests(fileManager, frameworkPath, resourceDir)

// Move resource bundles into the platform framework.
do {
try fileManager.contentsOfDirectory(
at: frameworkPath.deletingLastPathComponent(),
includingPropertiesForKeys: nil
)
.filter { $0.pathExtension == "bundle" }
// Bundles are moved rather than copied to prevent them from being
// packaged in a `Resources` directory at the root of the xcframework.
.forEach {
// Delete `gRPCCertificates-Cpp.bundle` since it is not needed (#9184).
guard $0.lastPathComponent != "gRPCCertificates-Cpp.bundle" else {
try fileManager.removeItem(at: $0)
return
}

try fileManager.moveItem(
at: $0,
to: resourceDir.appendingPathComponent($0.lastPathComponent)
)
}
} catch {
fatalError(
"Could not move resources for framework \(frameworkPath), platform \(platform). Error: \(error)"
)
}

// Use the appropriate moduleMaps
packageModuleMaps(inFrameworks: [frameworkPath],
Expand All @@ -663,39 +689,6 @@ struct FrameworkBuilder {
}
}

/// Process privacy manifests.
///
/// Move any privacy manifest-containing resource bundles into the platform framework.
func processPrivacyManifests(_ fileManager: FileManager,
_ frameworkPath: URL,
_ platformFrameworkDir: URL) {
try? fileManager.contentsOfDirectory(
at: frameworkPath.deletingLastPathComponent(),
includingPropertiesForKeys: nil
)
.filter { $0.pathExtension == "bundle" }
// TODO(ncooke3): Once the zip is built with Xcode 15, the following
// `filter` can be removed. The following block exists to preserve
// how resources (e.g. like FIAM's) are packaged for use in Xcode 14.
.filter { bundleURL in
let dirEnum = fileManager.enumerator(atPath: bundleURL.path)
var containsPrivacyManifest = false
while let relativeFilePath = dirEnum?.nextObject() as? String {
if relativeFilePath.hasSuffix("PrivacyInfo.xcprivacy") {
containsPrivacyManifest = true
break
}
}
return containsPrivacyManifest
}
// Bundles are moved rather than copied to prevent them from being
// packaged in a `Resources` directory at the root of the xcframework.
.forEach { try! fileManager.moveItem(
at: $0,
to: platformFrameworkDir.appendingPathComponent($0.lastPathComponent)
) }
}

/// Package the built frameworks into an XCFramework.
/// - Parameter withName: The framework name.
/// - Parameter frameworks: The grouped frameworks.
Expand Down
17 changes: 6 additions & 11 deletions ReleaseTooling/Template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,7 @@ To integrate a Firebase SDK with your app:
**Embed & Sign**. This step will enable privacy manifests to be picked up by
Xcode's tooling.

8. If the SDK has resources, go into the Resources folders, which will be in
the SDK folder. Drag all of those resources into the Project Navigator, just
like the frameworks, again making sure that the target you want to add these
resources to has a checkmark next to it, and that you've selected "Copy items
if needed".
9. Add the `-ObjC` flag to **Other Linker Settings**:
8. Add the `-ObjC` flag to **Other Linker Settings**:

a. In your project settings, open the **Settings** panel for your target.

Expand All @@ -63,7 +58,7 @@ To integrate a Firebase SDK with your app:

c. Double-click the setting, click the '+' button, and add `-ObjC`

10. Add the `-lc++` flag to **Other Linker Settings**:
9. Add the `-lc++` flag to **Other Linker Settings**:

a. In your project settings, open the **Settings** panel for your target.

Expand All @@ -72,21 +67,21 @@ To integrate a Firebase SDK with your app:

c. Double-click the setting, click the '+' button, and add `-lc++`

11. Drag the `Firebase.h` header in this directory into your project. This will
10. Drag the `Firebase.h` header in this directory into your project. This will
allow you to `#import "Firebase.h"` and start using any Firebase SDK that you
have.
12. Drag `module.modulemap` into your project and update the
11. Drag `module.modulemap` into your project and update the
"User Header Search Paths" in your project's Build Settings to include the
directory that contains the added module map.
13. If your app does not include any Swift implementation, you may need to add
12. If your app does not include any Swift implementation, you may need to add
a dummy Swift file to the app to prevent Swift system library missing
symbol linker errors. See
https://forums.swift.org/t/using-binary-swift-sdks-from-non-swift-apps/55989.

> ⚠ If prompted with the option to create a corresponding bridging header
> for the new Swift file, select **Don't create**.

14. You're done! Build your target and start using Firebase.
13. You're done! Build your target and start using Firebase.

If you want to add another SDK, repeat the steps above with the xcframeworks for
the new SDK. You only need to add each framework once, so if you've already
Expand Down
Loading