This document outlines the hierarchy of the Firestore-related targets in the
Package.swift manifest. The setup is designed to support three different
build options for Firestore: from a pre-compiled binary (the default), from
source (via the FIREBASE_SOURCE_FIRESTORE environment variable), or from a
local binary for CI purposes (via the FIREBASECI_USE_LOCAL_FIRESTORE_ZIP
environment variable).
When the FIREBASE_SOURCE_FIRESTORE environment variable is not set, SPM
will use pre-compiled binaries for Firestore and its heavy dependencies. This
is the default and recommended approach for most users.
The dependency tree for a binary-based build is as follows:
FirebaseFirestore (Library Product)
└── FirebaseFirestoreTarget (Wrapper Target)
└── FirebaseFirestore (Swift Target)
├── FirebaseAppCheckInterop
├── FirebaseCore
├── FirebaseCoreExtension
├── FirebaseSharedSwift
├── leveldb
├── nanopb
├── abseil (binary) (from https://github.com/google/abseil-cpp-binary.git)
├── gRPC-C++ (binary) (from https://github.com/google/grpc-binary.git, contains BoringSSL-GRPC target)
└── FirebaseFirestoreInternalWrapper (Wrapper Target)
└── FirebaseFirestoreInternal (Binary Target)
FirebaseFirestore: The Swift target containing the public API. In this configuration, it depends on the binary versions of abseil and gRPC, as well as theFirebaseFirestoreInternalWrapper.FirebaseFirestoreInternalWrapper: A thin wrapper target that exists to expose the headers from the underlying binary target.FirebaseFirestoreInternal: This is abinaryTargetthat downloads and links the pre-compiledFirebaseFirestoreInternal.xcframework. This framework contains the compiled C++ core of Firestore.
When the FIREBASE_SOURCE_FIRESTORE environment variable is set, Firestore and
its dependencies (like abseil and gRPC) are compiled from source.
To build Firestore from source, set the FIREBASE_SOURCE_FIRESTORE environment
variable before building the project.
A direct method for building within Xcode is to pass the environment variable when opening it from the command line. This approach scopes the variable to the Xcode instance. To enable an env var within Xcode, first quit any running Xcode instance, and then open the project from the command line:
open --env FIREBASE_SOURCE_FIRESTORE Package.swiftTo unset the env var, quit the running Xcode instance. If you need to pass
multiple variables, repeat the --env argument for each:
open --env FIREBASECI_USE_LATEST_GOOGLEAPPMEASUREMENT \
--env FIREBASE_SOURCE_FIRESTORE Package.swiftFor command-line builds using xcodebuild or swift build, the recommended
approach is to prefix the build command with the environment variable. This sets
the variable only for that specific command, avoiding unintended side effects.
FIREBASE_SOURCE_FIRESTORE=1 xcodebuild -scheme FirebaseFirestore \
-destination 'generic/platform=iOS'Alternatively, if you plan to run multiple commands that require the variable
to be set, you can export it. This will apply the variable to all subsequent
commands in that terminal session.
export FIREBASE_SOURCE_FIRESTORE=1
xcodebuild -scheme FirebaseFirestore -destination 'generic/platform=iOS'
# Any other commands here will also have the variable setOnce the project is built with the variable set, SPM will clone and build Firestore and its C++ dependencies (like abseil and gRPC) from source.
The dependency tree for a source-based build looks like this:
FirebaseFirestore (Library Product)
└── FirebaseFirestoreTarget (Wrapper Target)
└── FirebaseFirestore (Swift Target)
├── FirebaseCore
├── FirebaseCoreExtension
├── FirebaseSharedSwift
└── FirebaseFirestoreInternalWrapper (C++ Target)
├── FirebaseAppCheckInterop
├── FirebaseCore
├── leveldb
├── nanopb
├── abseil (source) (from https://github.com/firebase/abseil-cpp-SwiftPM.git)
└── gRPC-cpp (source) (from https://github.com/grpc/grpc-ios.git)
└── BoringSSL (source) (from https://github.com/firebase/boringSSL-SwiftPM.git)
FirebaseFirestore: The main Swift target containing the public Swift API for Firestore. It acts as a bridge to the underlying C++ implementation.FirebaseFirestoreInternalWrapper: This target compiles the core C++ source code of Firestore. It depends on other low-level libraries and C++ dependencies, which are also built from source.
A third, less common build option is available for CI environments. When the
FIREBASECI_USE_LOCAL_FIRESTORE_ZIP environment variable is set, the build
system will use a local FirebaseFirestoreInternal.xcframework instead of
downloading the pre-compiled binary. This option assumes the xcframework is
located at the root of the repository.
This option is primarily used by internal scripts, such as
scripts/check_firestore_symbols.sh, to perform validation against a locally
built version of the Firestore binary. It is not intended for general consumer
use.
The main entry point for integrating Firestore via SPM is the
FirebaseFirestore library product.
.library(
name: "FirebaseFirestore",
targets: ["FirebaseFirestoreTarget"])This product points to a wrapper target, FirebaseFirestoreTarget, which then
depends on the appropriate Firestore targets based on the chosen build option.
The FirebaseFirestoreTarget is a thin wrapper that exists to work around a
limitation in SPM where a single target cannot conditionally depend on
different sets of targets (source vs. binary).
By having clients depend on the wrapper, the Package.swift can internally
manage the complexity of switching between source and binary builds. This
provides a stable entry point for all clients and avoids pushing conditional
logic into their own package manifests.
The testing infrastructure for Firestore in SPM is designed to be independent of the build choice (source vs. binary).
-
FirebaseFirestoreTestingSupport: This is a library target, not a test target. It provides public testing utilities that consumers can use to write unit tests for their Firestore-dependent code. It has a dependency onFirebaseFirestoreTarget, which means it will link against whichever version of Firestore (source or binary) is being used in the build. -
FirestoreTestingSupportTests: This is a test target that contains the unit tests for theFirebaseFirestoreTestingSupportlibrary itself. Its purpose is to validate the testing utilities.
Because both of these targets depend on the FirebaseFirestoreTarget wrapper,
they seamlessly adapt to either the source-based or binary-based build path
without any conditional logic.