This document provides essential context and guidelines for Jules, an AI software engineering
agent, to effectively understand, navigate, and make changes within the firebase-ios-sdk
repository. It highlights key aspects of the development environment, coding practices, and
architectural patterns.
To contribute to or develop within the firebase-ios-sdk repository, an understanding of the
following setup is beneficial.
clang-format: Used for C, C++, and Objective-C code formatting. Version 20 is
specifically mentioned.mint: Used to install and run Swift command-line tools, including swiftformat for
Swift code styling.clang-format (version 20) and mint (for
swiftformat) for code styling. Ensure any generated or modified code adheres to these
styling requirements.You can develop Firebase libraries using either Swift Package Manager (SPM) or CocoaPods.
Swift Package Manager (SPM) is a primary development workflow. The project is typically opened
via the Package.swift file at the repository root.
FirebaseAuth, FirebaseFirestore)
are used to build and develop individual modules.For test-related tasks using SPM, be aware of the ./scripts/setup_spm_tests.sh script, which
configures Xcode to show schemes for testing individual packages. This script may need to be
invoked if tests need to be run or modified in an SPM context.
./scripts/setup_spm_tests.sh
CocoaPods (v1.12.0+) is another key development workflow.
cocoapods-generate plugin is used to create a development workspace from a .podspec
file.Development workspaces for individual libraries (e.g., FirebaseStorage) are generated using
a command like:
pod gen FirebaseStorage.podspec --local-sources=./ --auto-open --platforms=ios
FirebaseStorage.podspec with the podspec of the library you intend to develop.
Podspecs are located in the root directory.--local-sources=./ flag tells CocoaPods to use the local checkout of the SDK.--platforms can be set to ios, macos, or tvos. Note that for Xcode 10.2+,
multi-platform CocoaPods workspaces might have issues, so generating for a single
platform is advised by README.md.pod repo update first.Understanding this command structure is important if tasks involve setting up or modifying a CocoaPods-based development environment for a specific module.
Mac Catalyst Development:
pod gen as above for ios.CODE_SIGNING_REQUIRED with value NO to each relevant target's build settings.Code consistency is maintained by clang-format (for C-based languages) and swiftformat (for
Swift). Any code generated or modified must adhere to these standards.
The ./scripts/style.sh script is used to apply formatting. If a task involves code
changes, this script (or the underlying tools) should be used to ensure compliance:
./scripts/style.sh {path_to_changed_files_or_branch_name}
For example:
./scripts/style.sh FirebaseStorage/Sources/
# OR
./scripts/style.sh my-feature-branch
Running ./scripts/style.sh with no arguments will format all eligible files in the
repository.
Failures in CI style checks often indicate that code modifications were not formatted correctly with these tools.
Firestore has a self-contained Xcode project. For details, refer to Firestore/README.md.
Thorough testing is essential for maintaining the quality and stability of the Firebase SDK.
The primary method for running tests is through Xcode, after setting up your development environment using either Swift Package Manager or CocoaPods.
Enable Test Schemes: If you haven't already, run the script from the repository root:
./scripts/setup_spm_tests.sh
Run Tests:
FirebaseFirestoreTests).⌘U or click the "play" arrow in the project navigation bar to run the tests.CONTRIBUTING.md mentions that not all test schemes might be configured to run
with SPM.The following are environment variables to modify sources of code that can help with testing specific frameworks or dealing with version mismatches.
FIREBASECI_USE_LATEST_GOOGLEAPPMEASUREMENT: When passed, sets the dependency on the
https://github.com/google/GoogleAppMeasurement.git package to use the main branch. This is
done to keep the Firebase package's main branch building when it depends on unreleased changes
in the GoogleAppMeasurement package's main branch. Use it when you run into version issues.FIREBASECI_USE_LOCAL_FIRESTORE_ZIP: When passed, looks for a local
FirebaseFirestoreInternal.xcframework framework at the root of the repo to resolve the
Firestore target. Used for testing incombination with scripts/check_firestore_symbols.sh.FIREBASE_SOURCE_FIRESTORE: When passed, builds Firestore's large C++ dependencies (abseil,
gRPC, BoringSSL) from source rather than, by default, using existing binaries.To enable an env var within Xcode, quit the current Xcode instance, and open it from the command
line, passing each desired env var with the --env argument.
open --env FIREBASECI_USE_LATEST_GOOGLEAPPMEASUREMENT --env FIREBASE_SOURCE_FIRESTORE \
Package.swift
To unset the env vars, quit the running Xcode instance.
pod gen ... as described in the
"Setup Commands" section..xcworkspace.FirebaseStorage-Unit-unit).⌘U or click the "play" arrow to run tests.Product → Scheme ➞ Edit Scheme... (or use ⌥⌘U).scripts/code_coverage_report/README.md.GoogleService-Info.plist in TestsConfiguration files like GoogleService-Info.plist are necessary for Firebase SDKs to connect to
a backend project. How these are handled in tests varies:
GoogleService-Info.plist.FirebaseApp.configure()), tests often use
mock or fake GoogleService-Info.plist files with dummy values. These are typically
included directly in the test target's resources. Be aware of this pattern if tests
seem to require Firebase app initialization.GoogleService-Info.plist files.README.md. However, direct interaction with
the Firebase console to download plists is outside typical AI agent operations unless
explicitly guided../scripts/run_database_emulator.sh start before executing tests.GoogleService-Info.plist (copied to
FirebaseDatabase/Tests/Resources/GoogleService-Info.plist) and ensure security rules
are public during the test run.FirebaseStorage/Tests/Integration/StorageIntegration.swift.Designing and maintaining a consistent and developer-friendly API is critical for the Firebase SDK. Adherence to established guidelines is important for a good user experience and should be followed when tasks involve API modifications.
The primary reference for API design is docs/firebase-api-guidelines.md. Key principles for new
API designs include:
Async/Await: New asynchronous APIs should use Swift's async/await. Callback-based APIs
require justification (though callbacks are still appropriate for event handlers).
// Preferred
public func fetchData() async throws -> Data { /* ... */ }
// Pre-Swift Concurrency (No longer preferred for new async APIs)
public func fetchData(completion: (Data?, Error?) -> Void) { /* ... */ }
Sendable Types: New APIs should be Sendable where applicable, to allow safe use in
concurrent contexts (e.g., within a Task).
Access Control:
public access level should be used for new Swift APIs rather than open.final to prevent subclassing, unless subclassing
is an intended design feature.API Availability:
@available attribute is used to specify platform and version compatibility (e.g.,
@available(iOS 13, tvOS 13, macOS 10.15, macCatalyst 13, watchOS 7, *)).@available.Constants:
The "k" prefix for Swift constants should be avoided.
public enum NetworkConstants {
public static let httpPostMethod = "POST"
}
Minimize Optionals: While Swift's optionals provide type safety for nullability, their overuse should be avoided to prevent complicating call sites.
Structs vs. Enums for Extensibility:
Avoid Any, AnyObject, NS-Types: Any, AnyObject, or Objective-C NS-prefixed types
(like NSString, NSDictionary) should not be used in public Swift APIs. Swift native
types (String, Dictionary) are preferred, and heterogeneous collections should be
modeled with enums or structs for type safety.
Documentation: New APIs must be documented using Swift-flavored Markdown. Xcode's ⌥ ⌘ /
shortcut can generate documentation block structure.
Naming Conventions:
fetchMetadata() over fetch()
or getMetadata()).Error Handling:
throws.Error protocol should be defined and thrown.Objective-C (If Necessary):
typedefs in public Objective-C headers should be avoided as they obscure the
underlying type in the generated Swift interface. Full types should be used.The document HeadersImports.md provides detailed guidelines. Key points include:
FirebaseFoo/Sources/Public/FirebaseFoo/.FirebaseFoo/Sources/Public/FirebaseFoo/FirebaseFoo.h).FirebaseFoo/Sources/Private/.firebase-ios-sdk repo but NOT part of the
public API.source_files, not private_header_files.Interop/FirebaseComponentSystem.md).#import "FirebaseFoo/Sources/Internal/MyInternalHeader.h").
#import "AnotherPublicHeaderInFoo.h") to avoid
module collisions.#import "FirebaseCore/Extension/FirebaseCoreInternal.h").External Dependencies:
#if SWIFT_PACKAGE
@import GTMSessionFetcherCore;
#else
#import <GTMSessionFetcher/GTMSessionFetcher.h>
#endif
This structure ensures that APIs are well-defined, discoverable, and maintainable across different build systems and for various Firebase products.
Adhering to best practices ensures code quality, maintainability, and a positive developer experience for both contributors and users of the Firebase SDK.
CONTRIBUTING.md file contains detailed information on the
development workflow, pull requests, coding styles, and environment setup, which should be
adhered to..podspec files or Package.swift.FIRApp):
FirebaseApp (Swift) / FIRApp (Objective-C) is the central class for initializing and
configuring Firebase.GoogleService-Info.plist.FIRComponent):
FIRComponent, FIRComponentContainer) is used for
registering and discovering Firebase services at runtime.docs/AddNewPod.md and FIRApp.m).GoogleService-Info.plist (in relation to SDK code):
GoogleService-Info.plist in tests has specific considerations (see
"Handling GoogleService-Info.plist in Tests"), SDK code itself relies on FirebaseApp
to provide project configurations derived from such a file.-ObjC Linker Flag:
-ObjC "Other Linker Flags" setting is important, as it's necessary
for applications using Firebase Analytics (and often transitively, other Firebase SDKs)
to correctly link Objective-C categories.CHANGELOG.md files (root and product-specific) must be updated with
meaningful descriptions of changes for any pull request.@available and conditional compilation (#if os(iOS)) are
used. visionOS and watchOS are community-supported.HeadersImports.md must be followed strictly for
compatibility.Adherence to these practices helps maintain the quality and robustness of the Firebase Apple SDKs.
Recognizing the following common design and implementation patterns, prevalent throughout the Firebase Apple SDKs, facilitates understanding the existing codebase and developing new features consistently.
async/await for cleaner, more readable
control flow.Sendable to ensure thread safety, especially with Swift 6's stricter concurrency
checking.Case-less Enums for Constants:
Swift code uses case-less enums to group related constants, preventing instantiation and providing a clear namespace.
public enum StorageConstants {
public static let maxUploadRetryTime: TimeInterval = 600.0
public static let defaultChunkSize: Int64 = 256 * 1024
}
Structs for Extensible Enum-like Values:
structs with static factory methods are often used. This
avoids the issue where adding a new case to a public enum breaks client switch
statements. (See docs/firebase-api-guidelines.md for context).Protocol Buffers (Protobuf / Nanopb):
.proto files defining data structures and scripts
(e.g., generate_protos.sh) for compilation into Swift or Objective-C (often Nanopb
for C/Objective-C). Due to their complexity and impact on build processes, introducing
Protobufs to new areas of the SDK should be avoided unless that area already heavily
relies on them or it's a specific requirement for interacting with an existing
Protobuf-based system.API Visibility Layers (Public/Private/Internal):
Sources/Public/ directories.
Changes here are subject to semantic versioning.Sources/Private/ or Interop/
directories.Umbrella Headers:
FirebaseFoo.h) that includes all other public headers for that library,
simplifying imports for Objective-C users.FirebaseCoreInternal.h) to expose necessary private APIs to other
Firebase libraries.Module-Specific Prefixes (Objective-C):
FIR for
Firebase Core, FST for Firestore, FIRCLS for Crashlytics). This is less of a concern
in Swift due to namespacing with module names.Error Handling Conventions:
Error protocol, with specific error enums/structs per module.NSError** parameters and standard error domains (often
module-specific).Delegate Pattern (Objective-C & Swift):
Completion Handlers (Callbacks):
async/await is preferred for new Swift asynchronous operations, completion
handlers remain prevalent in many existing Objective-C and Swift APIs. These typically
take (ResultType?, Error?) or similar parameters.Singletons and Shared Instances:
FirebaseApp.app(), Firestore.firestore(), Auth.auth()).Resource Bundles:
.bundle files.Use of dispatch_once / Lazy Initialization for Singletons (Objective-C):
static let properties for a similar outcome.Understanding these patterns is key to navigating the codebase and contributing effectively.
The Firebase Apple SDK integrates several external open-source libraries to provide its functionality. These dependencies are managed as part of the overall SDK build and release process, primarily through CocoaPods and Swift Package Manager configurations.
Examples of such dependencies include (but are not limited to):
When working on tasks for this repository, do not introduce new external dependencies unless explicitly instructed to do so by the user. Adding and managing dependencies in a large SDK like this involves careful consideration of binary size, licensing, potential conflicts, and long-term maintenance. The existing dependencies are curated and managed by the Firebase team. If a task seems to require functionality that might suggest a new library, discuss alternatives or confirm the need for a new dependency with the user first.
This document (agents.md) is intended as a living guide to assist AI agents (like Jules) in
understanding and contributing to the firebase-ios-sdk repository. As the SDK evolves, new
patterns may emerge, best practices might be updated, or setup procedures could change.
Guideline for Future Tasks: If, during the course of completing new tasks, you identify:
Please consider updating this agents.md file to reflect those new findings. Keeping this
document current will improve the efficiency and accuracy of future AI-assisted development.