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 the FirebaseFirestoreInternalWrapper.FirebaseFirestoreInternalWrapper: A thin wrapper target that exists to
expose the headers from the underlying binary target.FirebaseFirestoreInternal: This is a binaryTarget that downloads and
links the pre-compiled FirebaseFirestoreInternal.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.swift
To 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.swift
For 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 set
Once 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.
FirebaseFirestore (Library product)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.
FirebaseFirestoreTarget (Wrapper target)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 on
FirebaseFirestoreTarget, 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 the FirebaseFirestoreTestingSupport library 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.