Files
Andrew Heard c06a1d7199 feat(appcheck): read CLI debug token on Simulator (#17017)
Co-authored-by: Nick Cooke <36927374+ncooke3@users.noreply.github.com>

In a Simulator, AppCheckDebugProvider now uses the debug token that
`firebase appcheck:debugtokens:create` saves to
~/.config/configstore/firebase-appcheck.json on the host, so apps
launched from Xcode work without manually registering a token. The
token is looked up by each app's Google App ID through
SIMULATOR_HOST_HOME. The lookup is compiled out on devices, macOS and
Mac Catalyst. No public API changes.

Debug tokens are now resolved in this order:
1. AppCheckDebugToken or FIRAAppCheckDebugToken environment variable
2. Token from the CLI config store (Simulator only)
3. Token stored in UserDefaults
4. Newly generated UUID

The config store comes before the stored token so a newly provisioned
token takes effect without reinstalling the app.

Logging:
- I-FAA004003: debug token loaded from the config store.
- I-FAA004004: exchanging the config store token failed; suggests
  re-running the CLI with --force and relaunching.
- I-FAA004002: exchanging an environment variable token failed; now
  names the variables instead of showing an unrelated local token.
- I-FAA004005: the config store exists but can't be read or parsed.
A missing file, or a path where it can't exist (e.g., ~/.config is a
regular file), is silent. Exchange-failure warnings are skipped when
the server is unreachable, and no message includes the token.
2026-11-06 19:23:51 -05:00

1866 lines
59 KiB
Swift

