Skip to content

[FR]: SPM downloads gRPC/abseil binaries (652 MB) even when Firestore is not used #16532

Description

@kimdane0115

Description

1. Use case

An app that links only Analytics / Crashlytics / Messaging — and never links Firestore — still resolves and downloads the Firestore-only binary dependencies.

In our app the only linked Firebase products are FirebaseCore, FirebaseMessaging, FirebaseAnalytics and FirebaseCrashlytics. FirebaseFirestore is not linked anywhere. Despite that, SwiftPM downloads:

Artifact Size
grpc-binary 1.69.1 610 MB
abseil-cpp-binary 1.2024072200.0 42 MB

That is 652 MB, ~42% of our entire SwiftPM cache (1,543 MB total for all packages).

For comparison, the artifacts we actually use are much smaller: firebase-ios-sdk 132 MB and googleappmeasurement 42 MB.

2. How the Firebase SDK currently handles it

In Package.swift, gRPC and abseil are declared as package-level dependencies:

if shouldUseSourceFirestore {
  packageInfo = ("https://github.com/grpc/grpc-ios.git", "1.69.0" ..< "1.70.0")
} else {
  packageInfo = ("https://github.com/google/grpc-binary.git", "1.69.0" ..< "1.70.0")
}

and they are consumed only by the FirebaseFirestore target:

.product(name: "abseil", package: "abseil-cpp-binary", condition: .when(platforms: [...])),
.product(name: "gRPC-C++", package: "grpc-binary", condition: .when(platforms: [...])),

Because SwiftPM resolves and fetches binary artifacts for the whole package graph regardless of which products the app actually links, these binaries are downloaded by every app that depends on firebase-ios-sdk, including apps that never touch Firestore.

This is a regression in behaviour compared to CocoaPods, where only the pods matching the declared subspecs were installed.

3. How we propose the Firebase SDK should handle it

Make the Firestore-only binary dependencies conditional so that apps not linking FirebaseFirestore never resolve them. Two possible directions:

  • Gate grpc-binary / abseil-cpp-binary behind a SwiftPM trait, so they are only resolved when Firestore is requested; or
  • Split Firestore (or at least its gRPC-dependent portion) into a separate package.

There is precedent for trimming the graph for exactly this reason: #15680 removed the swift-protobuf and GoogleDataTransport dependencies from ML Model Downloader to address #15649 ("Swift Package is very heavy"), shipped in 12.8.0. The Firestore binaries are more than an order of magnitude larger than what that PR saved.

Additional impact for Flutter apps

Flutter 3.44+ enables SwiftPM by default and points -clonedSourcePackagesDirPath at build/ios/SourcePackages, which flutter clean deletes. Every clean therefore discards these artifacts and the next build has to restore them. On CI, where each run starts from a cold cache, the 652 MB is downloaded on every single build.

Environment

  • firebase-ios-sdk 12.15.0 (Swift Package Manager)
  • grpc-binary 1.69.1, abseil-cpp-binary 1.2024072200.0
  • Xcode 26.6 (17F113), macOS
  • Flutter 3.44.9 (SwiftPM is the default since Flutter 3.44)
  • Linked products: FirebaseCore, FirebaseMessaging, FirebaseAnalytics, FirebaseCrashlytics
  • Not linked: FirebaseFirestore

Measured with du -sm build/ios/SourcePackages/artifacts/*:

610   artifacts/grpc-binary
132   artifacts/firebase-ios-sdk
 42   artifacts/googleappmeasurement
 42   artifacts/abseil-cpp-binary
 14   artifacts/google-ads-on-device-conversion-ios-sdk
1543  (whole SourcePackages directory)

Firebase Product(s) dropdown: select Firestore (source of the dependency).
Others affected: Analytics, Crashlytics, Messaging.

API Proposal

No response

Firebase Product(s)

Firestore

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions