From 07f42196b7fe015e412ad9914d61af24e48c5ac0 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 01:09:40 +0000 Subject: [PATCH 1/3] Formatted Jules.md to 80-character line wrap This commit reformats the Jules.md AI guide to ensure all narrative text is wrapped to a maximum of 80 characters per line. This change improves readability, especially in environments or editors with limited horizontal space, and aligns with common markdown style preferences. Code blocks have been preserved with minimal changes to maintain their integrity. --- Jules.md | 499 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 499 insertions(+) create mode 100644 Jules.md diff --git a/Jules.md b/Jules.md new file mode 100644 index 0000000000..96158eca23 --- /dev/null +++ b/Jules.md @@ -0,0 +1,499 @@ +# Introduction + +This document provides context and guidance for AI agents (like Jules) when +making changes to the Firebase C++ SDK repository. It covers essential +information about the repository's structure, setup, testing procedures, API +surface, best practices, and common coding patterns. + +The goal is to enable agents to understand the existing conventions and +contribute effectively to the codebase. + +# Setup Commands + +## Prerequisites + +Before building the Firebase C++ SDK, ensure the following prerequisites are +installed. Refer to the main `README.md` for detailed installation +instructions for your specific platform. + +* **CMake**: Version 3.7 or newer. +* **Python**: Version 3.7 or newer. +* **Abseil-py**: Python package. +* **OpenSSL**: Required for Realtime Database and Cloud Firestore (especially + for desktop builds). +* **Android SDK & NDK**: Required for building Android libraries. `sdkmanager` + can be used for installation. CMake for Android (version 3.10.2 + recommended) is also needed. +* **(Windows Only) Strings**: From Microsoft Sysinternals, required for Android + builds on Windows. +* **Cocoapods**: Required for building iOS or tvOS libraries. + +## Building the SDK + +The SDK uses CMake for C++ compilation and Gradle for Android-specific parts. + +### CMake (Desktop, iOS, tvOS) + +1. Create a build directory (e.g., `mkdir desktop_build && cd desktop_build`). +2. Run CMake to configure: `cmake ..` + * For iOS: + `cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchains/ios.cmake ..` + * For tvOS: + `cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchains/apple.toolchain.cmake -DPLATFORM=TVOS ..` +3. Build specific targets: `cmake --build . --target firebase_analytics` + (replace `firebase_analytics` with the desired library). + +Refer to `README.md` for details on CMake generators and providing custom +third-party dependency locations. + +### Gradle (Android) + +Each Firebase C++ library is a Gradle subproject. To build a specific library +(e.g., Analytics): + +```bash +./gradlew :analytics:assembleRelease +``` + +This command should be run from the root of the repository. Proguard files are +generated in each library's build directory (e.g., +`analytics/build/analytics.pro`). + +## Including the SDK in Projects + +### CMake Projects + +Use `add_subdirectory()` in your `CMakeLists.txt`: + +```cmake +add_subdirectory("[[Path to the Firebase C++ SDK]]") +target_link_libraries([[Your CMake Target]] firebase_analytics firebase_app) +``` + +### Android Gradle Projects + +In addition to CMake setup, use `Android/firebase_dependencies.gradle` in your +`build.gradle`: + +```gradle +apply from: "[[Path to the Firebase C++ SDK]]/Android/firebase_dependencies.gradle" +firebaseCpp.dependencies { + analytics +} +``` + +For more detailed instructions and examples, always refer to the main +`README.md` and the +[C++ Quickstarts](https://github.com/firebase/quickstart-cpp). + +# Testing + +## Testing Strategy + +The primary method for testing in this repository is through **integration +tests** for each Firebase library. While the `README.md` mentions unit tests +run via CTest, the current and preferred approach is to ensure comprehensive +coverage within the integration tests. + +## Running Tests + +* **Integration Test Location**: Integration tests for each Firebase product + (e.g., Firestore, Auth) are typically located in the `integration_test/` + directory within that product's module (e.g., + `firestore/integration_test/`). +* **Test Scripts**: The root of the repository contains scripts for running + tests on various platforms, such as: + * `test_windows_x32.bat` + * `test_windows_x64.bat` + * `test_linux.sh` + * `test_mac_x64.sh` + * `test_mac_ios.sh` + * `test_mac_ios_simulator.sh` + + These scripts typically build the SDKs and then execute the relevant tests + (primarily integration tests) via CTest or other platform-specific test + runners. + +## Writing Tests + +When adding new features or fixing bugs: + +* Prioritize adding or updating integration tests within the respective + product's `integration_test/` directory. +* Ensure tests cover the new functionality thoroughly and verify interactions + with the Firebase backend or other relevant components. +* Follow existing patterns within the integration tests for consistency. + +# API Surface + +## General API Structure + +The Firebase C++ SDK exposes its functionality through a set of classes and +functions organized by product (e.g., Firestore, Authentication, Realtime +Database). + +### Initialization + +1. **`firebase::App`**: This is the central entry point for the SDK. + * It must be initialized first using `firebase::App::Create(...)`. + * On Android, this requires passing the JNI environment (`JNIEnv*`) and + the Android Activity (`jobject`). + * `firebase::AppOptions` can be used to configure the app with specific + parameters if not relying on a `google-services.json` or + `GoogleService-Info.plist` file. +2. **Service Instances**: Once `firebase::App` is initialized, you obtain + instances of specific Firebase services. + * Examples: + * `firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app, &init_result);` + * `firebase::database::Database* database = firebase::database::Database::GetInstance(app, &init_result);` + * Always check the `init_result` (an `InitResult` enum, often + `firebase::kInitResultSuccess` on success) to ensure the service was + initialized successfully. + +### Asynchronous Operations: `firebase::Future` + +All asynchronous operations in the SDK return a `firebase::Future` object, +where `T` is the type of the expected result. + +* **Status Checking**: Use `future.status()` to check if the operation is + `kFutureStatusPending`, `kFutureStatusComplete`, or + `kFutureStatusInvalid`. +* **Getting Results**: Once `future.status() == kFutureStatusComplete`: + * Check for errors: `future.error()`. A value of `0` (e.g., + `firebase::auth::kAuthErrorNone`, `firebase::database::kErrorNone`) + usually indicates success. + * Get the error message: `future.error_message()`. + * Get the result: `future.result()`. This returns a pointer to the result + object of type `T`. The result is only valid if `future.error()` + indicates success. +* **Completion Callbacks**: Use `future.OnCompletion(...)` to register a + callback function (lambda or function pointer) that will be invoked when + the future completes. The callback receives the completed future as an + argument. + +### Core Classes and Operations (Examples from Auth and Database) + +While each Firebase product has its own specific classes, the following examples +illustrate common API patterns: + +* **`firebase::auth::Auth`**: The main entry point for Firebase + Authentication. + * Used to manage users, sign in/out, etc. + * Example: `firebase::auth::User* current_user = auth->current_user();` + * Methods for user creation/authentication: + `CreateUserWithEmailAndPassword()`, `SignInWithEmailAndPassword()`, + `SignInWithCredential()`. +* **`firebase::auth::User`**: + * Represents a user account. Data is typically accessed via its methods. + * Methods for profile updates: `UpdateEmail()`, `UpdatePassword()`, + `UpdateUserProfile()`. + * Other operations: `SendEmailVerification()`, `Delete()`. +* **`firebase::database::Database`**: The main entry point for Firebase + Realtime Database. + * Used to get `DatabaseReference` objects to specific locations in the + database. +* **`firebase::database::DatabaseReference`**: + * Represents a reference to a specific location (path) in the Realtime + Database. + * Methods for navigation: `Child()`, `Parent()`, `Root()`. + * Methods for data manipulation: `GetValue()`, `SetValue()`, + `UpdateChildren()`, `RemoveValue()`. + * Methods for listeners: `AddValueListener()`, `AddChildListener()`. +* **`firebase::database::Query`**: + * Used to retrieve data from a Realtime Database location based on + specific criteria. Obtained from a `DatabaseReference`. + * **Filtering**: `OrderByChild()`, `OrderByKey()`, `OrderByValue()`, + `EqualTo()`, `StartAt()`, `EndAt()`. + * **Limiting**: `LimitToFirst()`, `LimitToLast()`. + * Execution: `GetValue()` returns a `Future`. +* **`firebase::database::DataSnapshot`**: Contains data read from a Realtime + Database location (either directly or as a result of a query). Accessed + via `future.result()` or through listeners. + * Methods: `value()` (returns a `firebase::Variant` representing the + data), `children_count()`, `children()`, `key()`, `exists()`. +* **`firebase::Variant`**: A type that can hold various data types like + integers, strings, booleans, vectors (arrays), and maps (objects), + commonly used for reading and writing data with Realtime Database and other + services. +* **Operation-Specific Options**: Some operations might take optional + parameters to control behavior, though not always through a dedicated + "Options" class like Firestore's `SetOptions`. For example, + `User::UpdateUserProfile()` takes a `UserProfile` struct. + +### Listeners for Real-time Updates + +Many Firebase services support real-time data synchronization using listeners. + +* **`firebase::database::ValueListener` / + `firebase::database::ChildListener`**: Implemented by the developer and + registered with a `DatabaseReference`. + * `ValueListener::OnValueChanged(const firebase::database::DataSnapshot& snapshot)` + is called when the data at that location changes. + * `ChildListener` has methods like `OnChildAdded()`, `OnChildChanged()`, + `OnChildRemoved()`. +* **`firebase::auth::AuthStateListener`**: Implemented by the developer and + registered with `firebase::auth::Auth`. + * `AuthStateListener::OnAuthStateChanged(firebase::auth::Auth* auth)` is + called when the user's sign-in state changes. +* **Removing Listeners**: Listeners are typically removed by passing the + listener instance to a corresponding `Remove...Listener()` method (e.g., + `reference->RemoveValueListener(my_listener);`, + `auth->RemoveAuthStateListener(my_auth_listener);`). + +This overview provides a general understanding. Always refer to the specific +header files in `firebase/app/client/cpp/include/firebase/` and +`firebase/product_name/client/cpp/include/firebase/product_name/` for detailed +API documentation. + +# Best Practices + +## Coding Style + +* **Google C++ Style Guide**: Adhere to the + [Google C++ Style Guide](https://google.github.io/styleguide/cppguide.html) + as mentioned in `CONTRIBUTING.md`. +* **Formatting**: Use `python3 scripts/format_code.py -git_diff -verbose` to + format your code before committing. + +## Comments + +* Write clear and concise comments where necessary to explain complex logic or + non-obvious behavior. +* **Avoid overly verbose comments**: Do not state the obvious. The code should + be as self-documenting as possible. +* Follow existing comment styles within the module you are working on. +* "Avoid adding comments next to `#include` directives merely to explain why + the include is necessary; the code usage should make this clear, or it can + be part of a broader comment block if truly non-obvious for a section of + code." +* "Do not include comments that narrate the AI agent's iterative development + process (e.g., 'Removed old logic here', 'Changed variable name from X to + Y because...', 'Attempted Z but it did not work'). Comments should focus on + explaining the current state of the code for future maintainers, not its + development history or the AI's thought process." + +## Error Handling + +* **Check `Future` status and errors**: Always check `future.status()` and + `future.error()` before attempting to use `future.result()`. + * A common success code is `0` (e.g., + `firebase::auth::kAuthErrorNone`, `firebase::database::kErrorNone`). + Other specific error codes are defined per module (e.g., + `firebase::auth::kAuthErrorUserNotFound`). +* **Callback error parameters**: When using listeners or other callbacks, + always check the provided error code and message before processing the + data. +* Provide meaningful error messages if your code introduces new error + conditions. + +## Resource Management + +* **`firebase::Future`**: `Future` objects manage their own resources. + `Future::Release()` can be called, but it's often handled by RAII when + futures go out of scope. Be mindful of `Future` lifetimes if they are + stored as members or passed around. +* **ListenerRegistrations**: When a listener is no longer needed, call + `ListenerRegistration::Remove()` to detach it. Failure to do so can lead + to memory leaks and unnecessary network/CPU usage. +* **Pointers**: Standard C++ smart pointers (`std::unique_ptr`, + `std::shared_ptr`) should be used where appropriate for managing + dynamically allocated memory. + +## Immutability + +* Be aware that some objects, like `firebase::firestore::Query`, are + immutable. Methods that appear to modify them (e.g., `query.Where(...)`) + actually return a new instance with the modification. + +## Platform-Specific Code + +* Firebase C++ SDK supports multiple platforms (Android, iOS, tvOS, desktop - + Windows, macOS, Linux). +* Platform-specific code is typically organized into subdirectories: + * `android/` (for Java/JNI related code) + * `ios/` (for Objective-C/Swift interoperability code) + * `desktop/` (for Windows, macOS, Linux specific implementations) + * `common/` (for C++ code shared across all platforms) +* Use preprocessor directives (e.g., `#if FIREBASE_PLATFORM_ANDROID`, + `#if FIREBASE_PLATFORM_IOS`) to conditionally compile platform-specific + sections when necessary, but prefer separate implementation files where + possible for better organization. + +## Class and File Structure + +* Follow the existing pattern of internal and common classes within each + Firebase library (e.g., `firestore/src/common`, `firestore/src/main`, + `firestore/src/android`). +* Public headers defining the API are typically in + `src/include/firebase/product_name/`. +* Internal implementation classes often use the `Internal` suffix (e.g., + `DocumentReferenceInternal`). + +# Common Patterns + +## Pimpl (Pointer to Implementation) Idiom + +* Many public API classes (e.g., `firebase::storage::StorageReference`, + `firebase::storage::Metadata`) use the Pimpl idiom. +* They hold a pointer to an internal implementation class (e.g., + `StorageReferenceInternal`, `MetadataInternal`). +* This pattern helps decouple the public interface from its implementation, + reducing compilation dependencies and hiding internal details. +* When working with these classes, you will primarily interact with the public + interface. Modifications to the underlying implementation are done in the + `*Internal` classes. + +A common convention for this Pimpl pattern in the codebase (e.g., as seen in +`firebase::storage::Metadata`) is that the public class owns the raw pointer to +its internal implementation (`internal_`). This requires careful manual memory +management: +* **Creation**: The `internal_` object is typically allocated with `new` in + the public class's constructor(s). For instance, the default constructor + might do `internal_ = new ClassNameInternal(...);`, and a copy constructor + would do `internal_ = new ClassNameInternal(*other.internal_);` for a + deep copy. +* **Deletion**: The `internal_` object is `delete`d in the public class's + destructor (e.g., `delete internal_;`). It's good practice to set + `internal_ = nullptr;` immediately after deletion if the destructor isn't + the absolute last point of usage, or if helper delete functions are used + (as seen with `MetadataInternalCommon::DeleteInternal` which nullifies the + pointer in the public class instance before deleting). +* **Copy Semantics**: + * **Copy Constructor**: If supported, a deep copy is usually performed. A + new `internal_` instance is created, and the contents from the source + object's `internal_` are copied into this new instance. + * **Copy Assignment Operator**: If supported, it must also perform a deep + copy. This typically involves deleting the current `internal_` object, + then creating a new `internal_` instance and copying data from the + source's `internal_` object. Standard self-assignment checks should be + present. +* **Move Semantics**: + * **Move Constructor**: If supported, ownership of the `internal_` pointer + is transferred from the source object to the new object. The source + object's `internal_` pointer is then set to `nullptr` to prevent + double deletion. + * **Move Assignment Operator**: Similar to the move constructor, it + involves deleting the current object's `internal_`, then taking + ownership of the source's `internal_` pointer, and finally setting the + source's `internal_` to `nullptr`. +* **Cleanup Registration (Advanced)**: In some cases, like + `firebase::storage::Metadata`, there might be an additional registration + with a central cleanup mechanism (e.g., via `StorageInternal`). This acts + as a safeguard or part of a larger resource management strategy within the + module, but the fundamental responsibility for creation and deletion in + typical scenarios lies with the Pimpl class itself. + +It's crucial to correctly implement all these aspects (constructors, destructor, +copy/move operators) when dealing with raw pointer Pimpls to prevent memory +leaks, dangling pointers, or double deletions. + +## Namespace Usage + +* Code for each Firebase product is typically within its own namespace under + `firebase`. + * Example: `firebase::firestore`, `firebase::auth`, + `firebase::database`. +* Internal or platform-specific implementation details might be in nested + namespaces like `firebase::firestore::internal` or + `firebase::firestore::android`. + +## Futures for Asynchronous Operations + +* As detailed in the API Surface section, `firebase::Future` is the + standard way all asynchronous operations return their results. +* Familiarize yourself with `Future::status()`, `Future::error()`, + `Future::error_message()`, `Future::result()`, and + `Future::OnCompletion()`. + +## Internal Classes and Helpers + +* Each module often has a set of internal classes (often suffixed with + `Internal` or residing in an `internal` namespace) that manage the core + logic, platform-specific interactions, and communication with the Firebase + backend. +* Utility functions and helper classes are common within the `common/` or + `util/` subdirectories of a product. + +## Singleton Usage (Limited) + +* The primary singleton is `firebase::App::GetInstance()`. +* Service entry points like `firebase::firestore::Firestore::GetInstance()` + also provide singleton-like access to service instances (scoped to an `App` + instance). +* Beyond these entry points, direct creation or use of singletons for core + data objects or utility classes is not a dominant pattern. Dependencies are + generally passed explicitly. + +## Platform Abstraction + +* For operations that differ by platform, there's often a common C++ + interface defined in `common/` or `main/`, with specific implementations + in `android/`, `ios/`, and `desktop/` directories. +* JNI is used extensively in `android/` directories for C++ to Java + communication. +* Objective-C++ (`.mm` files) is used in `ios/` directories for C++ to + Objective-C communication. + +## Listener Pattern + +* The `AddSnapshotListener`/`ListenerRegistration` pattern is common for + features requiring real-time updates (e.g., Firestore, Realtime + Database). + +## Builder/Fluent Interface for Queries + +* Classes like `firebase::firestore::Query` use a fluent interface (method + chaining) to construct complex queries by progressively adding filters, + ordering, and limits. Each call typically returns a new instance of the + query object. + +# Updating This Document + +This document is a living guide. As the Firebase C++ SDK evolves, new patterns +may emerge, or existing practices might change. If you introduce a new common +pattern, significantly alter a build process, or establish a new best practice +during your work, please take a moment to update this `Jules.md` file +accordingly. + +Keeping this document current will greatly benefit future AI agents and human +developers working on this repository. + +# Prompting Jules AI + +## Recommended General Prompt Instruction + +When working on this task, please consistently refer to the `Jules.md` guide +for all repository-specific conventions, including setup procedures, coding +style, common architectural patterns, and API usage. Pay close attention to the +testing strategies outlined, ensuring your implementation includes +comprehensive integration tests with detailed test cases in your plan. Implement +robust error handling for any new or modified public API methods, following the +patterns for `firebase::Future` error reporting. If the feature involves +platform-specific code, ensure the public API remains consistent across all +platforms, as discussed in `Jules.md`. Write clear, maintainable code, +adhering to the commenting guidelines, and if you need to add new third-party +dependencies, document the rationale and update build configurations according +to the established practices. Ensure your changes align with the overall best +practices detailed in `Jules.md`. + +## Key Directives for Jules AI + +* **Prioritize `Jules.md`**: This document (`Jules.md`) contains + repository-specific guidelines. Prioritize this information when making + decisions about coding style, testing procedures, architectural patterns, + and API usage. +* **Adherence to Patterns**: Strive to follow the common patterns and best + practices outlined here. This ensures consistency across the codebase. +* **Clarification for Deviations**: If the existing patterns in `Jules.md` do + not seem suitable for a specific task, or if a deviation is necessary, + please explicitly state this in your plan or request clarification before + proceeding with implementation. +* **Updating `Jules.md`**: If you introduce a new, broadly applicable + pattern, or if a significant change to the build process or best practices + occurs as part of your task, please include a step in your plan to update + `Jules.md` to reflect these changes. +* **Testing**: Remember that integration tests are the primary method of + testing. Ensure new features are accompanied by corresponding integration + tests as described in the 'Testing' section of `Jules.md`. +* **Commit Messages**: Follow standard commit message guidelines. A brief + summary line, followed by a more detailed explanation if necessary. From 2263a342d3da28c4e629ba131fedaab0e1124331 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 21:41:43 +0000 Subject: [PATCH 2/3] Enrich Jules.md with info from online Firebase C++ docs This commit updates Jules.md, the AI agent guide, with additional context and details sourced from the official Firebase C++ online documentation. Key enhancements include: - **Introduction**: Added a link to the Firebase library support by platform table and a note on the open-source structure of the C++ SDKs (desktop vs. mobile). - **Setup Commands**: - Clarified iOS setup to include linking .framework files alongside pods. - Added a new "Desktop Platform Setup Details" subsection, covering: - Conversion of iOS `GoogleService-Info.plist` to `google-services-desktop.json` using the provided Python script. - Search order for desktop configuration files. - Common system library dependencies for Windows, macOS, and Linux desktop builds. - **API Surface**: - Clarified that `firebase::auth::User` objects are typically obtained from `firebase::auth::AuthResult` after successful authentication operations. - **Best Practices**: - Added a "Platform-Specific Considerations" subsection detailing: - The REST-based nature of the Realtime Database C++ SDK on desktop and the consequent need for server-side indexing for `OrderByChild()` queries. - Awareness of iOS method swizzling used by some Firebase products. These additions provide more comprehensive guidance for you, particularly regarding platform-specific nuances and SDK architecture. The document maintains an 80-character line wrap. --- Jules.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/Jules.md b/Jules.md index 96158eca23..fcf798f380 100644 --- a/Jules.md +++ b/Jules.md @@ -5,6 +5,16 @@ making changes to the Firebase C++ SDK repository. It covers essential information about the repository's structure, setup, testing procedures, API surface, best practices, and common coding patterns. +For a detailed view of which Firebase products are supported on each C++ +platform (Android, iOS, tvOS, macOS, Windows, Linux), refer to the official +[Firebase library support by platform table](https://firebase.google.com/docs/cpp/learn-more#library-support-by-platform). + +The Firebase C++ SDKs for desktop platforms (Windows, Linux, macOS) are +entirely open source and hosted in the main `firebase/firebase-cpp-sdk` GitHub +repository. The C++ SDKs for mobile platforms (iOS, tvOS, Android) are built +on top of the respective native open-source Firebase SDKs (Firebase iOS SDK and +Firebase Android SDK). + The goal is to enable agents to understand the existing conventions and contribute effectively to the codebase. @@ -38,6 +48,9 @@ The SDK uses CMake for C++ compilation and Gradle for Android-specific parts. 2. Run CMake to configure: `cmake ..` * For iOS: `cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchains/ios.cmake ..` + Note: iOS setup typically requires both including Firebase pods (via + `Podfile`) and linking the `.framework` files from the C++ SDK + distribution. * For tvOS: `cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchains/apple.toolchain.cmake -DPLATFORM=TVOS ..` 3. Build specific targets: `cmake --build . --target firebase_analytics` @@ -59,6 +72,26 @@ This command should be run from the root of the repository. Proguard files are generated in each library's build directory (e.g., `analytics/build/analytics.pro`). +### Desktop Platform Setup Details + +When setting up for desktop, if you are using an iOS `GoogleService-Info.plist` +file, convert it to the required `google-services-desktop.json` using the +script: `python generate_xml_from_google_services_json.py --plist -i GoogleService-Info.plist` +(run this from the script's directory, ensuring the plist file is accessible). + +The desktop SDK searches for configuration files in the current working +directory, first for `google-services-desktop.json`, then for +`google-services.json`. + +Common system library dependencies for desktop: +* **Windows**: Common dependencies include `advapi32.lib`, `ws2_32.lib`, + `crypt32.lib`. Specific products might need others (e.g., Firestore: + `rpcrt4.lib`, `ole32.lib`, `shell32.lib`). +* **macOS**: Common dependencies include `pthread` (system library) and + frameworks like `CoreFoundation`, `Foundation`, and `Security`. +* **Linux**: Common dependencies include `pthread` (system library). When + using GCC 5+, define `-D_GLIBCXX_USE_CXX11_ABI=0`. + ## Including the SDK in Projects ### CMake Projects @@ -179,6 +212,12 @@ illustrate common API patterns: * **`firebase::auth::Auth`**: The main entry point for Firebase Authentication. * Used to manage users, sign in/out, etc. + * Successful authentication operations (like + `SignInWithEmailAndPassword()`) return a + `Future`. The `firebase::auth::User` + object can then be obtained from this `AuthResult` (e.g., + `auth_result.result()->user()` after `result()` is confirmed + successful and the pointer is checked). * Example: `firebase::auth::User* current_user = auth->current_user();` * Methods for user creation/authentication: `CreateUserWithEmailAndPassword()`, `SignInWithEmailAndPassword()`, @@ -319,6 +358,21 @@ API documentation. sections when necessary, but prefer separate implementation files where possible for better organization. +## Platform-Specific Considerations + +* **Realtime Database (Desktop)**: The C++ SDK for Realtime Database on + desktop platforms (Windows, macOS, Linux) uses a REST-based + implementation. This means that any queries involving + `Query::OrderByChild()` require corresponding indexes to be defined in your + Firebase project's Realtime Database rules. Without these indexes, queries + may fail or not return expected results. +* **iOS Method Swizzling**: Be aware that some Firebase products on iOS + (e.g., Dynamic Links, Cloud Messaging) use method swizzling to + automatically attach handlers to your `AppDelegate`. While this simplifies + integration, it can occasionally be a factor to consider when debugging app + delegate behavior or integrating with other libraries that also perform + swizzling. + ## Class and File Structure * Follow the existing pattern of internal and common classes within each From c87cd1cb33595cd8bdf5c4b38442e5be08ef4f60 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 18 Jun 2025 00:45:52 +0000 Subject: [PATCH 3/3] I've updated the Jules.md file with information about Analytics initialization and Future management. This update incorporates further feedback from you into Jules.md: 1. **Clarified Analytics Initialization:** The "API Surface" -> "Initialization" section now specifies that Firebase Analytics uses a different initialization pattern (`firebase::analytics::Initialize(app)`) compared to the common `GetInstance(app, ...)` pattern of other services. It also notes that Analytics functions are typically called globally. 2. **Added Future Lifecycle Management Guidance:** A new point in "Best Practices" -> "Resource Management" emphasizes the importance of ensuring `Future` objects complete their course (e.g., via `OnCompletion` or by checking results) to prevent potential issues with operations not finalizing or resources not being cleaned up promptly. These changes provide more nuanced guidance for interacting with the Firebase C++ SDK. --- Jules.md | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/Jules.md b/Jules.md index fcf798f380..7da3ccf1b0 100644 --- a/Jules.md +++ b/Jules.md @@ -174,14 +174,26 @@ Database). * `firebase::AppOptions` can be used to configure the app with specific parameters if not relying on a `google-services.json` or `GoogleService-Info.plist` file. -2. **Service Instances**: Once `firebase::App` is initialized, you obtain - instances of specific Firebase services. - * Examples: +2. **Service Instances**: Once `firebase::App` is initialized, you generally + obtain instances of specific Firebase services using a static `GetInstance()` + method on the service's class, passing the `firebase::App` object. + * Examples for services like Auth, Database, Storage, Firestore: * `firebase::auth::Auth* auth = firebase::auth::Auth::GetAuth(app, &init_result);` * `firebase::database::Database* database = firebase::database::Database::GetInstance(app, &init_result);` + * `firebase::storage::Storage* storage = firebase::storage::Storage::GetInstance(app, &init_result);` * Always check the `init_result` (an `InitResult` enum, often - `firebase::kInitResultSuccess` on success) to ensure the service was - initialized successfully. + `firebase::kInitResultSuccess` on success) to ensure these services + were initialized successfully. + * **Note on Analytics**: Some products, like Firebase Analytics, have a + different pattern. Analytics is typically initialized with + `firebase::analytics::Initialize(const firebase::App& app)` (often + handled automatically for the default `App` instance). After this, + Analytics functions (e.g., `firebase::analytics::LogEvent(...)`) are + called as global functions within the `firebase::analytics` namespace, + rather than on an instance object obtained via `GetInstance()`. + Refer to the specific product's header file for its exact + initialization mechanism if it deviates from the common `GetInstance(app, ...)` + pattern. ### Asynchronous Operations: `firebase::Future` @@ -337,6 +349,19 @@ API documentation. * **Pointers**: Standard C++ smart pointers (`std::unique_ptr`, `std::shared_ptr`) should be used where appropriate for managing dynamically allocated memory. +* **`Future` Lifecycle**: Ensure `Future` objects returned from API calls are + properly managed. While `Future`s handle their own internal memory for the + result, the asynchronous operations they represent need to complete to + reliably free all associated operational resources or to ensure actions + (like writes to a database) are definitely finalized. Abandoning a `Future` + (letting it go out of scope without checking its result, attaching an + `OnCompletion` callback, or explicitly `Wait()`ing for it) can sometimes + lead to operations not completing as expected or resources not being + cleaned up promptly by the underlying services, especially if the `Future` + is the only handle to that operation. Prefer using `OnCompletion` or + otherwise ensuring the `Future` completes its course, particularly for + operations with side effects or those that allocate significant backend + resources. ## Immutability