浏览代码

docs(firestore): Add docs on Firestore x SPM integration (#15387)

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Nick Cooke 5 月之前
父节点
当前提交
abf5e55728
共有 2 个文件被更改,包括 199 次插入0 次删除
  1. 3 0
      Firestore/README.md
  2. 196 0
      docs/FirestoreSPM.md

+ 3 - 0
Firestore/README.md

@@ -48,6 +48,9 @@ scripts/build.sh Firestore iOS spm
 
 This is rarely necessary for primary development and is done automatically by CI.
 
+For a detailed explanation of the Firestore target hierarchy in the
+`Package.swift` manifest, see [FirestoreSPM.md](../docs/FirestoreSPM.md).
+
 ### Improving the debugger experience
 
 You can install a set of type formatters to improve the presentation of

+ 196 - 0
docs/FirestoreSPM.md

@@ -0,0 +1,196 @@
+# Firestore Swift Package Manager Target Hierarchy
+
+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).
+
+---
+
+## 1. Binary-based build (Default)
+
+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.
+
+### Dependency hierarchy
+
+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)
+```
+
+### Target breakdown
+
+*   **`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.
+
+---
+
+## 2. Source-based build
+
+When the `FIREBASE_SOURCE_FIRESTORE` environment variable is set, Firestore and
+its dependencies (like abseil and gRPC) are compiled from source.
+
+### How to build Firestore from source
+
+To build Firestore from source, set the `FIREBASE_SOURCE_FIRESTORE` environment
+variable before building the project.
+
+#### Building with Xcode
+
+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:
+
+```console
+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:
+```console
+open --env FIREBASECI_USE_LATEST_GOOGLEAPPMEASUREMENT \
+--env FIREBASE_SOURCE_FIRESTORE Package.swift
+```
+
+#### Command-line builds
+
+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.
+
+```bash
+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.
+
+```bash
+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.
+
+### Dependency hierarchy
+
+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)
+```
+
+### Target breakdown
+
+*   **`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.
+
+---
+
+## 3. Local binary build (CI only)
+
+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.
+
+---
+
+## Core target explanations
+
+### `FirebaseFirestore` (Library product)
+
+The main entry point for integrating Firestore via SPM is the
+`FirebaseFirestore` library product.
+
+```swift
+.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.
+
+---
+
+## Test targets
+
+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.