// swift-tools-version:6.2
// The swift-tools-version declares the minimum version of the Swift toolchain required to
// build this package. Note: Firebase requires Xcode 26.2+, which includes the Swift 6.2.3 compiler.
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#if compiler(<6.2.3)
#error("Firebase requires Swift 6.2.3 or higher. Please upgrade to Xcode 26.2 or later.")
#endif // compiler(<6.2.3)
import PackageDescription
let firebaseVersion = "13.2.0"
/// The name of the "Firestore" package trait.
let firestoreTraitName = "Firestore"
/// The "Firestore" package trait, which is on by default.
///
/// A package trait is an optional feature you can turn on or off when you add a package. This
/// trait controls whether Firestore and its dependencies (gRPC and Abseil) are downloaded and
/// built. If your app doesn't use Firestore, turn the trait off so that Swift Package Manager
/// (SwiftPM) downloads fewer packages. See `packageTraits` for how.
let firestoreTrait = Trait(
name: firestoreTraitName,
description: "Enables Firestore support and its underlying dependencies (gRPC, Abseil)."
)
/// The package traits that Firebase declares, with the "Firestore" trait on by default.
///
/// Turning off Firestore requires Xcode 26.4 or later (Swift 6.3 or later). With Xcode 26.2
/// (Swift 6.2), the setting is accepted but has no effect: Firestore is always included, and the
/// "trait is disabled" build error never appears. See `isFirestoreTraitConditionSupported` for why.
///
/// To turn off Firestore:
///
/// - In your own `Package.swift`, add `traits: []` (no default traits) to the Firebase dependency:
/// ```swift
/// .package(
/// url: "https://github.com/firebase/firebase-ios-sdk.git",
/// from: "13.0.0",
/// traits: []
/// )
/// ```
/// Leaving out `traits:` keeps the default traits, so Firestore is included.
/// - In an Xcode project, select your project, open the Package Dependencies tab, and uncheck
/// "Firestore" in the Traits menu for Firebase.
///
/// After turning off the trait, remove the `FirebaseFirestore` product from your targets, or the
/// build fails with an error asking you to turn the trait back on.
let packageTraits = Set<Trait>([
firestoreTrait,
// All traits are enabled by default.
.default(enabledTraits: [firestoreTraitName]),
])
/// Whether the "Firestore" trait can include or exclude Firestore with this version of Swift.
///
/// The problem: Xcode 26.2 has a bug. When an Xcode project (`.xcodeproj`) adds Firebase by its
/// GitHub URL, Xcode 26.2 doesn't turn on Firebase's default traits. (Packages that depend on
/// Firebase in their own `Package.swift` aren't affected.) Without the workaround below,
/// everything that requires the "Firestore" trait would be skipped, so Firestore would be missing
/// from apps that never turned it off.
///
/// The workaround: when this value is `false`, `firestoreTraitDependencyCondition(platforms:)` and
/// `firestoreTraitBuildSettingCondition()` ignore the trait. Firestore and its dependencies are
/// always built, and `FIRESTORE_TRAIT_ENABLED` is always defined, so the "trait is disabled" error
/// can't occur. Turning off the trait has no effect, even with `swift build` on Swift 6.2.
///
/// The trait is still declared because SwiftPM 6.2 fails to resolve any `Package.swift` that
/// passes `traits:` (even `traits: []`) to a dependency that declares no traits.
///
/// `Package.swift` can't check the Xcode version, so the compiler version stands in for it:
/// Xcode 26.2 includes Swift 6.2; Xcode 26.4, which handles traits correctly, includes Swift 6.3.
///
/// Remove this constant and the two helper functions once Firebase requires Xcode 26.4 or later.
#if compiler(>=6.3)
let isFirestoreTraitConditionSupported = true
#else
let isFirestoreTraitConditionSupported = false
#endif // compiler(>=6.3)
let shouldUseSourceFirestore = Context.environment["FIREBASE_SOURCE_FIRESTORE"] != nil
let package = Package(
name: "Firebase",
platforms: [.iOS(.v15), .macCatalyst(.v15), .macOS(.v11), .tvOS(.v15), .watchOS(.v8)],
products: packageProducts(),
traits: packageTraits,
dependencies: packageDependencies(),
targets: packageTargets(),
cxxLanguageStandard: CXXLanguageStandard.gnucxx17
)
// MARK: - Package Manifest Builders
func packageProducts() -> [Product] {
return [
.library(
name: "FirebaseAILogic",
targets: [
"FirebaseAILogic",
]
),
.library(
name: "FirebaseAnalytics",
targets: ["FirebaseAnalyticsTarget"]
),
// Adding this library to your project is enough for it to take effect. The module
// does not need to be imported into any source files.
.library(
name: "FirebaseAnalyticsCore",
targets: ["FirebaseAnalyticsCoreTarget"]
),
// Adding this library to your project is enough for it to take effect. The module
// does not need to be imported into any source files.
.library(
name: "FirebaseAnalyticsIdentitySupport",
targets: ["FirebaseAnalyticsIdentitySupportTarget"]
),
.library(
name: "FirebaseAuth",
targets: ["FirebaseAuth"]
),
.library(
name: "FirebaseAppCheck",
targets: ["FirebaseAppCheck"]
),
.library(
name: "FirebaseAppDistribution-Beta",
targets: ["FirebaseAppDistributionTarget"]
),
.library(
name: "FirebaseAuthCombine-Community",
targets: ["FirebaseAuthCombineSwift"]
),
.library(
name: "FirebaseFirestoreCombine-Community",
targets: ["FirebaseFirestoreCombineSwift"]
),
.library(
name: "FirebaseFunctionsCombine-Community",
targets: ["FirebaseFunctionsCombineSwift"]
),
.library(
name: "FirebaseStorageCombine-Community",
targets: ["FirebaseStorageCombineSwift"]
),
.library(
name: "FirebaseCore",
targets: ["FirebaseCore"]
),
.library(
name: "FirebaseCrashlytics",
targets: ["FirebaseCrashlytics"]
),
.library(
name: "FirebaseDatabase",
targets: ["FirebaseDatabase"]
),
.library(
name: "FirebaseFirestore",
targets: ["FirebaseFirestoreTarget"]
),
.library(
name: "FirebaseFunctions",
targets: ["FirebaseFunctions"]
),
.library(
name: "FirebaseInAppMessaging-Beta",
targets: ["FirebaseInAppMessagingTarget"]
),
.library(
name: "FirebaseInstallations",
targets: ["FirebaseInstallations"]
),
.library(
name: "FirebaseMessaging",
targets: ["FirebaseMessaging"]
),
.library(
name: "FirebasePerformance",
targets: ["FirebasePerformanceTarget"]
),
.library(
name: "FirebaseRemoteConfig",
targets: ["FirebaseRemoteConfig"]
),
.library(
name: "FirebaseStorage",
targets: ["FirebaseStorage"]
),
]
}
func packageDependencies() -> [Package.Dependency] {
return [
.package(
url: "https://github.com/google/promises.git",
"2.4.1" ..< "3.0.0"
),
googleAppMeasurementDependency(),
.package(
url: "https://github.com/google/GoogleDataTransport.git",
"10.1.1" ..< "11.0.0"
),
.package(
url: "https://github.com/google/GoogleUtilities.git",
"8.1.4" ..< "9.0.0"
),
.package(
url: "https://github.com/google/gtm-session-fetcher.git",
"4.0.0" ..< "6.0.0"
),
.package(
url: "https://github.com/firebase/nanopb.git",
"2.30910.1" ..< "2.30911.0"
),
abseilDependency(),
grpcDependency(),
.package(
url: "https://github.com/erikdoe/ocmock.git",
revision: "2c0bfd373289f4a7716db5d6db471640f91a6507"
),
.package(
url: "https://github.com/firebase/leveldb.git",
"1.22.5" ..< "1.23.0"
),
.package(
url: "https://github.com/SlaunchaMan/GCDWebServer.git",
revision: "935e2736044e71e5341663c3cc9a335ba6867a2b"
),
.package(
url: "https://github.com/google/interop-ios-for-google-sdks.git",
"101.0.0" ..< "102.0.0"
),
appCheckDependency(),
]
}
func packageTargets() -> [Target] {
var targets: [Target] = [
.target(
name: "Firebase",
path: "CoreOnly/Sources",
publicHeadersPath: "./"
),
// MARK: - Firebase AI
.target(
name: "FirebaseAILogic",
dependencies: firebaseAILogicDependencies(),
path: "FirebaseAI/Sources"
),
.testTarget(
name: "FirebaseAILogicUnit",
dependencies: [
"FirebaseAILogic",
"FirebaseStorage",
],
path: "FirebaseAI/Tests/Unit",
exclude: [
"README.md",
"Snippets/README.md",
],
resources: [
.copy("vertexai-sdk-test-data/mock-responses"),
.process("Resources"),
],
cSettings: [
.headerSearchPath("../../../"),
]
),
// MARK: - Firebase Core
.target(
name: "FirebaseCore",
dependencies: [
"Firebase",
"FirebaseCoreInternal",
.product(name: "GULEnvironment", package: "GoogleUtilities"),
.product(name: "GULLogger", package: "GoogleUtilities"),
],
path: "FirebaseCore/Sources",
resources: [.process("Resources/PrivacyInfo.xcprivacy")],
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("../.."),
.define("Firebase_VERSION", to: firebaseVersion),
// TODO: - Add support for cflags cSetting so that we can set the -fno-autolink option
],
linkerSettings: [
.linkedFramework("UIKit", .when(platforms: [.iOS, .macCatalyst, .tvOS])),
.linkedFramework("AppKit", .when(platforms: [.macOS])),
]
),
.testTarget(
name: "CoreUnit",
dependencies: [
"FirebaseCore",
"SharedTestUtilities",
.product(name: "OCMock", package: "ocmock"),
],
path: "FirebaseCore/Tests/Unit",
exclude: ["Resources/GoogleService-Info.plist"],
cSettings: [
.headerSearchPath("../../.."),
]
),
// MARK: - Firebase Core Extension
// Extension of FirebaseCore for consuming by Swift product SDKs.
// When depending on `FirebaseCoreExtension`, also depend on `FirebaseCore`
// to avoid potential linker issues.
.target(
name: "FirebaseCoreExtension",
path: "FirebaseCore/Extension",
resources: [.process("Resources/PrivacyInfo.xcprivacy")],
publicHeadersPath: ".",
cSettings: [
.headerSearchPath("../../"),
]
),
// MARK: - Firebase Core Internal
// Shared collection of APIs for internal FirebaseCore usage.
.target(
name: "FirebaseCoreInternal",
dependencies: [
.product(name: "GULNSData", package: "GoogleUtilities"),
],
path: "FirebaseCore/Internal/Sources",
resources: [.process("Resources/PrivacyInfo.xcprivacy")]
),
.testTarget(
name: "FirebaseCoreInternalTests",
dependencies: [
"FirebaseCoreInternal",
],
path: "FirebaseCore/Internal/Tests"
),
.target(
name: "FirebaseABTesting",
dependencies: ["FirebaseCore"],
path: "FirebaseABTesting/Sources",
resources: [.process("Resources/PrivacyInfo.xcprivacy")],
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("../../"),
]
),
.testTarget(
name: "ABTestingUnit",
dependencies: ["FirebaseABTesting", .product(name: "OCMock", package: "ocmock")],
path: "FirebaseABTesting/Tests/Unit",
resources: [.process("Resources")],
cSettings: [
.headerSearchPath("../../.."),
]
),
.target(
name: "FirebaseAnalyticsTarget",
dependencies: [.target(name: "FirebaseAnalyticsWrapper",
condition: .when(platforms: [.iOS, .macCatalyst, .macOS, .tvOS]))],
path: "SwiftPM-PlatformExclude/FirebaseAnalyticsWrap"
),
.target(
name: "FirebaseAnalyticsWrapper",
dependencies: [
.target(
name: "FirebaseAnalytics",
condition: .when(platforms: [.iOS, .macCatalyst, .macOS, .tvOS])
),
.product(name: "GoogleAppMeasurement",
package: "GoogleAppMeasurement",
condition: .when(platforms: [.iOS, .macCatalyst, .macOS, .tvOS])),
"FirebaseCore",
"FirebaseInstallations",
.product(name: "GULAppDelegateSwizzler", package: "GoogleUtilities"),
.product(name: "GULMethodSwizzler", package: "GoogleUtilities"),
.product(name: "GULNSData", package: "GoogleUtilities"),
.product(name: "GULNetwork", package: "GoogleUtilities"),
.product(name: "nanopb", package: "nanopb"),
],
path: "FirebaseAnalyticsWrapper",
linkerSettings: [
.linkedLibrary("sqlite3"),
.linkedLibrary("c++"),
.linkedLibrary("z"),
.linkedFramework("StoreKit"),
]
),
.binaryTarget(
name: "FirebaseAnalytics",
url: "https://dl.google.com/firebase/ios/swiftpm/13.2.0/FirebaseAnalytics.zip",
checksum: "e916c5b1bf160b5c40a949e58261b13b5edc76c19f24b1eb2d675da1de63ad74"
),
.testTarget(
name: "AnalyticsSwiftUnit",
dependencies: ["FirebaseAnalyticsTarget"],
path: "FirebaseAnalytics/Tests/SwiftUnit"
),
.testTarget(
name: "AnalyticsObjCAPI",
dependencies: ["FirebaseAnalyticsTarget"],
path: "FirebaseAnalytics/Tests/ObjCAPI"
),
.target(
name: "FirebaseAnalyticsCoreTarget",
dependencies: [.target(name: "FirebaseAnalyticsCoreWrapper",
condition: .when(platforms: [.iOS, .macCatalyst, .macOS, .tvOS]))],
path: "SwiftPM-PlatformExclude/FirebaseAnalyticsCoreWrap"
),
.target(
name: "FirebaseAnalyticsCoreWrapper",
dependencies: [
.target(
name: "FirebaseAnalytics",
condition: .when(platforms: [.iOS, .macCatalyst, .macOS, .tvOS])
),
.product(name: "GoogleAppMeasurementCore",
package: "GoogleAppMeasurement",
condition: .when(platforms: [.iOS, .macCatalyst, .macOS, .tvOS])),
"FirebaseCore",
"FirebaseInstallations",
.product(name: "GULAppDelegateSwizzler", package: "GoogleUtilities"),
.product(name: "GULMethodSwizzler", package: "GoogleUtilities"),
.product(name: "GULNSData", package: "GoogleUtilities"),
.product(name: "GULNetwork", package: "GoogleUtilities"),
.product(name: "nanopb", package: "nanopb"),
],
path: "FirebaseAnalyticsCoreWrapper",
linkerSettings: [
.linkedLibrary("sqlite3"),
.linkedLibrary("c++"),
.linkedLibrary("z"),
.linkedFramework("StoreKit"),
]
),
.target(
name: "FirebaseAnalyticsIdentitySupportTarget",
dependencies: [
.target(
name: "FirebaseAnalytics",
condition: .when(platforms: [.iOS, .macCatalyst, .macOS, .tvOS])
),
.product(name: "GoogleAppMeasurementIdentitySupport",
package: "GoogleAppMeasurement",
condition: .when(platforms: [.iOS, .macCatalyst, .macOS, .tvOS])),
"FirebaseCore",
"FirebaseInstallations",
.product(name: "GULAppDelegateSwizzler", package: "GoogleUtilities"),
.product(name: "GULMethodSwizzler", package: "GoogleUtilities"),
.product(name: "GULNSData", package: "GoogleUtilities"),
.product(name: "GULNetwork", package: "GoogleUtilities"),
.product(name: "nanopb", package: "nanopb"),
],
path: "FirebaseAnalyticsIdentitySupportWrapper",
linkerSettings: [
.linkedLibrary("sqlite3"),
.linkedLibrary("c++"),
.linkedLibrary("z"),
.linkedFramework("StoreKit"),
]
),
.target(
name: "FirebaseAppDistributionTarget",
dependencies: [.target(name: "FirebaseAppDistribution",
condition: .when(platforms: [.iOS]))],
path: "SwiftPM-PlatformExclude/FirebaseAppDistributionWrap"
),
.target(
name: "FirebaseAppDistribution",
dependencies: [
"FirebaseCore",
"FirebaseInstallations",
.product(name: "GULAppDelegateSwizzler", package: "GoogleUtilities"),
.product(name: "GULUserDefaults", package: "GoogleUtilities"),
],
path: "FirebaseAppDistribution/Sources",
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("../../"),
]
),
.testTarget(
name: "AppDistributionUnit",
dependencies: ["FirebaseAppDistribution", .product(name: "OCMock", package: "ocmock")],
path: "FirebaseAppDistribution/Tests/Unit",
exclude: ["Swift/"],
resources: [.process("Resources")],
cSettings: [
.headerSearchPath("../../.."),
]
),
.testTarget(
name: "AppDistributionUnitSwift",
dependencies: ["FirebaseAppDistribution"],
path: "FirebaseAppDistribution/Tests/Unit/Swift",
cSettings: [
.headerSearchPath("../../../.."),
],
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
.target(
name: "FirebaseAuth",
dependencies: [
"FirebaseAppCheckInterop",
"FirebaseAuthInterop",
"FirebaseAuthInternal",
"FirebaseCore",
"FirebaseCoreExtension",
.product(name: "GULAppDelegateSwizzler", package: "GoogleUtilities"),
.product(name: "GULEnvironment", package: "GoogleUtilities"),
.product(name: "GTMSessionFetcherCore", package: "gtm-session-fetcher"),
],
path: "FirebaseAuth/Sources",
exclude: [
"ObjC", "Public",
],
resources: [.process("Resources/PrivacyInfo.xcprivacy")],
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
],
linkerSettings: [
.linkedFramework("Security"),
.linkedFramework("SafariServices", .when(platforms: [.iOS])),
]
),
.target(
name: "FirebaseAuthInternal",
dependencies: [
.product(name: "RecaptchaInterop", package: "interop-ios-for-google-sdks"),
],
path: "FirebaseAuth/Sources",
exclude: [
"Swift", "Resources",
],
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("../../"),
]
),
// Internal headers only for consuming from Swift.
.target(
name: "FirebaseAuthInterop",
path: "FirebaseAuth/Interop",
exclude: [
"CMakeLists.txt",
],
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("../../"),
]
),
.testTarget(
name: "AuthUnit",
dependencies: [
"FirebaseAuth",
],
path: "FirebaseAuth/Tests/Unit",
exclude: [
// TODO: The following tests run in CocoaPods only, until mixed language or separate target.
"ObjCAPITests.m",
"ObjCGlobalTests.m",
"FIROAuthProviderTests.m",
],
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
.target(
name: "FirebaseAuthCombineSwift",
dependencies: ["FirebaseAuth"],
path: "FirebaseCombineSwift/Sources/Auth",
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
.target(
name: "FirebaseFirestoreCombineSwift",
dependencies: [
.target(name: "FirebaseFirestoreTarget", condition: firestoreTraitDependencyCondition()),
],
path: "FirebaseCombineSwift/Sources/Firestore"
),
.target(
name: "FirebaseStorageCombineSwift",
dependencies: [
"FirebaseStorage",
],
path: "FirebaseCombineSwift/Sources/Storage"
),
firebaseCrashlyticsTarget(),
.target(
name: "FirebaseCrashlyticsSwift",
dependencies: ["FirebaseRemoteConfigInterop"],
path: "Crashlytics/Crashlytics/Rollouts"
),
.testTarget(
name: "FirebaseCrashlyticsSwiftUnit",
dependencies: ["FirebaseCrashlyticsSwift"],
path: "Crashlytics/UnitTestsSwift/",
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
.testTarget(
name: "FirebaseCrashlyticsUnit",
dependencies: ["FirebaseCrashlytics", .product(name: "OCMock", package: "ocmock")],
path: "Crashlytics/UnitTests",
resources: [
.copy("FIRCLSMachO/machO_data"),
.copy("Data"),
],
cSettings: [
.headerSearchPath("../.."),
.define("DISPLAY_VERSION", to: firebaseVersion),
.define("CLS_SDK_NAME", to: "Crashlytics iOS SDK", .when(platforms: [.iOS])),
.define(
"CLS_SDK_NAME",
to: "Crashlytics macOS SDK",
.when(platforms: [.macOS, .macCatalyst])
),
.define("CLS_SDK_NAME", to: "Crashlytics tvOS SDK", .when(platforms: [.tvOS])),
.define("CLS_SDK_NAME", to: "Crashlytics watchOS SDK", .when(platforms: [.watchOS])),
]
),
.target(
name: "FirebaseDatabaseInternal",
dependencies: [
"FirebaseAppCheckInterop",
"FirebaseCore",
"leveldb",
.product(name: "GULUserDefaults", package: "GoogleUtilities"),
],
path: "FirebaseDatabase/Sources",
exclude: [
"third_party/Wrap-leveldb/LICENSE",
"third_party/SocketRocket/LICENSE",
"third_party/FImmutableSortedDictionary/LICENSE",
"third_party/SocketRocket/aa2297808c225710e267afece4439c256f6efdb3",
],
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("../../"),
],
linkerSettings: [
.linkedFramework("CFNetwork"),
.linkedFramework("Security"),
.linkedFramework("SystemConfiguration", .when(platforms: [.iOS, .macOS, .tvOS])),
.linkedFramework("WatchKit", .when(platforms: [.watchOS])),
]
),
.testTarget(
name: "DatabaseUnit",
dependencies: [
"FirebaseDatabase",
"SharedTestUtilities",
.product(name: "OCMock", package: "ocmock"),
],
path: "FirebaseDatabase/Tests/",
exclude: [
// Disable Swift tests as mixed targets are not supported (Xcode 12.4).
"Unit/Swift",
"Integration/",
],
resources: [.process("Resources")],
cSettings: [
.headerSearchPath("../.."),
],
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
.testTarget(
name: "DatabaseUnitSwift",
dependencies: ["FirebaseDatabase"],
path: "FirebaseDatabase/Tests/Unit/Swift",
cSettings: [
.headerSearchPath("../.."),
],
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
.target(
name: "FirebaseDatabase",
dependencies: ["FirebaseDatabaseInternal", "FirebaseSharedSwift"],
path: "FirebaseDatabase/Swift/Sources"
),
.target(
name: "FirebaseSharedSwift",
path: "FirebaseSharedSwift/Sources",
exclude: [
"third_party/FirebaseDataEncoder/LICENSE",
"third_party/FirebaseDataEncoder/METADATA",
]
),
.testTarget(
name: "FirebaseSharedSwiftTests",
dependencies: ["FirebaseSharedSwift"],
path: "FirebaseSharedSwift/Tests/"
),
firestoreWrapperTarget(),
// MARK: - Firebase Functions
.target(
name: "FirebaseFunctions",
dependencies: [
"FirebaseAppCheckInterop",
"FirebaseAuthInterop",
"FirebaseCore",
"FirebaseCoreExtension",
"FirebaseMessagingInterop",
"FirebaseSharedSwift",
.product(name: "GTMSessionFetcherCore", package: "gtm-session-fetcher"),
],
path: "FirebaseFunctions/Sources"
),
.testTarget(
name: "FirebaseFunctionsUnit",
dependencies: ["FirebaseFunctions",
"FirebaseAppCheckInterop",
"FirebaseAuthInterop",
"FirebaseMessagingInterop",
"SharedTestUtilities"],
path: "FirebaseFunctions/Tests/Unit",
cSettings: [
.headerSearchPath("../../../"),
],
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
.testTarget(
name: "FirebaseFunctionsIntegration",
dependencies: ["FirebaseFunctions",
"SharedTestUtilities"],
path: "FirebaseFunctions/Tests/Integration"
),
.testTarget(
name: "FirebaseFunctionsObjCIntegration",
dependencies: ["FirebaseFunctions",
"SharedTestUtilities"],
path: "FirebaseFunctions/Tests/ObjCIntegration",
// See https://forums.swift.org/t/importing-swift-libraries-from-objective-c/56730
exclude: [
"ObjCPPAPITests.mm",
],
cSettings: [
.headerSearchPath("../../.."),
]
),
.target(
name: "FirebaseFunctionsCombineSwift",
dependencies: ["FirebaseFunctions"],
path: "FirebaseCombineSwift/Sources/Functions",
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
.testTarget(
name: "FunctionsCombineUnit",
dependencies: ["FirebaseFunctionsCombineSwift",
"SharedTestUtilities"],
path: "FirebaseFunctions/Tests/CombineUnit"
),
// MARK: - Firebase In App Messaging
.target(
name: "FirebaseInAppMessagingTarget",
dependencies: [
.target(name: "FirebaseInAppMessaging", condition: .when(platforms: [.iOS, .tvOS])),
],
path: "SwiftPM-PlatformExclude/FirebaseInAppMessagingWrap"
),
.target(
name: "FirebaseInAppMessagingInternal",
dependencies: [
"FirebaseCore",
"FirebaseInstallations",
"FirebaseABTesting",
.product(name: "GULEnvironment", package: "GoogleUtilities"),
.product(name: "GULUserDefaults", package: "GoogleUtilities"),
.product(name: "nanopb", package: "nanopb"),
.target(name: "FirebaseInAppMessaging_iOS", condition: .when(platforms: [.iOS])),
],
path: "FirebaseInAppMessaging/Sources",
exclude: [
"DefaultUI/CHANGELOG.md",
"DefaultUI/README.md",
],
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("../../"),
.define("PB_FIELD_32BIT", to: "1"),
.define("PB_NO_PACKED_STRUCTS", to: "1"),
.define("PB_ENABLE_MALLOC", to: "1"),
]
),
.target(
name: "FirebaseInAppMessaging_iOS",
path: "FirebaseInAppMessaging/iOS",
resources: [.process("Resources")]
),
.target(
name: "FirebaseInAppMessaging",
dependencies: ["FirebaseInAppMessagingInternal"],
path: "FirebaseInAppMessaging/Swift/Source",
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
.target(
name: "FirebaseInstallations",
dependencies: [
"FirebaseCore",
.product(name: "FBLPromises", package: "Promises"),
.product(name: "GULEnvironment", package: "GoogleUtilities"),
.product(name: "GULUserDefaults", package: "GoogleUtilities"),
],
path: "FirebaseInstallations/Source/Library",
resources: [.process("Resources/PrivacyInfo.xcprivacy")],
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("../../../"),
],
linkerSettings: [
.linkedFramework("Security"),
]
),
.target(
name: "FirebaseMessaging",
dependencies: [
"FirebaseCore",
"FirebaseInstallations",
.product(name: "GULAppDelegateSwizzler", package: "GoogleUtilities"),
.product(name: "GULEnvironment", package: "GoogleUtilities"),
.product(name: "GULReachability", package: "GoogleUtilities"),
.product(name: "GULUserDefaults", package: "GoogleUtilities"),
.product(name: "GoogleDataTransport", package: "GoogleDataTransport"),
.product(name: "nanopb", package: "nanopb"),
],
path: "FirebaseMessaging/Sources",
resources: [.process("Resources/PrivacyInfo.xcprivacy")],
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("../../"),
.define("PB_FIELD_32BIT", to: "1"),
.define("PB_NO_PACKED_STRUCTS", to: "1"),
.define("PB_ENABLE_MALLOC", to: "1"),
],
linkerSettings: [
.linkedFramework("SystemConfiguration", .when(platforms: [.iOS, .macOS, .tvOS])),
]
),
// Internal headers only for consuming from Swift.
.target(
name: "FirebaseMessagingInterop",
path: "FirebaseMessaging/Interop",
publicHeadersPath: ".",
cSettings: [
.headerSearchPath("../../"),
]
),
.testTarget(
name: "MessagingUnit",
dependencies: [
"FirebaseMessaging",
"SharedTestUtilities",
.product(name: "OCMock", package: "ocmock"),
],
path: "FirebaseMessaging/Tests/UnitTests",
cSettings: [
.headerSearchPath("../../.."),
]
),
.target(
name: "FirebasePerformanceTarget",
dependencies: [.target(name: "FirebasePerformance",
condition: .when(platforms: [.iOS, .tvOS, .visionOS]))],
path: "SwiftPM-PlatformExclude/FirebasePerformanceWrap"
),
.target(
name: "FirebasePerformance",
dependencies: [
"FirebaseCore",
"FirebaseInstallations",
// Performance depends on the Obj-C target of FirebaseRemoteConfig to
// avoid including Swift code from the `FirebaseRemoteConfig` target
// that is unneeded.
"FirebaseRemoteConfigInternal",
"FirebaseSessions",
.product(name: "GoogleDataTransport", package: "GoogleDataTransport"),
.product(name: "GULEnvironment", package: "GoogleUtilities"),
.product(name: "GULMethodSwizzler", package: "GoogleUtilities"),
.product(name: "GULUserDefaults", package: "GoogleUtilities"),
.product(name: "nanopb", package: "nanopb"),
],
path: "FirebasePerformance/Sources",
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("../../"),
.define("PB_FIELD_32BIT", to: "1"),
.define("PB_NO_PACKED_STRUCTS", to: "1"),
.define("PB_ENABLE_MALLOC", to: "1"),
.define("FIRPerformance_LIB_VERSION", to: firebaseVersion),
],
linkerSettings: [
.linkedFramework("MobileCoreServices", .when(platforms: [.iOS, .tvOS])),
.linkedFramework("QuartzCore", .when(platforms: [.iOS, .tvOS])),
]
),
.testTarget(
name: "PerformanceUnit",
dependencies: [
"FirebasePerformanceTarget",
"SharedTestUtilities",
"GCDWebServer",
.product(name: "OCMock", package: "ocmock"),
],
path: "FirebasePerformance/Tests/Unit",
resources: [
.process("FPRURLFilterTests-Info.plist"),
.process("Server/smallDownloadFile"),
.process("Server/bigDownloadFile"),
],
cSettings: [
.headerSearchPath("../../.."),
.define("PB_FIELD_32BIT", to: "1"),
.define("PB_NO_PACKED_STRUCTS", to: "1"),
.define("PB_ENABLE_MALLOC", to: "1"),
]
),
.target(
name: "SharedTestUtilities",
dependencies: ["FirebaseCore",
"FirebaseCoreExtension",
"FirebaseAppCheckInterop",
"FirebaseAuthInterop",
"FirebaseMessagingInterop",
"GoogleDataTransport",
.product(name: "OCMock", package: "ocmock")],
path: "SharedTestUtilities",
publicHeadersPath: "./",
cSettings: [
.headerSearchPath("../"),
]
),
// MARK: - Firebase Remote Config
.target(
name: "FirebaseRemoteConfigInternal",
dependencies: [
"FirebaseCore",
"FirebaseABTesting",
"FirebaseInstallations",
"FirebaseRemoteConfigInterop",
.product(name: "GULEnvironment", package: "GoogleUtilities"),
.product(name: "GULNSData", package: "GoogleUtilities"),
],
path: "FirebaseRemoteConfig/Sources",
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("../../"),
]
),
.testTarget(
name: "RemoteConfigUnit",
dependencies: ["FirebaseRemoteConfigInternal", .product(name: "OCMock", package: "ocmock")],
path: "FirebaseRemoteConfig/Tests/Unit",
exclude: [
// Need to be evaluated/ported to RC V2.
"RCNConfigAnalyticsTest.m",
"RCNConfigSettingsTest.m",
"RCNConfigTest.m",
"RCNRemoteConfig+FIRAppTest.m",
"RCNThrottlingTests.m",
],
resources: [
.process("SecondApp-GoogleService-Info.plist"),
.process("Defaults-testInfo.plist"),
.process("TestABTPayload.txt"),
],
cSettings: [
.headerSearchPath("../../.."),
]
),
.testTarget(
name: "RemoteConfigSwiftUnit",
dependencies: ["FirebaseRemoteConfigInternal"],
path: "FirebaseRemoteConfig/Tests/SwiftUnit",
cSettings: [
.headerSearchPath("../../.."),
]
),
.target(
name: "FirebaseRemoteConfig",
dependencies: [
"FirebaseRemoteConfigInternal",
"FirebaseSharedSwift",
],
path: "FirebaseRemoteConfig/Swift",
resources: [.process("Resources/PrivacyInfo.xcprivacy")],
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
.testTarget(
name: "RemoteConfigFakeConsole",
dependencies: ["FirebaseRemoteConfig",
"RemoteConfigFakeConsoleObjC"],
path: "FirebaseRemoteConfig/Tests/Swift",
exclude: [
"AccessToken.json",
"README.md",
"ObjC/",
],
resources: [
.process("Defaults-testInfo.plist"),
],
cSettings: [
.headerSearchPath("../../../"),
],
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
.target(
name: "RemoteConfigFakeConsoleObjC",
dependencies: [.product(name: "OCMock", package: "ocmock")],
path: "FirebaseRemoteConfig/Tests/Swift/ObjC",
publicHeadersPath: ".",
cSettings: [
.headerSearchPath("../../../../"),
]
),
// Internal headers only for consuming from other SDK.
.target(
name: "FirebaseRemoteConfigInterop",
path: "FirebaseRemoteConfig/Interop",
publicHeadersPath: ".",
cSettings: [
.headerSearchPath("../../"),
]
),
// MARK: - Firebase Sessions
.target(
name: "FirebaseSessions",
dependencies: [
"FirebaseCore",
"FirebaseInstallations",
"FirebaseCoreExtension",
"FirebaseSessionsObjC",
// The `FirebaseSessions` target transitively depends on nanopb via the internal
// `FirebaseSessionsObjC` target. Not explicitly depending on nanopb leads to
// undefined symbol errors in Tuist based SPM builds.
// See the conversations in
// - https://github.com/firebase/firebase-ios-sdk/issues/15276
// - https://github.com/firebase/firebase-ios-sdk/pull/15287
.product(name: "nanopb", package: "nanopb"),
.product(name: "GoogleDataTransport", package: "GoogleDataTransport"),
.product(name: "GULEnvironment", package: "GoogleUtilities"),
.product(name: "GULUserDefaults", package: "GoogleUtilities"),
],
path: "FirebaseSessions/Sources",
cSettings: [
.headerSearchPath(".."),
.define("DISPLAY_VERSION", to: firebaseVersion),
.define("PB_FIELD_32BIT", to: "1"),
.define("PB_NO_PACKED_STRUCTS", to: "1"),
.define("PB_ENABLE_MALLOC", to: "1"),
],
linkerSettings: [
.linkedFramework("Security"),
.linkedFramework(
"SystemConfiguration",
.when(platforms: [.iOS, .macCatalyst, .macOS, .tvOS])
),
]
),
// The Sessions SDK is Swift-first with Objective-C code to support
// nanopb. Because Swift Package Manager doesn't support mixed
// language targets, the ObjC code has been extracted out into
// a separate target.
.target(
name: "FirebaseSessionsObjC",
dependencies: [
"FirebaseCore",
"FirebaseCoreExtension",
.product(name: "GULEnvironment", package: "GoogleUtilities"),
.product(name: "nanopb", package: "nanopb"),
],
path: "FirebaseSessions",
exclude: [
"README.md",
"Sources/",
"Tests/",
"ProtoSupport/",
"generate_project.sh",
"generate_protos.sh",
"generate_testapp.sh",
],
publicHeadersPath: "SourcesObjC",
cSettings: [
.headerSearchPath(".."),
.define("DISPLAY_VERSION", to: firebaseVersion),
.define("PB_FIELD_32BIT", to: "1"),
.define("PB_NO_PACKED_STRUCTS", to: "1"),
.define("PB_ENABLE_MALLOC", to: "1"),
],
linkerSettings: [
.linkedFramework("Security"),
.linkedFramework(
"SystemConfiguration",
.when(platforms: [.iOS, .macCatalyst, .macOS, .tvOS])
),
]
),
.testTarget(
name: "FirebaseSessionsUnit",
dependencies: ["FirebaseSessions"],
path: "FirebaseSessions/Tests/Unit"
),
// MARK: - Firebase Storage
.target(
name: "FirebaseStorage",
dependencies: [
"FirebaseAppCheckInterop",
"FirebaseAuthInterop",
"FirebaseCore",
"FirebaseCoreExtension",
.product(name: "GTMSessionFetcherCore", package: "gtm-session-fetcher"),
.product(name: "GULEnvironment", package: "GoogleUtilities"),
],
path: "FirebaseStorage/Sources",
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
.testTarget(
name: "FirebaseStorageUnit",
dependencies: ["FirebaseStorage",
"SharedTestUtilities"],
path: "FirebaseStorage/Tests/Unit",
cSettings: [
.headerSearchPath("../../../"),
],
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
.testTarget(
name: "StorageObjCIntegration",
dependencies: ["FirebaseStorage"],
path: "FirebaseStorage/Tests/ObjCIntegration",
exclude: [
// See https://forums.swift.org/t/importing-swift-libraries-from-objective-c/56730
"FIRStorageIntegrationTests.m",
"ObjCPPAPITests.mm",
"Credentials.h",
],
cSettings: [
.headerSearchPath("../../.."),
]
),
.testTarget(
name: "swift-test",
dependencies: [
"Firebase",
"FirebaseAuth",
"FirebaseAppCheck",
"FirebaseABTesting",
"FirebaseAnalytics",
.target(name: "FirebaseAppDistribution",
condition: .when(platforms: [.iOS])),
"FirebaseAuthCombineSwift",
.target(name: "FirebaseFirestoreCombineSwift",
condition: firestoreTraitDependencyCondition()),
"FirebaseFunctionsCombineSwift",
"FirebaseStorageCombineSwift",
"FirebaseCrashlytics",
"FirebaseCore",
"FirebaseDatabase",
.target(name: "FirebaseFirestoreTarget",
condition: firestoreTraitDependencyCondition()),
"FirebaseFunctions",
.target(name: "FirebaseInAppMessaging",
condition: .when(platforms: [.iOS, .tvOS])),
"FirebaseInstallations",
"FirebaseMessaging",
.target(name: "FirebasePerformance",
condition: .when(platforms: [.iOS, .tvOS])),
"FirebaseRemoteConfig",
"FirebaseSessions",
"FirebaseStorage",
.product(name: "nanopb", package: "nanopb"),
],
path: "SwiftPMTests/swift-test",
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
.testTarget(
name: "analytics-import-test",
dependencies: [
"FirebaseAnalyticsWrapper",
"Firebase",
],
path: "SwiftPMTests/analytics-import-test",
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
.testTarget(
name: "objc-import-test",
dependencies: [
"Firebase",
"FirebaseAuth",
"FirebaseABTesting",
"FirebaseAppCheck",
.target(name: "FirebaseAppDistribution",
condition: .when(platforms: [.iOS])),
"FirebaseCrashlytics",
"FirebaseCore",
"FirebaseDatabase",
.target(name: "FirebaseFirestoreTarget",
condition: firestoreTraitDependencyCondition()),
"FirebaseFunctions",
.target(name: "FirebaseInAppMessaging",
condition: .when(platforms: [.iOS, .tvOS])),
"FirebaseInstallations",
"FirebaseMessaging",
.target(name: "FirebasePerformance",
condition: .when(platforms: [.iOS, .tvOS])),
"FirebaseRemoteConfig",
"FirebaseStorage",
],
path: "SwiftPMTests/objc-import-test",
cSettings: [.define("FIRESTORE_TRAIT_ENABLED", firestoreTraitBuildSettingCondition())]
),
.testTarget(
name: "version-test",
dependencies: [
"FirebaseCore",
],
path: "SwiftPMTests/version-test",
cSettings: [
.define("FIR_VERSION", to: firebaseVersion),
]
),
// MARK: - Firebase App Check
.target(name: "FirebaseAppCheck",
dependencies: [
"FirebaseAppCheckInterop",
"FirebaseCore",
.product(name: "AppCheckCore", package: "app-check"),
.product(name: "AppCheckRecaptchaProvider", package: "app-check"),
.product(name: "GULEnvironment", package: "GoogleUtilities"),
.product(name: "GULUserDefaults", package: "GoogleUtilities"),
],
path: "FirebaseAppCheck/Sources",
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("../.."),
],
linkerSettings: [
.linkedFramework(
"DeviceCheck",
.when(platforms: [.iOS, .macCatalyst, .macOS, .tvOS])
),
]),
// Internal headers only for consuming from Swift.
.target(
name: "FirebaseAppCheckInterop",
path: "FirebaseAppCheck/Interop",
exclude: [
"CMakeLists.txt",
],
publicHeadersPath: "Public",
cSettings: [
.headerSearchPath("../../"),
]
),
.testTarget(
name: "FirebaseAppCheckUnit",
dependencies: [
"FirebaseAppCheck",
"SharedTestUtilities",
.product(name: "OCMock", package: "ocmock"),
],
path: "FirebaseAppCheck/Tests/Unit",
exclude: [
// Swift tests are in the target `FirebaseAppCheckUnitSwift` since mixed language targets
// are not supported (as of Xcode 15.0).
"Swift",
],
cSettings: [
.headerSearchPath("../../.."),
]
),
.testTarget(
name: "FirebaseAppCheckUnitSwift",
dependencies: [
"FirebaseAppCheck",
"FirebaseCoreExtension",
"SharedTestUtilities",
.product(name: "AppCheckCore", package: "app-check"),
],
path: "FirebaseAppCheck/Tests/Unit/Swift",
cSettings: [
.headerSearchPath("../../../"),
],
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
// MARK: Testing support
.target(
name: "FirebaseFirestoreTestingSupport",
dependencies: ["FirebaseFirestoreTarget"],
path: "FirebaseTestingSupport/Firestore/Sources",
publicHeadersPath: "./",
cSettings: [
.headerSearchPath("../../.."),
.headerSearchPath("../../../Firestore/Source/Public/FirebaseFirestore"),
]
),
.testTarget(
name: "FirestoreTestingSupportTests",
dependencies: ["FirebaseFirestoreTestingSupport"],
path: "FirebaseTestingSupport/Firestore/Tests",
cSettings: [
.headerSearchPath("../../.."),
]
),
.testTarget(
name: "FirebaseFirestoreTests",
dependencies: [
"Firebase",
"FirebaseCore",
"FirebaseFirestoreTarget",
],
path: "Firestore/Swift/Tests/Unit",
cSettings: [
.headerSearchPath("../../../"),
]
),
]
targets.append(contentsOf: firestoreTargets())
#if compiler(>=6.4) && canImport(FoundationModels)
targets.append(contentsOf: geminiLanguageModelTargets())
#endif
return targets
}
// MARK: - Helper Functions
func firebaseCrashlyticsTarget() -> Target {
var cSettings: [CSetting] = [
.headerSearchPath(".."),
.define("DISPLAY_VERSION", to: firebaseVersion),
.define("CLS_SDK_NAME", to: "Crashlytics iOS SDK", .when(platforms: [.iOS])),
.define(
"CLS_SDK_NAME", to: "Crashlytics macOS SDK",
.when(platforms: [.macOS, .macCatalyst])
),
.define("CLS_SDK_NAME", to: "Crashlytics tvOS SDK", .when(platforms: [.tvOS])),
.define("CLS_SDK_NAME", to: "Crashlytics watchOS SDK", .when(platforms: [.watchOS])),
.define("PB_FIELD_32BIT", to: "1"),
.define("PB_NO_PACKED_STRUCTS", to: "1"),
.define("PB_ENABLE_MALLOC", to: "1"),
]
if Context.environment["FIREBASE_IS_NIGHTLY_TESTING"] != nil {
cSettings += [.define("FIREBASE_IS_NIGHTLY_TESTING", to: "1")]
}
return .target(
name: "FirebaseCrashlytics",
dependencies: [
"FirebaseCore",
"FirebaseInstallations",
"FirebaseSessions",
"FirebaseRemoteConfigInterop",
"FirebaseCrashlyticsSwift",
.product(name: "GoogleDataTransport", package: "GoogleDataTransport"),
.product(name: "GULEnvironment", package: "GoogleUtilities"),
.product(name: "FBLPromises", package: "Promises"),
.product(name: "nanopb", package: "nanopb"),
],
path: "Crashlytics",
exclude: [
"run",
"CHANGELOG.md",
"LICENSE",
"README.md",
"ProtoSupport",
"UnitTests",
"generate_project.sh",
"upload-symbols",
"CrashlyticsInputFiles.xcfilelist",
"third_party/libunwind/LICENSE",
"Crashlytics/Rollouts",
],
sources: [
"Crashlytics",
"Protogen",
"Shared",
"third_party/libunwind/dwarf.h",
],
resources: [.process("Resources/PrivacyInfo.xcprivacy")],
publicHeadersPath: "Crashlytics/Public",
cSettings: cSettings,
linkerSettings: [
.linkedFramework("Security"),
.linkedFramework("SystemConfiguration", .when(platforms: [.iOS, .macOS, .tvOS])),
]
)
}
func googleAppMeasurementDependency() -> Package.Dependency {
let appMeasurementURL = "https://github.com/google/GoogleAppMeasurement.git"
// Point SPM CI to the tip of main of https://github.com/google/GoogleAppMeasurement so that the
// release process can defer publishing the GoogleAppMeasurement tag until after testing.
if Context.environment["FIREBASECI_USE_LATEST_GOOGLEAPPMEASUREMENT"] != nil {
return .package(url: appMeasurementURL, branch: "main")
}
return .package(url: appMeasurementURL, "13.2.0" ..< "13.3.0")
}
func abseilDependency() -> Package.Dependency {
let packageInfo: (url: String, range: Range<Version>)
// If building Firestore from source, abseil will need to be built as source
// as the headers in the binary version of abseil are unusable.
if shouldUseSourceFirestore {
packageInfo = (
"https://github.com/firebase/abseil-cpp-SwiftPM.git",
"0.20250512.1" ..< "0.20250513.0"
)
} else {
packageInfo = (
"https://github.com/google/abseil-cpp-binary.git",
"1.2025051202.0" ..< "1.2025051300.0"
)
}
return .package(url: packageInfo.url, packageInfo.range)
}
func grpcDependency() -> Package.Dependency {
let packageInfo: (url: String, range: Range<Version>)
// If building Firestore from source, abseil will need to be built as source
// as the headers in the binary version of abseil are unusable.
if shouldUseSourceFirestore {
packageInfo = ("https://github.com/grpc/grpc-ios.git", "1.83.1" ..< "1.84.0")
} else {
packageInfo = ("https://github.com/google/grpc-binary.git", "1.83.1" ..< "1.84.0")
}
return .package(url: packageInfo.url, packageInfo.range)
}
func firestoreWrapperTarget() -> Target {
if shouldUseSourceFirestore {
return .target(
name: "FirebaseFirestoreTarget",
dependencies: [
.target(
name: "FirebaseFirestore",
condition: firestoreTraitDependencyCondition(
platforms: [.iOS, .tvOS, .macOS, .visionOS, .macCatalyst]
)
),
],
path: "SwiftPM-PlatformExclude/FirebaseFirestoreWrap",
cSettings: [.define("FIRESTORE_TRAIT_ENABLED", firestoreTraitBuildSettingCondition())]
)
}
return .target(
name: "FirebaseFirestoreTarget",
dependencies: [.target(
name: "FirebaseFirestore",
condition: firestoreTraitDependencyCondition(platforms: [.iOS, .tvOS, .macOS, .macCatalyst])
)],
path: "SwiftPM-PlatformExclude/FirebaseFirestoreWrap",
cSettings: [
.define("FIREBASE_BINARY_FIRESTORE", to: "1"),
.define("FIRESTORE_TRAIT_ENABLED", firestoreTraitBuildSettingCondition()),
]
)
}
func firestoreTargets() -> [Target] {
if shouldUseSourceFirestore {
return [
.target(
name: "FirebaseFirestoreInternalWrapper",
dependencies: [
"FirebaseAppCheckInterop",
"FirebaseCore",
"leveldb",
.product(name: "nanopb", package: "nanopb"),
.product(name: "abseil", package: "abseil-cpp-SwiftPM",
condition: firestoreTraitDependencyCondition()),
.product(name: "gRPC-cpp", package: "grpc-ios",
condition: firestoreTraitDependencyCondition()),
],
path: "Firestore",
exclude: [
"CHANGELOG.md",
"CMakeLists.txt",
"Example/",
"LICENSE",
"Protos/CMakeLists.txt",
"Protos/Podfile",
"Protos/README.md",
"Protos/build_protos.py",
"Protos/cpp/",
"Protos/lib/",
"Protos/nanopb_cpp_generator.py",
"Protos/protos/",
"README.md",
"Source/CMakeLists.txt",
"Source/Resources/",
"Swift/",
"core/CMakeLists.txt",
"core/src/util/config_detected.h.in",
"core/test/",
"fuzzing/",
"test.sh",
// Swift PM doesn't recognize hpp files, so we're relying on search paths
// to find third_party/nlohmann_json/json.hpp.
"third_party/",
// Exclude alternate implementations for other platforms
"core/src/remote/connectivity_monitor_noop.cc",
"core/src/util/filesystem_win.cc",
"core/src/util/log_stdio.cc",
"core/src/util/secure_random_openssl.cc",
],
sources: [
"Source/",
"Protos/nanopb/",
"core/include/",
"core/src",
],
publicHeadersPath: "Source/Public",
cSettings: [
.headerSearchPath("../"),
.headerSearchPath("Source/Public/FirebaseFirestore"),
.headerSearchPath("Protos/nanopb"),
.headerSearchPath("third_party/re2"),
.define("PB_FIELD_32BIT", to: "1"),
.define("PB_NO_PACKED_STRUCTS", to: "1"),
.define("PB_ENABLE_MALLOC", to: "1"),
.define("FIRFirestore_VERSION", to: firebaseVersion),
],
linkerSettings: [
.linkedFramework(
"SystemConfiguration",
.when(platforms: [.iOS, .macOS, .tvOS, .visionOS])
),
.linkedFramework("UIKit", .when(platforms: [.iOS, .tvOS, .visionOS])),
.linkedFramework("Network"),
.linkedLibrary("c++"),
]
),
.target(
name: "FirebaseFirestore",
dependencies: [
"FirebaseCore",
"FirebaseCoreExtension",
"FirebaseFirestoreInternalWrapper",
"FirebaseSharedSwift",
],
path: "Firestore",
exclude: [
"CHANGELOG.md",
"CMakeLists.txt",
"Example/",
"LICENSE",
"Protos/",
"README.md",
"Source/",
"Swift/Source/Resources/",
"core/",
"fuzzing/",
"test.sh",
"Swift/CHANGELOG.md",
"Swift/Tests/",
"third_party/nlohmann_json",
],
sources: [
"Swift/Source/",
],
resources: [.process("Source/Resources/PrivacyInfo.xcprivacy")],
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
]
),
]
}
let firestoreInternalTarget: Target = {
if Context.environment["FIREBASECI_USE_LOCAL_FIRESTORE_ZIP"] != nil {
// This is set when running `scripts/check_firestore_symbols.sh`.
return .binaryTarget(
name: "FirebaseFirestoreInternal",
// The `xcframework` should be moved to the root of the repo.
path: "FirebaseFirestoreInternal.xcframework"
)
} else {
return .binaryTarget(
name: "FirebaseFirestoreInternal",
url: "https://dl.google.com/firebase/ios/bin/firestore/13.2.0/pre_rc0/FirebaseFirestoreInternal.zip",
checksum: "17f395f923188a3b565836fb80e7acfec20e1077099a80f74884035ca08d53d6"
)
}
}()
return [
.target(
name: "FirebaseFirestore",
dependencies: [
.target(
name: "FirebaseFirestoreInternalWrapper",
condition: firestoreTraitDependencyCondition(platforms: [
.iOS, .macCatalyst, .tvOS, .macOS,
])
),
.product(
name: "abseil",
package: "abseil-cpp-binary",
condition: firestoreTraitDependencyCondition(platforms: [
.iOS, .macCatalyst, .tvOS, .macOS,
])
),
.product(
name: "gRPC-C++",
package: "grpc-binary",
condition: firestoreTraitDependencyCondition(platforms: [
.iOS, .macCatalyst, .tvOS, .macOS,
])
),
.product(name: "nanopb", package: "nanopb"),
"FirebaseAppCheckInterop",
"FirebaseCore",
"FirebaseCoreExtension",
"leveldb",
"FirebaseSharedSwift",
],
path: "Firestore/Swift/Source",
resources: [.process("Resources/PrivacyInfo.xcprivacy")],
swiftSettings: [
.swiftLanguageMode(SwiftLanguageMode.v5),
],
linkerSettings: [
.linkedFramework("SystemConfiguration", .when(platforms: [.iOS, .macOS, .tvOS])),
.linkedFramework("UIKit", .when(platforms: [.iOS, .tvOS])),
.linkedFramework("Network"),
.linkedLibrary("c++"),
]
),
.target(
name: "FirebaseFirestoreInternalWrapper",
dependencies: [.target(
name: "FirebaseFirestoreInternal",
condition: firestoreTraitDependencyCondition(platforms: [
.iOS, .macCatalyst, .tvOS, .macOS,
])
)],
path: "FirebaseFirestoreInternal",
publicHeadersPath: "."
),
firestoreInternalTarget,
]
}
/// Returns the condition for a dependency to link only when the "Firestore" trait is on.
///
/// When `isFirestoreTraitConditionSupported` is `false` (Xcode 26.2), the trait is ignored and
/// only `platforms` is checked.
///
/// - Parameter platforms: The platforms the dependency applies to, or `nil` for all platforms.
/// - Returns: The dependency condition, or `nil`, which means the dependency is always linked.
func firestoreTraitDependencyCondition(platforms: [Platform]? = nil)
-> TargetDependencyCondition? {
guard isFirestoreTraitConditionSupported else {
guard let platforms else { return nil }
return .when(platforms: platforms)
}
guard let platforms else {
return .when(traits: [firestoreTraitName])
}
return .when(platforms: platforms, traits: [firestoreTraitName])
}
/// Returns the condition for a build setting to apply only when the "Firestore" trait is on.
///
/// - Returns: `.when(traits: ["Firestore"])`, or `nil` if `isFirestoreTraitConditionSupported` is
/// `false` (Xcode 26.2). A `nil` condition means the setting always applies.
func firestoreTraitBuildSettingCondition() -> BuildSettingCondition? {
guard isFirestoreTraitConditionSupported else { return nil }
return .when(traits: [firestoreTraitName])
}
func firebaseAILogicDependencies() -> [Target.Dependency] {
var dependencies: [Target.Dependency] = [
// Direct dependency on AppCheck for automatic token acquisition and
// management.
"FirebaseAppCheck",
// Despite the direct dependency on App Check, the AI Logic SDK still
// uses AppCheck through the interop.
"FirebaseAppCheckInterop",
"FirebaseAuthInterop",
"FirebaseCore",
"FirebaseCoreExtension",
]
#if compiler(>=6.4) && canImport(FoundationModels)
dependencies.append("GeminiLanguageModel")
#endif // compiler(>=6.4) && canImport(FoundationModels)
return dependencies
}
#if compiler(>=6.4) && canImport(FoundationModels)
func geminiLanguageModelTargets() -> [Target] {
let swiftSettings: [SwiftSetting] = [
.enableUpcomingFeature("ExistentialAny"),
.enableUpcomingFeature("InternalImportsByDefault"),
.enableUpcomingFeature("MemberImportVisibility"),
.swiftLanguageMode(.v6),
]
return [
.target(
name: "GeminiLanguageModel",
dependencies: [
"GeminiAPIClient",
"GeminiAPIDataModels",
],
path: "GeminiLanguageModel/Sources/GeminiLanguageModel",
swiftSettings: swiftSettings
),
.testTarget(
name: "GeminiLanguageModelTests",
dependencies: [
"GeminiLanguageModel",
"GeminiTestUtilities",
],
path: "GeminiLanguageModel/Tests/GeminiLanguageModelTests",
exclude: [
"IntegrationTests/README.md",
"README.md",
],
swiftSettings: swiftSettings
),
.target(
name: "GeminiAPIClient",
dependencies: [
"GeminiAPIDataModels",
],
path: "GeminiLanguageModel/Sources/GeminiAPIClient",
swiftSettings: swiftSettings
),
.testTarget(
name: "GeminiAPIClientTests",
dependencies: [
"GeminiAPIClient",
"GeminiTestUtilities",
],
path: "GeminiLanguageModel/Tests/GeminiAPIClientTests",
swiftSettings: swiftSettings
),
.target(
name: "GeminiAPIDataModels",
path: "GeminiLanguageModel/Sources/GeminiAPIDataModels",
swiftSettings: [
.enableUpcomingFeature("ExistentialAny"),
.enableUpcomingFeature("MemberImportVisibility"),
.swiftLanguageMode(.v6),
]
),
.target(
name: "GeminiTestUtilities",
path: "GeminiLanguageModel/Tests/GeminiTestUtilities",
exclude: ["README.md"],
swiftSettings: swiftSettings,
),
]
}
#endif // compiler(>=6.4) && canImport(FoundationModels)
func appCheckDependency() -> Package.Dependency {
let appCheckURL = "https://github.com/google/app-check.git"
if let localPath = Context.environment["FIREBASE_APP_CHECK_LOCAL_PATH"] {
// Pin the package name so a checkout in a directory not named `app-check` still resolves.
return .package(name: "app-check", path: localPath)
}
if let branch = Context.environment["FIREBASE_APP_CHECK_BRANCH"] {
return .package(url: appCheckURL, branch: branch)
}
// Point SPM CI to the tip of main of https://github.com/google/app-check until 12.1.0 is tagged.
if Context.environment["FIREBASECI_USE_LATEST_GOOGLEAPPMEASUREMENT"] != nil {
return .package(url: appCheckURL, branch: "main")
}
return .package(url: appCheckURL, "12.1.0" ..< "13.0.0")
}