diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..e49cb52b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# Preserve byte-for-byte upstream files checked against the official archive. +source/Firebase/native/UPSTREAM-NOTICES.txt -text whitespace=-trailing-space +tests/fixtures/firebase13/13.1.1/METADATA.md -text whitespace=-trailing-space diff --git a/.github/workflows/firebase-release.yml b/.github/workflows/firebase-release.yml index 060994c0..7faf3bbe 100644 --- a/.github/workflows/firebase-release.yml +++ b/.github/workflows/firebase-release.yml @@ -283,7 +283,7 @@ jobs: - name: Export Sign-In and integration dependency closures run: | dotnet tool run dotnet-cake -- signin_publish.cake - dotnet tool run dotnet-cake -- --target=firebase-publish-metadata + dotnet tool run dotnet-cake -- --target=firebase-publish-metadata --producer=legacy - name: Release tooling tests run: python3 -m unittest discover -s tests/firebase-release -v - name: Plan Sign-In validation and release @@ -376,11 +376,11 @@ jobs: # GitHub Packages reads need a repository token; fork pull requests use nuget.org alone. GH_TOKEN: ${{ (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.token || '' }} run: | - dotnet tool run dotnet-cake -- --target=firebase-publish-metadata + dotnet tool run dotnet-cake -- --target=firebase-publish-metadata --producer=legacy python3 scripts/signin-release/integration_feed.py --fetch-published - name: Build Firebase 12 integration fixtures only if: steps.fixtures.outputs.source != 'published' - run: dotnet tool run dotnet-cake -- --target=nuget --names=Firebase.Auth,Firebase.Analytics,Firebase.CloudFirestore + run: dotnet tool run dotnet-cake -- --target=nuget --names=Firebase.Auth,Firebase.Analytics,Firebase.CloudFirestore --producer=legacy - name: Stage Firebase 12 integration feed run: python3 scripts/signin-release/integration_feed.py - name: Combined Sign-In and Firebase 12 consumers diff --git a/.github/workflows/firebase13-xbd.yml b/.github/workflows/firebase13-xbd.yml new file mode 100644 index 00000000..6544cea7 --- /dev/null +++ b/.github/workflows/firebase13-xbd.yml @@ -0,0 +1,186 @@ +name: Firebase 13 XBD experiment + +on: + pull_request: + paths: + - 'source/Firebase/**' + - 'source/Google/**' + - 'tools/firebase13/**' + - 'tools/legacy/**' + - 'tests/legacy-producer/**' + - 'tests/fixtures/legacy-producer/**' + - 'legacy.cake' + - 'legacy_production.cake' + - 'eng/legacy-producer.json' + - 'signin_publish.cake' + - '.github/workflows/firebase-release.yml' + - 'tests/firebase13/**' + - 'tests/fixtures/firebase13/**' + - 'firebase13.cake' + - 'firebase13_common.cake' + - 'common.cake' + - 'poco.cake' + - '.config/dotnet-tools.json' + - 'docs/Firebase/NuGet/**' + - 'docs/Google/NuGet/**' + - 'build.cake' + - 'components.cake' + - 'firebase_release.cake' + - 'global.json' + - 'Directory.Build.props' + - 'source/AssemblyInfo.cs' + - 'scripts/FirebaseBindingAudit/**' + - 'scripts/FirebaseBindingAudit.Tests/**' + - 'scripts/firebase-binding-audit*.json' + - 'tests/crashlytics/**' + - 'tools/e2e/select-simulator.sh' + - '.github/workflows/firebase13-xbd.yml' + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: firebase13-xbd-${{ github.ref }} + cancel-in-progress: true + +jobs: + schema: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + - uses: actions/setup-dotnet@v5 + with: + global-json-file: global.json + - run: python3 -m unittest discover -s tests/firebase13 -v + - run: python3 tools/firebase13/native.py native-assets-validate + - name: Locked legacy producer and published-fingerprint regressions + run: python3 -m unittest discover -s tests/legacy-producer -v + - name: Binding audit and fingerprint regression tests + env: + MSBuildEnableWorkloadResolver: false + run: dotnet test scripts/FirebaseBindingAudit.Tests + - name: Crashlytics upload integrity and stock XBD ZIP cache tests + run: python3 -m unittest discover -s tests/crashlytics -v + + native: + # Trusted same-repository PRs validate the full experiment, including follow-up branches. + # Fork pull requests cannot schedule code on the self-hosted runner. + if: >- + github.event_name == 'workflow_dispatch' || + (github.event_name == 'pull_request' && + github.event.pull_request.head.repo.full_name == github.repository) + needs: schema + runs-on: [self-hosted, macOS, ARM64, xcode-27.1] + timeout-minutes: 180 + env: + E2E_SIMULATOR_NAME: GoogleApisCI-iPhone + steps: + - uses: actions/checkout@v5 + - run: tools/ci/select-xcode.sh '27.1' + - uses: actions/setup-dotnet@v5 + with: + global-json-file: global.json + - name: Install a failing pod sentinel + run: | + mkdir -p "$RUNNER_TEMP/firebase13-tools" + cat > "$RUNNER_TEMP/firebase13-tools/pod" <<'EOF' + #!/bin/sh + echo 'Unexpected CocoaPods invocation' >&2 + exit 97 + EOF + chmod +x "$RUNNER_TEMP/firebase13-tools/pod" + echo "$RUNNER_TEMP/firebase13-tools" >> "$GITHUB_PATH" + - name: Acquire, validate and pack exact Firebase closure + run: python3 tools/firebase13/native.py nuget + - name: Audit all Firebase Objective-C bindings + run: | + dotnet tool install Sharpie.Bind.Tool --version 26.3.0.11 --tool-path "$RUNNER_TEMP/firebase13-sharpie" + python3 tools/firebase13/audit.py --cache "$HOME/Library/Caches/XamarinBuildDownload" --sharpie-path "$RUNNER_TEMP/firebase13-sharpie/sharpie" + - name: Verify actual native binding registrations + run: python3 tools/firebase13/check_symbols.py --cache "$HOME/Library/Caches/XamarinBuildDownload" + - name: Core cold-cache and offline matrix + run: python3 tools/firebase13/consumers.py --scope core + - name: Combined Analytics Auth Firestore cold-cache and offline matrix + run: python3 tools/firebase13/consumers.py --scope combined + - name: Analytics without advertising-ID support + run: python3 tools/firebase13/consumers.py --scope combined --without-ad-id --quick + - name: All Firebase products cold-cache and offline matrix + run: python3 tools/firebase13/consumers.py --scope all + - uses: actions/upload-artifact@v7 + if: always() + with: + name: firebase13-xbd-experimental-validation + path: | + output/firebase13/*.nupkg + output/firebase13-results/* + output/firebase13-api-audit/** + retention-days: 14 + + legacy-signin: + # This validates package production/consumption only; it cannot publish or approve deployment. + if: >- + github.event_name == 'workflow_dispatch' || + (github.event_name == 'pull_request' && + github.event.pull_request.head.repo.full_name == github.repository) + needs: schema + runs-on: [self-hosted, macOS, ARM64, xcode-27.1] + timeout-minutes: 180 + permissions: + contents: read + packages: read + env: + BUILD_COMMIT: ${{ github.sha }} + BUILD_NUMBER: ${{ github.run_number }} + E2E_SIMULATOR_NAME: GoogleApisCI-iPhone + GH_TOKEN: ${{ github.token }} + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 + - run: tools/ci/select-xcode.sh '27.1' + - uses: actions/setup-dotnet@v5 + with: + global-json-file: global.json + - run: dotnet tool restore + - name: Install pinned legacy CocoaPods runtime + run: | + pin=$(python3 -c 'import json; print(json.load(open("eng/signin-release.json"))["nativeBuild"]["cocoapods"])') + export GEM_HOME="$RUNNER_TEMP/legacy-cocoapods-$pin" + gem install cocoapods --version "$pin" --no-document + echo "GEM_HOME=$GEM_HOME" >> "$GITHUB_ENV" + echo "$GEM_HOME/bin" >> "$GITHUB_PATH" + - name: Export unchanged Sign-In baseline and plan validation + run: | + dotnet tool run dotnet-cake -- signin_publish.cake + dotnet tool run dotnet-cake -- --target=firebase-publish-metadata --producer=legacy + python3 scripts/firebase-release/release.py --channel signin plan --manual --online + - name: Original Sign-In production command + run: dotnet tool run dotnet-cake -- --target=nuget --names=Google.SignIn + - name: Inspect packed native delivery and exact CocoaPods resolution + run: | + python3 scripts/firebase-release/release.py --channel signin prepare --online + python3 scripts/signin-release/validate.py + - name: Standalone and transitive offline consumers + run: python3 scripts/signin-release/consumers.py + - name: Acquire matching Firebase 12 integration fixtures + id: fixtures + run: python3 scripts/signin-release/integration_feed.py --fetch-published + - name: Produce missing fixtures with the isolated legacy baseline + if: steps.fixtures.outputs.source != 'published' + run: dotnet tool run dotnet-cake -- --target=nuget --names=Firebase.Auth,Firebase.Analytics,Firebase.CloudFirestore --producer=legacy + - name: Combined Sign-In and Firebase 12 offline consumers + run: | + python3 scripts/signin-release/integration_feed.py + python3 scripts/signin-release/consumers.py --feed output/signin-combined --combined + - uses: actions/upload-artifact@v7 + if: always() + with: + name: firebase13-legacy-signin-validation + path: | + output/signin-candidate + output/signin-resolution + output/signin-results + output/signin-plan.json + output/signin-metadata.json + retention-days: 14 diff --git a/.gitignore b/.gitignore index eff793ac..129df583 100644 --- a/.gitignore +++ b/.gitignore @@ -28,3 +28,10 @@ artifacts *.user GoogleService-Info.plist !tests/E2E/Firebase.Foundation/FirebaseFoundationE2E/GoogleService-Info.plist + +!tools/firebase13/ + +__pycache__/ +*.pyc + +!tools/legacy/ diff --git a/build.cake b/build.cake index eefdb4e2..d80a73b2 100644 --- a/build.cake +++ b/build.cake @@ -1,3 +1,4 @@ +#load "legacy_production.cake" #load "poco.cake" #load "components.cake" #load "common.cake" @@ -281,4 +282,9 @@ Teardown (context => Information ("{0}", a); }); -RunTarget (TARGET); +if (new [] { "externals", "libs", "nuget", "build", "ci" }.Contains(TARGET)) + RunLegacyProductionCommand("build", TARGET, NAMES, Argument("producer", "auto")); +else if (TARGET == "firebase-publish-metadata" && Argument("producer", "auto") == "legacy") + RunLegacyProductionCommand("metadata", "", "", "legacy", "firebase", Argument("metadata-output", "output/firebase-metadata.json")); +else + RunTarget (TARGET); diff --git a/components.cake b/components.cake index 7613c379..a8589803 100644 --- a/components.cake +++ b/components.cake @@ -1,20 +1,20 @@ // Firebase artifacts available to be built. These artifacts generate NuGets. -Artifact FIREBASE_AB_TESTING_ARTIFACT = new Artifact ("Firebase.ABTesting", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "ABTesting"); -Artifact FIREBASE_ANALYTICS_ARTIFACT = new Artifact ("Firebase.Analytics", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "Analytics"); -Artifact FIREBASE_AUTH_ARTIFACT = new Artifact ("Firebase.Auth", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "Auth"); -Artifact FIREBASE_CLOUD_FIRESTORE_ARTIFACT = new Artifact ("Firebase.CloudFirestore", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "CloudFirestore"); -Artifact FIREBASE_CLOUD_FUNCTIONS_ARTIFACT = new Artifact ("Firebase.CloudFunctions", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "CloudFunctions"); -Artifact FIREBASE_CLOUD_MESSAGING_ARTIFACT = new Artifact ("Firebase.CloudMessaging", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "CloudMessaging"); -Artifact FIREBASE_CORE_ARTIFACT = new Artifact ("Firebase.Core", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "Core"); -Artifact FIREBASE_CRASHLYTICS_ARTIFACT = new Artifact ("Firebase.Crashlytics", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "Crashlytics"); -Artifact FIREBASE_DATABASE_ARTIFACT = new Artifact ("Firebase.Database", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "Database"); -Artifact FIREBASE_IN_APP_MESSAGING_ARTIFACT = new Artifact ("Firebase.InAppMessaging", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "InAppMessaging"); -Artifact FIREBASE_INSTALLATIONS_ARTIFACT = new Artifact ("Firebase.Installations", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "Installations"); -Artifact FIREBASE_PERFORMANCE_MONITORING_ARTIFACT = new Artifact ("Firebase.PerformanceMonitoring", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "PerformanceMonitoring"); -Artifact FIREBASE_REMOTE_CONFIG_ARTIFACT = new Artifact ("Firebase.RemoteConfig", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "RemoteConfig"); -Artifact FIREBASE_STORAGE_ARTIFACT = new Artifact ("Firebase.Storage", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "Storage"); -Artifact FIREBASE_APP_DISTRIBUTION_ARTIFACT = new Artifact ("Firebase.AppDistribution", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "AppDistribution"); -Artifact FIREBASE_APP_CHECK_ARTIFACT = new Artifact ("Firebase.AppCheck", "12.19.3", "15.0", ComponentGroup.Firebase, csprojName: "AppCheck"); +Artifact FIREBASE_AB_TESTING_ARTIFACT = new Artifact ("Firebase.ABTesting", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "ABTesting"); +Artifact FIREBASE_ANALYTICS_ARTIFACT = new Artifact ("Firebase.Analytics", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "Analytics"); +Artifact FIREBASE_AUTH_ARTIFACT = new Artifact ("Firebase.Auth", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "Auth"); +Artifact FIREBASE_CLOUD_FIRESTORE_ARTIFACT = new Artifact ("Firebase.CloudFirestore", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "CloudFirestore"); +Artifact FIREBASE_CLOUD_FUNCTIONS_ARTIFACT = new Artifact ("Firebase.CloudFunctions", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "CloudFunctions"); +Artifact FIREBASE_CLOUD_MESSAGING_ARTIFACT = new Artifact ("Firebase.CloudMessaging", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "CloudMessaging"); +Artifact FIREBASE_CORE_ARTIFACT = new Artifact ("Firebase.Core", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "Core"); +Artifact FIREBASE_CRASHLYTICS_ARTIFACT = new Artifact ("Firebase.Crashlytics", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "Crashlytics"); +Artifact FIREBASE_DATABASE_ARTIFACT = new Artifact ("Firebase.Database", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "Database"); +Artifact FIREBASE_IN_APP_MESSAGING_ARTIFACT = new Artifact ("Firebase.InAppMessaging", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "InAppMessaging"); +Artifact FIREBASE_INSTALLATIONS_ARTIFACT = new Artifact ("Firebase.Installations", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "Installations"); +Artifact FIREBASE_PERFORMANCE_MONITORING_ARTIFACT = new Artifact ("Firebase.PerformanceMonitoring", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "PerformanceMonitoring"); +Artifact FIREBASE_REMOTE_CONFIG_ARTIFACT = new Artifact ("Firebase.RemoteConfig", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "RemoteConfig"); +Artifact FIREBASE_STORAGE_ARTIFACT = new Artifact ("Firebase.Storage", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "Storage"); +Artifact FIREBASE_APP_DISTRIBUTION_ARTIFACT = new Artifact ("Firebase.AppDistribution", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "AppDistribution"); +Artifact FIREBASE_APP_CHECK_ARTIFACT = new Artifact ("Firebase.AppCheck", "13.1.1.0", "15.0", ComponentGroup.Firebase, csprojName: "AppCheck"); // Google artifacts available to be built. These artifacts generate NuGets. Artifact GOOGLE_ANALYTICS_ARTIFACT = new Artifact ("Google.Analytics", "3.20.0.2", "15.0", ComponentGroup.Google, csprojName: "Analytics"); @@ -22,16 +22,16 @@ Artifact GOOGLE_CAST_ARTIFACT = new Artifact ("Google.Cast" Artifact GOOGLE_MAPS_ARTIFACT = new Artifact ("Google.Maps", "9.2.0.10", "15.0", ComponentGroup.Google, csprojName: "Maps"); Artifact GOOGLE_UMP_ARTIFACT = new Artifact ("Google.UserMessagingPlatform", "1.1.0.1", "15.0", ComponentGroup.Google, csprojName: "UserMessagingPlatform"); Artifact GOOGLE_PLACES_ARTIFACT = new Artifact ("Google.Places", "7.4.0.4", "15.0", ComponentGroup.Google, csprojName: "Places"); -Artifact GOOGLE_APP_CHECK_CORE_ARTIFACT = new Artifact ("Google.AppCheckCore", "11.3.2", "15.0", ComponentGroup.Google, csprojName: "AppCheckCore"); +Artifact GOOGLE_APP_CHECK_CORE_ARTIFACT = new Artifact ("Google.AppCheckCore", "12.0.0.0", "15.0", ComponentGroup.Google, csprojName: "AppCheckCore"); Artifact GOOGLE_SIGN_IN_ARTIFACT = new Artifact ("Google.SignIn", "10.1.0.0", "15.0", ComponentGroup.Google, csprojName: "SignIn"); Artifact GOOGLE_TAG_MANAGER_ARTIFACT = new Artifact ("Google.TagManager", "9.2.0.0", "15.0", ComponentGroup.Google, csprojName: "TagManager"); -Artifact GOOGLE_GOOGLE_APP_MEASUREMENT_ARTIFACT = new Artifact ("Google.AppMeasurement", "12.19.3", "15.0", ComponentGroup.Google, csprojName: "GoogleAppMeasurement"); -Artifact GOOGLE_PROMISES_OBJC_ARTIFACT = new Artifact ("Google.PromisesObjC", "2.4.0.8", "15.0", ComponentGroup.Google, csprojName: "PromisesObjC"); -Artifact GOOGLE_GTM_SESSION_FETCHER_ARTIFACT = new Artifact ("Google.GTMSessionFetcher", "3.5.0.8", "15.0", ComponentGroup.Google, csprojName: "GTMSessionFetcher"); -Artifact GOOGLE_NANOPB_ARTIFACT = new Artifact ("Google.Nanopb", "3.30910.0.6", "15.0", ComponentGroup.Google, csprojName: "Nanopb"); -Artifact GOOGLE_GOOGLE_UTILITIES_ARTIFACT = new Artifact ("Google.GoogleUtilities", "8.1.5", "15.0", ComponentGroup.Google, csprojName: "GoogleUtilities"); -Artifact GOOGLE_GOOGLE_DATA_TRANSPORT_ARTIFACT = new Artifact ("Google.GoogleDataTransport", "10.1.0.6", "15.0", ComponentGroup.Google, csprojName: "GoogleDataTransport"); +Artifact GOOGLE_GOOGLE_APP_MEASUREMENT_ARTIFACT = new Artifact ("Google.AppMeasurement", "13.1.1.0", "15.0", ComponentGroup.Google, csprojName: "GoogleAppMeasurement"); +Artifact GOOGLE_PROMISES_OBJC_ARTIFACT = new Artifact ("Google.PromisesObjC", "2.4.1.0", "15.0", ComponentGroup.Google, csprojName: "PromisesObjC"); +Artifact GOOGLE_GTM_SESSION_FETCHER_ARTIFACT = new Artifact ("Google.GTMSessionFetcher", "5.3.1.0", "15.0", ComponentGroup.Google, csprojName: "GTMSessionFetcher"); +Artifact GOOGLE_NANOPB_ARTIFACT = new Artifact ("Google.Nanopb", "3.30910.0.7", "15.0", ComponentGroup.Google, csprojName: "Nanopb"); +Artifact GOOGLE_GOOGLE_UTILITIES_ARTIFACT = new Artifact ("Google.GoogleUtilities", "8.1.5.1", "15.0", ComponentGroup.Google, csprojName: "GoogleUtilities"); +Artifact GOOGLE_GOOGLE_DATA_TRANSPORT_ARTIFACT = new Artifact ("Google.GoogleDataTransport", "10.1.1.0", "15.0", ComponentGroup.Google, csprojName: "GoogleDataTransport"); // MLKit artifacts available to be built. These artifacts generate NuGets. Artifact MLKIT_CORE_ARTIFACT = new Artifact ("MLKit.Core", "12.0.0.3", "16.0", ComponentGroup.MLKit, csprojName: "Core"); Artifact MLKIT_TEXT_RECOGNITION = new Artifact ("MLKit.TextRecognition", "1.0.0.3", "15.0", ComponentGroup.MLKit, csprojName: "TextRecognition"); @@ -97,22 +97,23 @@ var ARTIFACTS = new Dictionary { void SetArtifactsDependencies () { + GOOGLE_GOOGLE_APP_MEASUREMENT_ARTIFACT.Dependencies = null; FIREBASE_AB_TESTING_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT }; FIREBASE_ANALYTICS_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT, FIREBASE_INSTALLATIONS_ARTIFACT, GOOGLE_GOOGLE_APP_MEASUREMENT_ARTIFACT }; FIREBASE_AUTH_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT, GOOGLE_GTM_SESSION_FETCHER_ARTIFACT }; - FIREBASE_CLOUD_FIRESTORE_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT, FIREBASE_AUTH_ARTIFACT }; + FIREBASE_CLOUD_FIRESTORE_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT }; FIREBASE_CLOUD_FUNCTIONS_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT, GOOGLE_GTM_SESSION_FETCHER_ARTIFACT }; FIREBASE_CLOUD_MESSAGING_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT, FIREBASE_INSTALLATIONS_ARTIFACT }; - FIREBASE_CORE_ARTIFACT.Dependencies = new [] { GOOGLE_GOOGLE_DATA_TRANSPORT_ARTIFACT, GOOGLE_GOOGLE_UTILITIES_ARTIFACT, GOOGLE_NANOPB_ARTIFACT, GOOGLE_PROMISES_OBJC_ARTIFACT, GOOGLE_APP_CHECK_CORE_ARTIFACT }; + FIREBASE_CORE_ARTIFACT.Dependencies = new [] { GOOGLE_APP_CHECK_CORE_ARTIFACT, GOOGLE_GOOGLE_DATA_TRANSPORT_ARTIFACT, GOOGLE_GOOGLE_UTILITIES_ARTIFACT, GOOGLE_NANOPB_ARTIFACT, GOOGLE_PROMISES_OBJC_ARTIFACT }; FIREBASE_CRASHLYTICS_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT, FIREBASE_INSTALLATIONS_ARTIFACT }; FIREBASE_DATABASE_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT }; - FIREBASE_IN_APP_MESSAGING_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT, FIREBASE_INSTALLATIONS_ARTIFACT, FIREBASE_AB_TESTING_ARTIFACT }; + FIREBASE_IN_APP_MESSAGING_ARTIFACT.Dependencies = new [] { FIREBASE_AB_TESTING_ARTIFACT, FIREBASE_CORE_ARTIFACT, FIREBASE_INSTALLATIONS_ARTIFACT }; FIREBASE_INSTALLATIONS_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT }; - FIREBASE_PERFORMANCE_MONITORING_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT, FIREBASE_INSTALLATIONS_ARTIFACT, FIREBASE_AB_TESTING_ARTIFACT, FIREBASE_REMOTE_CONFIG_ARTIFACT }; - FIREBASE_REMOTE_CONFIG_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT, FIREBASE_INSTALLATIONS_ARTIFACT, FIREBASE_AB_TESTING_ARTIFACT }; - FIREBASE_STORAGE_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT, FIREBASE_DATABASE_ARTIFACT, GOOGLE_GTM_SESSION_FETCHER_ARTIFACT }; + FIREBASE_PERFORMANCE_MONITORING_ARTIFACT.Dependencies = new [] { FIREBASE_AB_TESTING_ARTIFACT, FIREBASE_CORE_ARTIFACT, FIREBASE_INSTALLATIONS_ARTIFACT, FIREBASE_REMOTE_CONFIG_ARTIFACT }; + FIREBASE_REMOTE_CONFIG_ARTIFACT.Dependencies = new [] { FIREBASE_AB_TESTING_ARTIFACT, FIREBASE_CORE_ARTIFACT, FIREBASE_INSTALLATIONS_ARTIFACT }; + FIREBASE_STORAGE_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT, GOOGLE_GTM_SESSION_FETCHER_ARTIFACT }; FIREBASE_APP_DISTRIBUTION_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT, FIREBASE_INSTALLATIONS_ARTIFACT }; - FIREBASE_APP_CHECK_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT, FIREBASE_INSTALLATIONS_ARTIFACT, GOOGLE_APP_CHECK_CORE_ARTIFACT }; + FIREBASE_APP_CHECK_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT, GOOGLE_APP_CHECK_CORE_ARTIFACT }; GOOGLE_ANALYTICS_ARTIFACT.Dependencies = null; GOOGLE_CAST_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT }; @@ -121,7 +122,7 @@ void SetArtifactsDependencies () GOOGLE_PLACES_ARTIFACT.Dependencies = null; GOOGLE_SIGN_IN_ARTIFACT.Dependencies = new [] { GOOGLE_GTM_SESSION_FETCHER_ARTIFACT, GOOGLE_PROMISES_OBJC_ARTIFACT, GOOGLE_GOOGLE_UTILITIES_ARTIFACT, GOOGLE_APP_CHECK_CORE_ARTIFACT }; GOOGLE_TAG_MANAGER_ARTIFACT.Dependencies = new [] { FIREBASE_CORE_ARTIFACT, FIREBASE_INSTALLATIONS_ARTIFACT, FIREBASE_ANALYTICS_ARTIFACT }; - GOOGLE_APP_CHECK_CORE_ARTIFACT.Dependencies = new [] { GOOGLE_PROMISES_OBJC_ARTIFACT, GOOGLE_GOOGLE_UTILITIES_ARTIFACT }; + GOOGLE_APP_CHECK_CORE_ARTIFACT.Dependencies = new [] { GOOGLE_GOOGLE_UTILITIES_ARTIFACT, GOOGLE_PROMISES_OBJC_ARTIFACT }; GOOGLE_PROMISES_OBJC_ARTIFACT.Dependencies = null; GOOGLE_GTM_SESSION_FETCHER_ARTIFACT.Dependencies = null; GOOGLE_NANOPB_ARTIFACT.Dependencies = null; @@ -146,68 +147,22 @@ void SetArtifactsDependencies () void SetArtifactsPodSpecs () { // Firebase components - FIREBASE_AB_TESTING_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("FirebaseABTesting", "12.19.0", frameworkSource: FrameworkSource.Pods) - }; - FIREBASE_ANALYTICS_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("FirebaseAnalytics", "12.19.0") - }; - FIREBASE_AUTH_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("FirebaseAuth", "12.19.0", frameworkSource: FrameworkSource.Pods) - }; - FIREBASE_CLOUD_FIRESTORE_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("FirebaseFirestore", "12.19.3", frameworkSource: FrameworkSource.Pods), - PodSpec.Create ("FirebaseFirestoreInternal", "12.19.3", frameworkSource: FrameworkSource.Pods), - PodSpec.Create ("BoringSSL-GRPC", "0.0.37", frameworkSource: FrameworkSource.Pods, frameworkName: "openssl_grpc"), - PodSpec.Create ("gRPC-Core", "1.69.0", frameworkSource: FrameworkSource.Pods, frameworkName: "grpc"), - PodSpec.Create ("gRPC-C++", "1.69.0", frameworkSource: FrameworkSource.Pods, frameworkName: "grpcpp"), - PodSpec.Create ("abseil", "1.20240722.0", frameworkSource: FrameworkSource.Pods, frameworkName: "absl", subSpecs: new [] { "algorithm", "base", "memory", "meta", "strings", "time", "types" }), - }; - FIREBASE_CLOUD_FUNCTIONS_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("FirebaseFunctions", "12.19.0", frameworkSource: FrameworkSource.Pods) - }; - FIREBASE_CLOUD_MESSAGING_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("FirebaseMessaging", "12.19.0", frameworkSource: FrameworkSource.Pods) - }; - FIREBASE_CORE_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("FirebaseAppCheckInterop", "12.19.0", frameworkSource: FrameworkSource.Pods), - PodSpec.Create ("FirebaseAuthInterop", "12.19.0", frameworkSource: FrameworkSource.Pods), - PodSpec.Create ("FirebaseCore", "12.19.3", frameworkSource: FrameworkSource.Pods), - PodSpec.Create ("FirebaseCoreExtension", "12.19.0", frameworkSource: FrameworkSource.Pods), - PodSpec.Create ("FirebaseCoreInternal", "12.19.0", frameworkSource: FrameworkSource.Pods), - PodSpec.Create ("FirebaseMessagingInterop", "12.19.0", frameworkSource: FrameworkSource.Pods), - PodSpec.Create ("FirebaseRemoteConfigInterop", "12.19.0", frameworkSource: FrameworkSource.Pods), - PodSpec.Create ("FirebaseSharedSwift", "12.19.0", frameworkSource: FrameworkSource.Pods), - PodSpec.Create ("leveldb-library", "1.22.6", frameworkSource: FrameworkSource.Pods, frameworkName: "leveldb"), - }; - FIREBASE_CRASHLYTICS_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("FirebaseCrashlytics", "12.19.0", frameworkSource: FrameworkSource.Pods) - }; - FIREBASE_DATABASE_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("FirebaseDatabase", "12.19.0", frameworkSource: FrameworkSource.Pods) - }; - FIREBASE_IN_APP_MESSAGING_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("Firebase", "12.19.3", frameworkSource: FrameworkSource.Pods, frameworkName: "FirebaseInAppMessaging", targetName: "FirebaseInAppMessaging", subSpecs: new [] { "InAppMessaging" }) - }; - FIREBASE_INSTALLATIONS_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("FirebaseInstallations", "12.19.0", frameworkSource: FrameworkSource.Pods), - PodSpec.Create ("FirebaseSessions", "12.19.0", frameworkSource: FrameworkSource.Pods) - }; - FIREBASE_PERFORMANCE_MONITORING_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("FirebasePerformance", "12.19.0", frameworkSource: FrameworkSource.Pods) - }; - FIREBASE_REMOTE_CONFIG_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("FirebaseRemoteConfig", "12.19.0", frameworkSource: FrameworkSource.Pods) - }; - FIREBASE_STORAGE_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("FirebaseStorage", "12.19.0", frameworkSource: FrameworkSource.Pods) - }; - FIREBASE_APP_DISTRIBUTION_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("Firebase", "12.19.3", frameworkSource: FrameworkSource.Pods, frameworkName: "FirebaseAppDistribution", targetName: "FirebaseAppDistribution", subSpecs: new [] { "AppDistribution" }) - }; - FIREBASE_APP_CHECK_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("FirebaseAppCheck", "12.19.0", frameworkSource: FrameworkSource.Pods) - }; + FIREBASE_AB_TESTING_ARTIFACT.PodSpecs = Array.Empty(); + FIREBASE_ANALYTICS_ARTIFACT.PodSpecs = Array.Empty(); + FIREBASE_AUTH_ARTIFACT.PodSpecs = Array.Empty(); + FIREBASE_CLOUD_FIRESTORE_ARTIFACT.PodSpecs = Array.Empty(); + FIREBASE_CLOUD_FUNCTIONS_ARTIFACT.PodSpecs = Array.Empty(); + FIREBASE_CLOUD_MESSAGING_ARTIFACT.PodSpecs = Array.Empty(); + FIREBASE_CORE_ARTIFACT.PodSpecs = Array.Empty(); + FIREBASE_CRASHLYTICS_ARTIFACT.PodSpecs = Array.Empty(); + FIREBASE_DATABASE_ARTIFACT.PodSpecs = Array.Empty(); + FIREBASE_IN_APP_MESSAGING_ARTIFACT.PodSpecs = Array.Empty(); + FIREBASE_INSTALLATIONS_ARTIFACT.PodSpecs = Array.Empty(); + FIREBASE_PERFORMANCE_MONITORING_ARTIFACT.PodSpecs = Array.Empty(); + FIREBASE_REMOTE_CONFIG_ARTIFACT.PodSpecs = Array.Empty(); + FIREBASE_STORAGE_ARTIFACT.PodSpecs = Array.Empty(); + FIREBASE_APP_DISTRIBUTION_ARTIFACT.PodSpecs = Array.Empty(); + FIREBASE_APP_CHECK_ARTIFACT.PodSpecs = Array.Empty(); // Google components GOOGLE_ANALYTICS_ARTIFACT.PodSpecs = new [] { @@ -230,32 +185,16 @@ void SetArtifactsPodSpecs () PodSpec.Create ("AppAuth", "3.0.0", frameworkSource: FrameworkSource.Pods), PodSpec.Create ("GTMAppAuth", "6.0.0", frameworkSource: FrameworkSource.Pods), }; - GOOGLE_APP_CHECK_CORE_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("AppCheckCore", "11.3.2", frameworkSource: FrameworkSource.Pods), - PodSpec.Create ("PromisesSwift", "2.4.0", frameworkSource: FrameworkSource.Pods, frameworkName: "Promises", targetName: "PromisesSwift"), - PodSpec.Create ("RecaptchaInterop", "101.0.0", frameworkSource: FrameworkSource.Pods), - }; + GOOGLE_APP_CHECK_CORE_ARTIFACT.PodSpecs = Array.Empty(); GOOGLE_TAG_MANAGER_ARTIFACT.PodSpecs = new [] { PodSpec.Create ("GoogleTagManager", "9.2.0") }; - GOOGLE_GOOGLE_APP_MEASUREMENT_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("GoogleAppMeasurement", "12.19.0") - }; - GOOGLE_PROMISES_OBJC_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("PromisesObjC", "2.4.0", frameworkSource: FrameworkSource.Pods, frameworkName: "FBLPromises", targetName: "PromisesObjC"), - }; - GOOGLE_GTM_SESSION_FETCHER_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("GTMSessionFetcher", "3.5.0", frameworkSource: FrameworkSource.Pods, subSpecs: new [] { "Full" }), - }; - GOOGLE_NANOPB_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("nanopb", "3.30910.0", frameworkSource: FrameworkSource.Pods), - }; - GOOGLE_GOOGLE_UTILITIES_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("GoogleUtilities", "8.1.5", frameworkSource: FrameworkSource.Pods, subSpecs: new [] { "AppDelegateSwizzler", "Environment", "Logger", "MethodSwizzler", "Network", "NSData+zlib", "Privacy", "Reachability", "UserDefaults", }), - }; - GOOGLE_GOOGLE_DATA_TRANSPORT_ARTIFACT.PodSpecs = new [] { - PodSpec.Create ("GoogleDataTransport", "10.1.0", frameworkSource: FrameworkSource.Pods), - }; + GOOGLE_GOOGLE_APP_MEASUREMENT_ARTIFACT.PodSpecs = Array.Empty(); + GOOGLE_PROMISES_OBJC_ARTIFACT.PodSpecs = Array.Empty(); + GOOGLE_GTM_SESSION_FETCHER_ARTIFACT.PodSpecs = Array.Empty(); + GOOGLE_NANOPB_ARTIFACT.PodSpecs = Array.Empty(); + GOOGLE_GOOGLE_UTILITIES_ARTIFACT.PodSpecs = Array.Empty(); + GOOGLE_GOOGLE_DATA_TRANSPORT_ARTIFACT.PodSpecs = Array.Empty(); // MLKit components MLKIT_CORE_ARTIFACT.PodSpecs = new [] { diff --git a/docs/FIREBASE_13_XBD.md b/docs/FIREBASE_13_XBD.md new file mode 100644 index 00000000..12b873f9 --- /dev/null +++ b/docs/FIREBASE_13_XBD.md @@ -0,0 +1,208 @@ +# Firebase 13.1.1 with Xamarin.Build.Download + +This is an unpublished Firebase-only delivery experiment. Firebase 13.1.1 is the +first candidate; versions 13.1.0 and earlier do not contain the Firestore eMudhra +certificate-trust-store security fix. The preserved earlier Firebase 13 migration +is reference material, not the build provider for this experiment. + +## Scope and delivery + +The 16 existing Firebase products and their seven existing Google support packages +use the exact Xamarin.Build.Download `[0.11.6]` dependency. Package IDs, namespaces, +managed type names, and .NET 10 iOS/Mac Catalyst targets remain stable. No AI Logic +binding product is introduced. No Sign-In, Maps, Places, Tag Manager, Cast, UMP, or +ML Kit product is migrated here. + +`source/Firebase/native-assets.json` owns the source, package versions, dependency +closure, native framework paths, linker metadata, actual binary versions, resource +slices, and tool digests. `tools/firebase13/generate.py` produces the checked-in +`build`/`buildTransitive` targets; schema validation rejects stale generated files. +Repository-owned NuGet dependencies use exact bounded versions for the verified +archive closure. Schema validation checks Cake, project references and the ownership +manifest together, including duplicate dependencies; package inspection checks the +actual nuspec ranges for every target framework. +RecaptchaInterop retains its AppCheckCore NuGet owner. Firestore native bridge +registrations use the actual `__FIR…` names while retaining managed class names. + +Packages contain managed assemblies, delivery targets, readmes, and license/notice +metadata. They contain no XCFrameworks, frameworks, native bundles, static archives, +Crashlytics executables, CocoaPods output, or native source-build recipe. Binding +compilation creates managed bindings only. The producer inspects Google's prebuilt +archive; it never builds Firebase's native SDKs from source. + +Restore does not acquire native SDKs. A real application/extension build uses stock +XBD to acquire Google's official release archive. Each package adds only its owned +frameworks and resources after `_XamarinBuildDownload`, before Apple interface +compilation. Outer/design-time and binding-project builds skip acquisition. The +normal application build still links and signs native code. + +## Source and cache + +- URL: `https://github.com/firebase/firebase-ios-sdk/releases/download/13.1.1/Firebase.zip` +- SHA-256: `eab04111b6b6ebd2bbd9264b452b2eec5be13703207f32f7cf10d9040e246b70` +- Shared XBD cache ID: `FirebaseiOSSDK-13.1.1` +- Archive bytes: 387,929,918; expanded archive bytes: 1,682,508,330. + +All 23 packages declare the identical archive/cache identity. The common target +excludes an already-declared XBD item, and version checks reject conflicting +Firebase archive identities. Cold acquisition downloads the complete archive even +for a Core-only consumer. No partial ZIP provider or repository mirror is used. + +On macOS the standard cache defaults to +`~/Library/Caches/XamarinBuildDownload`; XBD uses its Windows default on Windows. +Set `XamarinBuildDownloadDir` to relocate it. Consumers need network access for +initial native acquisition as well as ordinary NuGet restore. A restored consumer +with a populated native cache can build with `--no-restore` offline. + +For recovery, delete the `FirebaseiOSSDK-13.1.1` directory **and** its neighboring +`FirebaseiOSSDK-13.1.1.unpacked` completion marker. Remove the corresponding `.zip` +if present when recovering from a failed/corrupt download. Rebuild online. Deleting +only extracted files can leave XBD believing extraction already completed. + +Consumer cache/extraction behavior is stock XBD. The targets pass the pinned `Sha256` and the 1,800-second `ExclusiveLockTimeout` +through stock XBD metadata (verified against the installed 0.11.6 implementation). +Producer/release validation independently enforces the complete ZIP digest. +A real stock-XBD fixture proves that 0.11.6 does **not** enforce that digest after +a fresh ZIP download: its hash check only applies to an existing archive before +downloading. Passing `Sha256` metadata therefore does not guarantee consumer-time +integrity of freshly downloaded frameworks. Production will retain stock XBD +0.11.6 with this limitation. On a cold cache, the build relies on HTTPS and the +official versioned release asset for the bytes it receives. XBD can reuse the +extracted files on later builds without rechecking them. + +Teams that require checksum enforcement can verify the official ZIP against the +pinned SHA-256 above before using it to populate a fresh, isolated cache. Run those +builds with native download access blocked so an absent or invalid cache cannot +fall back to automatic acquisition. For Pair to Mac, this applies wherever native +acquisition runs. This is an optional build policy; the NuGets keep the stock +first-build behavior. + +If an official XBD release fixes fresh-download verification, rerun the +wrong-digest, retry, and cache-reuse tests before adopting it. Use a fresh cache +identity or invalidate old entries so the verified path does not reuse files +extracted by 0.11.6. Crashlytics upload-symbols is independently hashed before +execution, including after copying it to a paired Mac. + +## Native details and compatibility + +The archive supplies static frameworks. Targets preserve per-project Apple +framework/linker settings, add `-ObjC`/`-lc++`, and request SDK Swift runtime linking. +Privacy bundles use the actual device/simulator/Catalyst bundle layout. Their +payloads are compared after normalizing Apple's `Contents/Resources` container; +SDK-specific bundle Info.plists are retained per slice. Compiled In-App Messaging +UI resources are selected per platform instead of requiring byte equality across +platforms. Duplicate product-framework payloads must match except detached outer +XCFramework signatures; the complete archive digest covers those signatures too. + +Analytics/App Measurement binaries in this official 13.1.1 archive report binary +version 13.0.1; the ownership manifest records the actual binary versions rather +than falsely requiring every binary to report the umbrella release version. +GoogleAdsOnDeviceConversion is included only on iOS with advertising-ID support. +`FirebaseWithoutAdIdSupport=True` excludes both it and IdentitySupport; Catalyst +always excludes GoogleAdsOnDeviceConversion. + +The shared native baseline includes AppCheckCore 12.0.0, GTMSessionFetcher 5.3.1, +PromisesObjC 2.4.1, GoogleUtilities 8.1.5 and GoogleDataTransport 10.1.1. These are +new package payloads with new package versions, including binding revisions when +upstream native versions did not change. Previously published versions are not +replaced. Non-Firebase product source/native pins remain untouched. Existing +Sign-In packages with AppCheckCore `<12` or GTMSessionFetcher `<4` bounds cannot be +represented as compatible with this Firebase closure. Google's native Sign-In +10.1.0 allows AppCheckCore 11.x/12.x and GTMSessionFetcher 3.3 through 5.x. +Supporting that combination here would require a separately validated NuGet +binding revision with compatible dependency ranges. The native Sign-In version +can stay at 10.1.0. The existing published NuGet stays on the Firebase 12 +compatibility path. + +## Commands + +Run from the repository root on a Mac with the pinned .NET workload and Xcode: + +```sh +dotnet tool restore +dotnet tool run dotnet-cake firebase13.cake --target=native-assets-validate +dotnet tool run dotnet-cake firebase13.cake --target=externals +dotnet tool run dotnet-cake firebase13.cake --target=nuget +python3 tools/firebase13/native.py packages-validate +dotnet tool install Sharpie.Bind.Tool --version 26.3.0.11 --tool-path /tmp/firebase13-sharpie +python3 tools/firebase13/audit.py --cache "$HOME/Library/Caches/XamarinBuildDownload" --sharpie-path /tmp/firebase13-sharpie/sharpie +python3 tools/firebase13/consumers.py --scope core +python3 tools/firebase13/consumers.py --scope combined +python3 tools/firebase13/consumers.py --scope combined --without-ad-id --quick +python3 tools/firebase13/consumers.py --scope all +``` + +`--names=Firebase.Core` selects its dependency closure; an omitted name packs all +23 packages. Packages go to `output/firebase13`, separate from legacy outputs. +`--cache` overrides the producer cache. Producer validation requires the pinned +ZIP: use `--archive` when a warm XBD cache no longer retains it. Acquisition uses +XBD, and archive verification occurs before packing. An absent official binary +archive is a release blocker; there is no CocoaPods or source-build fallback. + +Firebase 13 production uses `firebase13.cake` or a Firebase selection through +`build.cake`. Existing non-Firebase commands use the isolated, locked legacy +producer. Default/mixed requests are partitioned so a Firebase 13 failure never +falls back to CocoaPods. Scoped projects reject unverified packing. See +[LEGACY_PRODUCTION.md](LEGACY_PRODUCTION.md) for commands, source isolation and the +unchanged Sign-In 10.1.0 production/validation baseline. + +## Managed API updates + +Firestore retains its existing managed names while correcting Objective-C class +names for its pipeline bridge types to the actual `__FIR…Bridge` exports. New 13.x +bindings cover BSON ObjectId/Timestamp, Decimal128, explicit Int32, binary subtypes, +MinKey/MaxKey/Regex values, literal-source and write pipeline stages, and the atomic +pipeline constructor. The literals, update and upsert stages expose expression-valued +`NSDictionary` constructors (including the literals array). +Their untyped native interop initializers are internal. Simulator probes exercise +these typed stage constructors, BSON round-trips, inherited +NSObject equality and pipeline construction without contacting a Firebase service. + +The existing binding audit runs against all 16 Firebase products using the pinned +archive. Audit-only staged copies adapt Google's standard framework headers and +Swift compatibility headers; the XBD cache is never modified. Explicitly scoped +audit dispositions document inherited NSObject/NSCopying methods and the Storage +task protocol methods already generated by bgen. They do not remove those public +managed APIs or waive the required fallback comparison. + +## Validation and publication limits + +The `Firebase 13 XBD experiment` workflow runs schema/hostile-archive/unit checks on +PRs. Same-repository PR branches also run the Mac producer and +consumer matrix; fork PRs cannot schedule the self-hosted runner. Manual dispatch +is available once the workflow exists on the default branch. The workflow has +read-only repository permissions and no publication job. A failing `pod` is placed +first on PATH. Consumer tests isolate NuGet caches, verify restore leaves XBD alone, +perform native acquisition on the first build, block HTTP(S) for subsequent builds, +verify warm-cache bytes, test direct/transitive references and supported platforms, +check native/resource duplication, and execute a secret-free simulator load probe. + +The experiment keeps publication disabled in both its manifest and the existing +Firebase release configuration. These local candidates are not sealed publication +artifacts. Promotion to the approval-gated publisher must update the existing +packed-native assumptions and seal/verify the XBD-delivered candidate evidence. +Do not bypass existing release checks or represent the experiment as released. +The current pinned .NET Catalyst SDK requires a 17.0 deployment floor for test +applications; binding TFMs and declared package minimums are preserved. +Local validation evidence is summarized in `FIREBASE_13_XBD_VALIDATION.md`. +Non-Firebase package production uses the isolated baseline described in +[LEGACY_PRODUCTION.md](LEGACY_PRODUCTION.md). Sign-In remains at 10.1.0 without a +binding revision; its existing consumer dependency bounds remain unchanged. +Real Pair-to-Mac execution and credentialed Firebase service flows are not proved +by the simulator load probe. Windows path/remote-task behavior still needs review. + +## Unresolved licensing questions + +The NuGets distribute bindings/targets and obtain native binaries directly from +Google, reducing the native redistribution surface. This does not establish legal +clearance. Before publication, confirm the terms governing Analytics and Google +App Measurement acquisition/use through these targets, the appropriate package +license/acceptance wording, and any downstream notice obligations. Preserve the +separate Analytics/App Measurement redistribution review; it has not been closed. +Google's archive NOTICES are retained verbatim as `UPSTREAM-NOTICES.txt` in packages. +No SDK binary or executable is mirrored or redistributed in the NuGets. + +References: +- [Firebase 13.1.1 release](https://github.com/firebase/firebase-ios-sdk/releases/tag/13.1.1) +- [Google eMudhra remediation guidance](https://firebase.google.com/support/guides/compromised-emudhra-intermediate-ca) +- [Tagged upstream package manifest](https://github.com/firebase/firebase-ios-sdk/blob/13.1.1/Package.swift) diff --git a/docs/FIREBASE_13_XBD_VALIDATION.md b/docs/FIREBASE_13_XBD_VALIDATION.md new file mode 100644 index 00000000..d63a6d47 --- /dev/null +++ b/docs/FIREBASE_13_XBD_VALIDATION.md @@ -0,0 +1,73 @@ +# Firebase 13.1.1 XBD experiment: local validation + +This records feature-branch validation on macOS with Xcode 27.1 and the repository's +.NET 10 workloads. It is not a sealed release manifest or a claim of GitHub CI +completion. No packages have been published by this work. + +## Completed checks + +- The official Firebase 13.1.1 ZIP matches the committed SHA-256 and the digest + supplied by its GitHub release asset. Producer validation checks archive paths + and links, METADATA, tagged Package.swift, native versions, supported slices, + complete framework ownership, duplicate framework payloads, privacy/UI resources, + notices and Crashlytics tool hashes. Independently signed outer XCFramework + signatures are pinned by the archive hash; duplicate comparison excludes those + detached signatures and compares the actual framework payloads. +- All 23 scoped NuGets pack for iOS and Mac Catalyst. Package inspection requires + the exact public XBD 0.11.6 dependency and both build import paths, and rejects + embedded frameworks, bundles, executables or native download remnants. +- All 16 Firebase product binding audits pass. Swift compatibility headers require + explicit public-header input for the Storage fallback. Narrow audit dispositions + identify APIs already supplied through NSObject/NSCopying or generated protocol + implementation. They are supported by generated bindings and simulator probes. +- All 177 explicit Objective-C class registrations match exports in the 40 + canonical iOS libraries. Actual Mach-O architectures match metadata for all 119 + iOS/device, simulator and Catalyst slices, independently of Info.plist claims. +- The combined Analytics/Auth/Firestore closure passes direct and + library-transitive consumer builds for iOS simulator, unsigned iOS device and + Mac Catalyst. Core separately passes a fresh-cache simulator probe. Restore + leaves the native cache untouched; the first application + build populates it. Subsequent builds with HTTP(S) proxied to a closed local port + reuse unchanged cache bytes. The first offline pass performs a Rebuild. +- All 16 Firebase products together pass simulator build/load and offline-cache + checks. Analytics without advertising-ID support passes separately. Consumer + inspection checks native ownership, logical bundle uniqueness and privacy + resource hashes, including the advertising-ID/platform exclusions. +- Secret-free simulator probes verify Firebase 13.1.1 load, representative native + class availability, Firestore BSON value round-trips and pipeline construction. + Crashlytics upload-symbols executes its help command from the downloaded archive. +- Eleven new Python tests cover manifest/delivery and hostile-archive cases; the + existing 72 release-tool tests and 125 binding-audit tests pass. +- Local producer and consumer paths run with a failing pod sentinel. Consumer + probes assert that it was never invoked. The dedicated Firebase entry point + never loads CocoaPods code. + +## Limits and promotion work + +- These are local experimental artifacts. The new read-only workflow can repeat + schema checks and the Mac matrix, but this record does not assert a workflow run. +- The older Firebase publisher assumes packed native payloads. Publication remains + disabled. Before release, adapt its candidate validation, exact artifact handoff + and evidence sealing to this delivery model and rerun the complete matrix for + the exact release commit. Existing Sign-In release behavior is not being migrated. +- The all-product and no-ad-ID checks above are simulator checks; the committed + harness supports the broader matrix but it has not all been executed for those + two shapes locally. The full platform matrix was run for the combined + Analytics/Auth/Firestore closure. +- Non-Firebase producer isolation is covered by the locked-baseline tests and a + separate Sign-In production/consumer CI lane; see LEGACY_PRODUCTION.md. +- Real Windows/Pair-to-Mac execution, authenticated Firebase service operations and + the compatibility of existing non-Firebase packages with the new shared native + baseline are not established. Current Sign-In dependency bounds are incompatible. +- Ten Crashlytics tests verify local/remote upload integrity and real stock-XBD + ZIP caching with a bounded local archive. This replaces tests of the removed raw + script download. The ZIP fixture confirms that a fresh download with deliberately + mismatched digest metadata succeeds in XBD 0.11.6; it is explicitly **not** a + consumer-time digest guarantee. Producer verification still rejects mismatches. +- Production will retain stock XBD 0.11.6 and document its consumer checksum and + cache limits. Producer archive safety and digest verification remain mandatory. + Teams requiring pre-extraction verification can use the isolated, verified + cache procedure in FIREBASE_13_XBD.md. +- Analytics/App Measurement licensing, package acceptance wording and downstream + notice obligations remain open before publication; direct acquisition is not a + legal conclusion. See FIREBASE_13_XBD.md. diff --git a/docs/Firebase/NuGet/ABTesting.md b/docs/Firebase/NuGet/ABTesting.md index a238b4a1..6f52f139 100644 --- a/docs/Firebase/NuGet/ABTesting.md +++ b/docs/Firebase/NuGet/ABTesting.md @@ -55,3 +55,7 @@ Avoid mixing unrelated Firebase binding package sets or mismatched Firebase nati - Repository: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents - Issues: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/issues + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/Firebase/NuGet/Analytics.md b/docs/Firebase/NuGet/Analytics.md index e9d40216..d4aea948 100644 --- a/docs/Firebase/NuGet/Analytics.md +++ b/docs/Firebase/NuGet/Analytics.md @@ -53,3 +53,7 @@ Avoid mixing unrelated Firebase binding package sets or mismatched Firebase nati - Repository: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents - Issues: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/issues + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/Firebase/NuGet/AppCheck.md b/docs/Firebase/NuGet/AppCheck.md index b640dcbd..5cf37bd6 100644 --- a/docs/Firebase/NuGet/AppCheck.md +++ b/docs/Firebase/NuGet/AppCheck.md @@ -55,3 +55,7 @@ Avoid mixing unrelated Firebase binding package sets or mismatched Firebase nati - Repository: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents - Issues: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/issues + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/Firebase/NuGet/AppDistribution.md b/docs/Firebase/NuGet/AppDistribution.md index 595a8105..109f5ccb 100644 --- a/docs/Firebase/NuGet/AppDistribution.md +++ b/docs/Firebase/NuGet/AppDistribution.md @@ -55,3 +55,7 @@ Avoid mixing unrelated Firebase binding package sets or mismatched Firebase nati - Repository: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents - Issues: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/issues + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/Firebase/NuGet/Auth.md b/docs/Firebase/NuGet/Auth.md index 40b0bc82..6c512066 100644 --- a/docs/Firebase/NuGet/Auth.md +++ b/docs/Firebase/NuGet/Auth.md @@ -55,3 +55,7 @@ Avoid mixing unrelated Firebase binding package sets or mismatched Firebase nati - Repository: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents - Issues: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/issues + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/Firebase/NuGet/CloudFirestore.md b/docs/Firebase/NuGet/CloudFirestore.md index 92a8afb6..58a95987 100644 --- a/docs/Firebase/NuGet/CloudFirestore.md +++ b/docs/Firebase/NuGet/CloudFirestore.md @@ -53,3 +53,7 @@ Avoid mixing unrelated Firebase binding package sets or mismatched Firebase nati - Repository: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents - Issues: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/issues + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/Firebase/NuGet/CloudFunctions.md b/docs/Firebase/NuGet/CloudFunctions.md index 7624da8e..c09dc059 100644 --- a/docs/Firebase/NuGet/CloudFunctions.md +++ b/docs/Firebase/NuGet/CloudFunctions.md @@ -53,3 +53,7 @@ Avoid mixing unrelated Firebase binding package sets or mismatched Firebase nati - Repository: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents - Issues: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/issues + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/Firebase/NuGet/CloudMessaging.md b/docs/Firebase/NuGet/CloudMessaging.md index 96c68509..eff224fa 100644 --- a/docs/Firebase/NuGet/CloudMessaging.md +++ b/docs/Firebase/NuGet/CloudMessaging.md @@ -57,3 +57,7 @@ Avoid mixing unrelated Firebase binding package sets or mismatched Firebase nati - Repository: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents - Issues: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/issues + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/Firebase/NuGet/Core.md b/docs/Firebase/NuGet/Core.md index 8abe465f..59afc82c 100644 --- a/docs/Firebase/NuGet/Core.md +++ b/docs/Firebase/NuGet/Core.md @@ -53,3 +53,7 @@ Avoid mixing unrelated Firebase binding package sets or mismatched Firebase nati - Repository: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents - Issues: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/issues + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/Firebase/NuGet/Crashlytics.md b/docs/Firebase/NuGet/Crashlytics.md index ceee2f2d..7aaa15f2 100644 --- a/docs/Firebase/NuGet/Crashlytics.md +++ b/docs/Firebase/NuGet/Crashlytics.md @@ -87,3 +87,7 @@ Symbol uploads verify the downloaded `upload-symbols` tool against a SHA-256 dig If the tool is missing or its digest differs, delete two things from the configured Xamarin build download cache: the versioned `FCrshlytcs-` directory and the `FCrshlytcs-.unpacked` marker beside it. Then rebuild to download the pinned tool again. Both are needed, because the marker records the download as complete and deleting the directory on its own restores nothing. A third file, `FCrshlytcs-.sh`, is normally absent — it is the download cache, and a successful download moves it into the versioned directory. It survives only when an earlier attempt failed, which is what happens if the marker is deleted while the directory is left in place. If you see it, delete it too: its bytes are restored in place of a fresh download. Do not run the rejected file or change the expected digest to match it. Setting `FirebaseCrashlyticsUploadSymbolsEnabled` to `False` skips the tool download and execution. Release preparation updates the source commit, cache version, and digest together. + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/Firebase/NuGet/Database.md b/docs/Firebase/NuGet/Database.md index 6ded19d3..a3f7983d 100644 --- a/docs/Firebase/NuGet/Database.md +++ b/docs/Firebase/NuGet/Database.md @@ -53,3 +53,7 @@ Avoid mixing unrelated Firebase binding package sets or mismatched Firebase nati - Repository: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents - Issues: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/issues + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/Firebase/NuGet/InAppMessaging.md b/docs/Firebase/NuGet/InAppMessaging.md index 544731a6..03100b5c 100644 --- a/docs/Firebase/NuGet/InAppMessaging.md +++ b/docs/Firebase/NuGet/InAppMessaging.md @@ -55,3 +55,7 @@ Avoid mixing unrelated Firebase binding package sets or mismatched Firebase nati - Repository: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents - Issues: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/issues + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/Firebase/NuGet/Installations.md b/docs/Firebase/NuGet/Installations.md index a23e3d21..71435694 100644 --- a/docs/Firebase/NuGet/Installations.md +++ b/docs/Firebase/NuGet/Installations.md @@ -55,3 +55,7 @@ Avoid mixing unrelated Firebase binding package sets or mismatched Firebase nati - Repository: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents - Issues: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/issues + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/Firebase/NuGet/PerformanceMonitoring.md b/docs/Firebase/NuGet/PerformanceMonitoring.md index f42da382..43ef9a38 100644 --- a/docs/Firebase/NuGet/PerformanceMonitoring.md +++ b/docs/Firebase/NuGet/PerformanceMonitoring.md @@ -55,3 +55,7 @@ Avoid mixing unrelated Firebase binding package sets or mismatched Firebase nati - Repository: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents - Issues: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/issues + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/Firebase/NuGet/RemoteConfig.md b/docs/Firebase/NuGet/RemoteConfig.md index b79c8af0..21f1a3ef 100644 --- a/docs/Firebase/NuGet/RemoteConfig.md +++ b/docs/Firebase/NuGet/RemoteConfig.md @@ -53,3 +53,7 @@ Avoid mixing unrelated Firebase binding package sets or mismatched Firebase nati - Repository: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents - Issues: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/issues + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/Firebase/NuGet/Storage.md b/docs/Firebase/NuGet/Storage.md index 9e9ba4f3..2314382b 100644 --- a/docs/Firebase/NuGet/Storage.md +++ b/docs/Firebase/NuGet/Storage.md @@ -53,3 +53,7 @@ Avoid mixing unrelated Firebase binding package sets or mismatched Firebase nati - Repository: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents - Issues: https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/issues + +## Firebase 13 native delivery + +Firebase 13 candidates use Xamarin.Build.Download to acquire Google’s official binary archive during the first application build. Native binaries and bundles are not included in these NuGets. Restore does not acquire the native SDK. A populated XBD cache supports offline `--no-restore` builds. See [Firebase 13 XBD delivery](https://github.com/AdamEssenmacher/GoogleApisForiOSComponents/blob/main/docs/FIREBASE_13_XBD.md) for cache configuration, compatibility limits, and validation status. These changes do not apply to published Firebase 12 packages. diff --git a/docs/LEGACY_PRODUCTION.md b/docs/LEGACY_PRODUCTION.md new file mode 100644 index 00000000..ac349b96 --- /dev/null +++ b/docs/LEGACY_PRODUCTION.md @@ -0,0 +1,80 @@ +# Isolated non-Firebase package production + +The Firebase 13 experiment and the existing non-Firebase products require different +shared native dependencies. The compatibility producer keeps the pre-migration +source baseline pinned by commit and tree in `eng/legacy-producer.json`. Sign-In +stays at native 10.1.0 and package 10.1.0.0, with its existing dependency bounds, +managed APIs, target frameworks, native ownership and packed-framework delivery. +Maps/Places and deferred products retain their original delivery behavior too. + +## Commands and outputs + +Existing commands continue to select the appropriate producer: + +```sh +dotnet tool restore +dotnet tool run dotnet-cake -- --target=nuget --names=Google.SignIn +dotnet tool run dotnet-cake -- --target=libs --names=Google.Maps +dotnet tool run dotnet-cake -- --target=nuget --names=Firebase.Core +``` + +Non-Firebase selections build in an isolated copy of the locked repository source, +using the original CocoaPods pins, Ruby hooks, project files and pack commands. +Firebase 13 selections use the verified XBD producer. An unfiltered or mixed build +partitions those requests; an unsupported Firebase 13 acquisition never falls back +to CocoaPods. The lock distinguishes Cake registry aliases from artifact IDs. + +Legacy NuGets are copied to `output/`; modern NuGets remain in `output/firebase13/`. +The copy rejects missing, extra, duplicate or wrong-version packages. Legacy native +outputs owned by non-Firebase projects and Podfile resolution evidence retain their +established `externals/` paths. Shared Firebase 13 framework aliases are preserved. + +The explicit legacy entry point is also available: + +```sh +dotnet tool run dotnet-cake legacy.cake --target=nuget --names=Google.SignIn +dotnet tool run dotnet-cake legacy.cake --target=plan --names=Google.TagManager +``` + +The Sign-In/Firebase integration fixture build explicitly requests its Firebase 12 +baseline with `--producer=legacy`. That option selects historical production inputs; +it is not a Firebase 13 fallback. Existing Sign-In NuGet bounds still constrain +consumer combinations with Firebase 13. This producer isolation does not change +those published declarations. + +## Source isolation and reproducibility + +The producer materializes only the pinned Git tree into `output/legacy-sources/`. +It does not reset the checkout, move a branch, or copy untracked files or local +credentials. A shallow checkout may need one Git fetch of the pinned source commit. +CocoaPods retains its existing producer-time networking requirements. Consumer +native acquisition remains specific to each package's original delivery model. + +Metadata-only source copies are discarded automatically. Build workspaces remain +for inspection and are removed by the existing `clean` target. Current non-Firebase +source, package readmes/icons, shared compiler inputs and Cake declarations are +checked against the locked inputs. A later edit fails with guidance instead of +silently building stale source. Advancing a legacy baseline requires a reviewed +compatible source commit and package/version validation; the published 10.1.0 +fingerprint fixture is retained as regression evidence. + +Release fingerprints and native-reference inspection use the same locked source +that actually builds these packages. The producer commit is recorded separately in +validation manifests. The frozen legacy metadata and source fingerprints match the +published Sign-In 10.1.0 release, allowing reuse without a binding revision. No +existing package ID/version may be overwritten with a different payload. + +## Validation + +The read-only Firebase experiment workflow validates producer partitioning, pinned +source materialization, output identity checks, mutation rejection and the published +Sign-In fingerprint fixture. Its separate `legacy-signin` job runs the original +production command, validates the exact CocoaPods resolution and packed native +references, and builds direct/transitive simulator, unsigned-device and Catalyst +consumers with native HTTP(S) acquisition blocked. Combined consumers use matching +Firebase 12 fixtures. The existing Sign-In release pipeline uses that same baseline. + +No publication job or deployment approval is added by this validation lane. Real +OAuth/account interaction and Windows/Pair-to-Mac execution remain outside these +secret-free checks. Deferred products retain their original source and pins; the +new native execution gate exercises Sign-In rather than every deferred SDK. diff --git a/eng/firebase-release.json b/eng/firebase-release.json index c937b915..6abc837a 100644 --- a/eng/firebase-release.json +++ b/eng/firebase-release.json @@ -1,5 +1,5 @@ { - "releaseVersion": "12.19.3", + "releaseVersion": null, "minimumFirebaseVersion": "12.12.0", "nativeBuild": { "runner": "xcode-27.1", diff --git a/eng/legacy-producer.json b/eng/legacy-producer.json new file mode 100644 index 00000000..60c8d800 --- /dev/null +++ b/eng/legacy-producer.json @@ -0,0 +1,340 @@ +{ + "schema": 1, + "commit": "8cee0d065459f1d98c0ac9ff27d15484c92d5afd", + "tree": "478647f3633b32b60bf1470e09a3271d77182b6b", + "artifacts": [ + { + "key": "Firebase.ABTesting", + "id": "AdamE.Firebase.iOS.ABTesting", + "version": "12.19.3", + "project": "source/Firebase/ABTesting/ABTesting.csproj", + "dependencies": [ + "Firebase.Core" + ], + "artifactId": "Firebase.ABTesting" + }, + { + "key": "Firebase.Analytics", + "id": "AdamE.Firebase.iOS.Analytics", + "version": "12.19.3", + "project": "source/Firebase/Analytics/Analytics.csproj", + "dependencies": [ + "Firebase.Core", + "Firebase.Installations", + "Google.GoogleAppMeasurement" + ], + "artifactId": "Firebase.Analytics" + }, + { + "key": "Firebase.Auth", + "id": "AdamE.Firebase.iOS.Auth", + "version": "12.19.3", + "project": "source/Firebase/Auth/Auth.csproj", + "dependencies": [ + "Firebase.Core", + "Google.GTMSessionFetcher" + ], + "artifactId": "Firebase.Auth" + }, + { + "key": "Firebase.CloudFirestore", + "id": "AdamE.Firebase.iOS.CloudFirestore", + "version": "12.19.3", + "project": "source/Firebase/CloudFirestore/CloudFirestore.csproj", + "dependencies": [ + "Firebase.Core", + "Firebase.Auth" + ], + "artifactId": "Firebase.CloudFirestore" + }, + { + "key": "Firebase.CloudFunctions", + "id": "AdamE.Firebase.iOS.CloudFunctions", + "version": "12.19.3", + "project": "source/Firebase/CloudFunctions/CloudFunctions.csproj", + "dependencies": [ + "Firebase.Core", + "Google.GTMSessionFetcher" + ], + "artifactId": "Firebase.CloudFunctions" + }, + { + "key": "Firebase.CloudMessaging", + "id": "AdamE.Firebase.iOS.CloudMessaging", + "version": "12.19.3", + "project": "source/Firebase/CloudMessaging/CloudMessaging.csproj", + "dependencies": [ + "Firebase.Core", + "Firebase.Installations" + ], + "artifactId": "Firebase.CloudMessaging" + }, + { + "key": "Firebase.Core", + "id": "AdamE.Firebase.iOS.Core", + "version": "12.19.3", + "project": "source/Firebase/Core/Core.csproj", + "dependencies": [ + "Google.GoogleDataTransport", + "Google.GoogleUtilities", + "Google.Nanopb", + "Google.PromisesObjC", + "Google.AppCheckCore" + ], + "artifactId": "Firebase.Core" + }, + { + "key": "Firebase.Crashlytics", + "id": "AdamE.Firebase.iOS.Crashlytics", + "version": "12.19.3", + "project": "source/Firebase/Crashlytics/Crashlytics.csproj", + "dependencies": [ + "Firebase.Core", + "Firebase.Installations" + ], + "artifactId": "Firebase.Crashlytics" + }, + { + "key": "Firebase.Database", + "id": "AdamE.Firebase.iOS.Database", + "version": "12.19.3", + "project": "source/Firebase/Database/Database.csproj", + "dependencies": [ + "Firebase.Core" + ], + "artifactId": "Firebase.Database" + }, + { + "key": "Firebase.InAppMessaging", + "id": "AdamE.Firebase.iOS.InAppMessaging", + "version": "12.19.3", + "project": "source/Firebase/InAppMessaging/InAppMessaging.csproj", + "dependencies": [ + "Firebase.Core", + "Firebase.Installations", + "Firebase.ABTesting" + ], + "artifactId": "Firebase.InAppMessaging" + }, + { + "key": "Firebase.Installations", + "id": "AdamE.Firebase.iOS.Installations", + "version": "12.19.3", + "project": "source/Firebase/Installations/Installations.csproj", + "dependencies": [ + "Firebase.Core" + ], + "artifactId": "Firebase.Installations" + }, + { + "key": "Firebase.PerformanceMonitoring", + "id": "AdamE.Firebase.iOS.PerformanceMonitoring", + "version": "12.19.3", + "project": "source/Firebase/PerformanceMonitoring/PerformanceMonitoring.csproj", + "dependencies": [ + "Firebase.Core", + "Firebase.Installations", + "Firebase.ABTesting", + "Firebase.RemoteConfig" + ], + "artifactId": "Firebase.PerformanceMonitoring" + }, + { + "key": "Firebase.RemoteConfig", + "id": "AdamE.Firebase.iOS.RemoteConfig", + "version": "12.19.3", + "project": "source/Firebase/RemoteConfig/RemoteConfig.csproj", + "dependencies": [ + "Firebase.Core", + "Firebase.Installations", + "Firebase.ABTesting" + ], + "artifactId": "Firebase.RemoteConfig" + }, + { + "key": "Firebase.Storage", + "id": "AdamE.Firebase.iOS.Storage", + "version": "12.19.3", + "project": "source/Firebase/Storage/Storage.csproj", + "dependencies": [ + "Firebase.Core", + "Firebase.Database", + "Google.GTMSessionFetcher" + ], + "artifactId": "Firebase.Storage" + }, + { + "key": "Firebase.AppDistribution", + "id": "AdamE.Firebase.iOS.AppDistribution", + "version": "12.19.3", + "project": "source/Firebase/AppDistribution/AppDistribution.csproj", + "dependencies": [ + "Firebase.Core", + "Firebase.Installations" + ], + "artifactId": "Firebase.AppDistribution" + }, + { + "key": "Firebase.AppCheck", + "id": "AdamE.Firebase.iOS.AppCheck", + "version": "12.19.3", + "project": "source/Firebase/AppCheck/AppCheck.csproj", + "dependencies": [ + "Firebase.Core", + "Firebase.Installations", + "Google.AppCheckCore" + ], + "artifactId": "Firebase.AppCheck" + }, + { + "key": "Google.GoogleAppMeasurement", + "id": "AdamE.Google.iOS.GoogleAppMeasurement", + "version": "12.19.3", + "project": "source/Google/GoogleAppMeasurement/GoogleAppMeasurement.csproj", + "dependencies": [], + "artifactId": "Google.AppMeasurement" + }, + { + "key": "Google.Analytics", + "id": "AdamE.Google.iOS.Analytics", + "version": "3.20.0.2", + "project": "source/Google/Analytics/Analytics.csproj", + "dependencies": [], + "artifactId": "Google.Analytics" + }, + { + "key": "Google.Cast", + "id": "AdamE.Google.iOS.Cast", + "version": "4.7.0.1", + "project": "source/Google/Cast/Cast.csproj", + "dependencies": [ + "Firebase.Core" + ], + "artifactId": "Google.Cast" + }, + { + "key": "Google.Maps", + "id": "AdamE.Google.iOS.Maps", + "version": "9.2.0.10", + "project": "source/Google/Maps/Maps.csproj", + "dependencies": [], + "artifactId": "Google.Maps" + }, + { + "key": "Google.UserMessagingPlatform", + "id": "AdamE.Google.iOS.UserMessagingPlatform", + "version": "1.1.0.1", + "project": "source/Google/UserMessagingPlatform/UserMessagingPlatform.csproj", + "dependencies": [], + "artifactId": "Google.UserMessagingPlatform" + }, + { + "key": "Google.Places", + "id": "AdamE.Google.iOS.Places", + "version": "7.4.0.4", + "project": "source/Google/Places/Places.csproj", + "dependencies": [], + "artifactId": "Google.Places" + }, + { + "key": "Google.SignIn", + "id": "AdamE.Google.iOS.SignIn", + "version": "10.1.0.0", + "project": "source/Google/SignIn/SignIn.csproj", + "dependencies": [ + "Google.GTMSessionFetcher", + "Google.PromisesObjC", + "Google.GoogleUtilities", + "Google.AppCheckCore" + ], + "artifactId": "Google.SignIn" + }, + { + "key": "Google.AppCheckCore", + "id": "AdamE.Google.iOS.AppCheckCore", + "version": "11.3.2", + "project": "source/Google/AppCheckCore/AppCheckCore.csproj", + "dependencies": [ + "Google.PromisesObjC", + "Google.GoogleUtilities" + ], + "artifactId": "Google.AppCheckCore" + }, + { + "key": "Google.TagManager", + "id": "AdamE.Google.iOS.TagManager", + "version": "9.2.0.0", + "project": "source/Google/TagManager/TagManager.csproj", + "dependencies": [ + "Firebase.Core", + "Firebase.Installations", + "Firebase.Analytics" + ], + "artifactId": "Google.TagManager" + }, + { + "key": "Google.GTMSessionFetcher", + "id": "AdamE.Google.iOS.GTMSessionFetcher", + "version": "3.5.0.8", + "project": "source/Google/GTMSessionFetcher/GTMSessionFetcher.csproj", + "dependencies": [], + "artifactId": "Google.GTMSessionFetcher" + }, + { + "key": "Google.PromisesObjC", + "id": "AdamE.Google.iOS.PromisesObjC", + "version": "2.4.0.8", + "project": "source/Google/PromisesObjC/PromisesObjC.csproj", + "dependencies": [], + "artifactId": "Google.PromisesObjC" + }, + { + "key": "Google.Nanopb", + "id": "AdamE.Google.iOS.Nanopb", + "version": "3.30910.0.6", + "project": "source/Google/Nanopb/Nanopb.csproj", + "dependencies": [], + "artifactId": "Google.Nanopb" + }, + { + "key": "Google.GoogleUtilities", + "id": "AdamE.Google.iOS.GoogleUtilities", + "version": "8.1.5", + "project": "source/Google/GoogleUtilities/GoogleUtilities.csproj", + "dependencies": [], + "artifactId": "Google.GoogleUtilities" + }, + { + "key": "Google.GoogleDataTransport", + "id": "AdamE.Google.iOS.GoogleDataTransport", + "version": "10.1.0.6", + "project": "source/Google/GoogleDataTransport/GoogleDataTransport.csproj", + "dependencies": [ + "Google.Nanopb", + "Google.PromisesObjC" + ], + "artifactId": "Google.GoogleDataTransport" + }, + { + "key": "MLKit.Core", + "id": "AdamE.MLKit.iOS.Core", + "version": "12.0.0.3", + "project": "source/MLKit/Core/Core.csproj", + "dependencies": [ + "Firebase.Core" + ], + "artifactId": "MLKit.Core" + }, + { + "key": "MLKit.BarcodeScanning", + "id": "AdamE.MLKit.iOS.BarcodeScanning", + "version": "6.0.0.3", + "project": "source/MLKit/BarcodeScanning/BarcodeScanning.csproj", + "dependencies": [ + "Firebase.Core", + "MLKit.Core" + ], + "artifactId": "MLKit.BarcodeScanning" + } + ] +} diff --git a/firebase13.cake b/firebase13.cake new file mode 100644 index 00000000..b4e55abe --- /dev/null +++ b/firebase13.cake @@ -0,0 +1,10 @@ +#load "firebase13_common.cake" +// Firebase-only binary-distribution experiment. No CocoaPods code is loaded here. +var target = Argument("target", "native-assets-validate"); +var names = Argument("names", ""); +var archive = Argument("archive", ""); +var cache = Argument("cache", ""); +Task(target).Does(() => { + RunFirebase13Command(target, names, archive, cache); +}); +RunTarget(target); diff --git a/firebase13_common.cake b/firebase13_common.cake new file mode 100644 index 00000000..28dfe787 --- /dev/null +++ b/firebase13_common.cake @@ -0,0 +1,11 @@ +// Shared producer-only invocation. No CocoaPods code or consumer downloader. +void RunFirebase13Command(string target, string names, string archive, string cache) +{ + var args = new ProcessArgumentBuilder(); + args.AppendQuoted("tools/firebase13/native.py").Append(target); + if (!string.IsNullOrWhiteSpace(names)) args.Append("--names").AppendQuoted(names); + if (!string.IsNullOrWhiteSpace(archive)) args.Append("--archive").AppendQuoted(archive); + if (!string.IsNullOrWhiteSpace(cache)) args.Append("--cache").AppendQuoted(cache); + if (StartProcess("python3", new ProcessSettings { Arguments = args }) != 0) + throw new Exception("Firebase 13 XBD operation failed; see diagnostics above."); +} diff --git a/firebase_release.cake b/firebase_release.cake index adf74d2d..15d6b1ed 100644 --- a/firebase_release.cake +++ b/firebase_release.cake @@ -1,3 +1,4 @@ +#load "firebase13_common.cake" using System.Text; using System.Text.Json; using System.Text.RegularExpressions; @@ -213,6 +214,17 @@ Task ("firebase-release-update") void RunFirebaseReleaseTooling (bool applyChanges) { + if (FileExists("source/Firebase/native-assets.json")) { + if (applyChanges) + throw new Exception("Firebase 13 uses the pinned official archive and native-assets.json. Automated updates and publication are disabled for this experiment; verify a new official archive/digest before updating its manifest and fixtures."); + var manifest = JsonDocument.Parse(System.IO.File.ReadAllText("source/Firebase/native-assets.json")); + var pinnedVersion = manifest.RootElement.GetProperty("releaseVersion").GetString(); + if (!string.IsNullOrWhiteSpace(FIREBASE_RELEASE_VERSION) && FIREBASE_RELEASE_VERSION != pinnedVersion) + throw new Exception($"This experiment validates only Firebase {pinnedVersion}; no CocoaPods or source-build fallback is available."); + RunFirebase13Command("release-check", "", Argument("archive", ""), Argument("cache", "")); + return; + } + var context = CreateFirebaseReleaseContext (); var updates = GetFirebaseReleaseFileUpdates (context); var changedUpdates = updates.Where (u => u.Changed).ToList (); diff --git a/legacy.cake b/legacy.cake new file mode 100644 index 00000000..4ef7ea51 --- /dev/null +++ b/legacy.cake @@ -0,0 +1,3 @@ +#load "legacy_production.cake" +var legacyTarget = Argument("target", "nuget"); +RunLegacyProductionCommand(legacyTarget == "plan" ? "plan" : "build", legacyTarget == "plan" ? "nuget" : legacyTarget, Argument("names", ""), "legacy"); diff --git a/legacy_production.cake b/legacy_production.cake new file mode 100644 index 00000000..35d33b22 --- /dev/null +++ b/legacy_production.cake @@ -0,0 +1,16 @@ +// Compatibility dispatcher. Actual CocoaPods production uses the isolated locked source tree. +void RunLegacyProductionCommand(string command, string target, string names, string mode, string channel = "signin", string output = "") +{ + var args = new ProcessArgumentBuilder(); + args.AppendQuoted("tools/legacy/producer.py").Append(command); + if (!string.IsNullOrWhiteSpace(target)) args.Append("--target").AppendQuoted(target); + if (!string.IsNullOrWhiteSpace(names)) args.Append("--names").AppendQuoted(names); + args.Append("--mode").AppendQuoted(mode).Append("--channel").AppendQuoted(channel); + if (!string.IsNullOrWhiteSpace(output)) args.Append("--output").AppendQuoted(MakeAbsolute((FilePath)output).FullPath); + foreach (var key in new [] { "archive", "cache" }) { + var value = Argument(key, ""); + if (!string.IsNullOrWhiteSpace(value)) args.Append("--" + key).AppendQuoted(value); + } + if (StartProcess("python3", new ProcessSettings { Arguments = args }) != 0) + throw new Exception("Isolated producer operation failed; see diagnostics above."); +} diff --git a/scripts/FirebaseBindingAudit.Tests/AuditRunnerTests.cs b/scripts/FirebaseBindingAudit.Tests/AuditRunnerTests.cs index da23a6e9..f1741ca3 100644 --- a/scripts/FirebaseBindingAudit.Tests/AuditRunnerTests.cs +++ b/scripts/FirebaseBindingAudit.Tests/AuditRunnerTests.cs @@ -4,6 +4,15 @@ namespace FirebaseBindingAudit.Tests; public sealed class AuditRunnerTests { + [Fact] + public void SwiftCompatibilityHeaderRetryUsesExplicitHeaderScopeAndInstalledSdk() + { + var args = AuditRunner.BuildSharpieHeaderArguments("/cache/Storage.framework/Headers/Storage-Swift.h", "/audit/output", "iphoneos27.1", "/audit/frameworks"); + Assert.Equal(new[] { "bind", "--header", "/cache/Storage.framework/Headers/Storage-Swift.h", "--scope", "/cache/Storage.framework/Headers", + "--namespace", "Storage", "--sdk", "iphoneos27.1", "--output", "/audit/output", "-c", "-x", "objective-c", "-F", "/audit/frameworks" }, args); + Assert.DoesNotContain("--framework", args); + } + [Theory] [InlineData(true)] [InlineData(false)] @@ -264,17 +273,35 @@ public void TryResolveSharpieCompanionFrameworkPath_UsesLaterExistingImport() } [Fact] - public void PrepareStagedXcframeworkForTarget_MaterializesSymlinkBeforeAddingUmbrellaImports() + public void SwiftSubmoduleRemovalBalancesNestedBlocksAndIgnoresCommentAndStringBraces() + { + const string root = "framework module Root { header \"Root.h\" }"; + var map = root + "\nmodule Root.Swift { module Nested { header \"Brace}.h\" } /* } */ requires objc }\nmodule Sibling { export * }"; + var result = AuditRunner.FlattenSwiftSubmodules(map); + Assert.Contains(root, result); + Assert.Contains("module Sibling { export * }", result); + Assert.DoesNotContain("module Root.Swift", result); + Assert.Throws(() => AuditRunner.FlattenSwiftSubmodules("module Root.Swift { module Nested { }")); + } + + [Theory] + [InlineData("FirebaseFunctions-umbrella.h", true, false)] + [InlineData("FirebaseFunctions.h", true, true)] + [InlineData("FirebaseFunctions.h", false, false)] + public void PrepareStagedXcframeworkForTarget_MaterializesSymlinkBeforeAddingUmbrellaImports(string umbrellaName, bool optIn, bool normalize) { var tempRoot = Path.Combine(Path.GetTempPath(), $"firebase-binding-audit-umbrella-{Guid.NewGuid():N}"); try { var sourceXcframeworkPath = Path.Combine(tempRoot, "externals", "FirebaseFunctions.xcframework"); - var sourceHeaderPath = Path.Combine(sourceXcframeworkPath, "ios-arm64", "FirebaseFunctions.framework", "Headers", "FirebaseFunctions-umbrella.h"); + var sourceHeaderPath = Path.Combine(sourceXcframeworkPath, "ios-arm64", "FirebaseFunctions.framework", "Headers", umbrellaName); Directory.CreateDirectory(Path.GetDirectoryName(sourceHeaderPath)!); File.WriteAllText(sourceHeaderPath, "FOUNDATION_EXPORT double FirebaseFunctionsVersionNumber;\n"); + var sourceModuleMap = Path.Combine(sourceXcframeworkPath, "ios-arm64", "FirebaseFunctions.framework", "Modules", "module.modulemap"); + Directory.CreateDirectory(Path.GetDirectoryName(sourceModuleMap)!); + File.WriteAllText(sourceModuleMap, "framework module FirebaseFunctions { umbrella \".\" }\nmodule FirebaseFunctions.Swift { header \"FirebaseFunctions-Swift.h\" requires objc }"); var stagedXcframeworkPath = Path.Combine(tempRoot, "frameworks", "FirebaseFunctions.xcframework"); Directory.CreateDirectory(Path.GetDirectoryName(stagedXcframeworkPath)!); Directory.CreateSymbolicLink(stagedXcframeworkPath, sourceXcframeworkPath); @@ -284,13 +311,17 @@ public void PrepareStagedXcframeworkForTarget_MaterializesSymlinkBeforeAddingUmb { Id = "CloudFunctions", Xcframework = "FirebaseFunctions", - ObjcUmbrellaHeaderImports = ["FirebaseFunctions/FirebaseFunctions-Swift.h"] + ObjcUmbrellaHeaderImports = ["FirebaseFunctions/FirebaseFunctions-Swift.h"], + UsePrebuiltFrameworkLayout = optIn }, stagedXcframeworkPath); - var stagedHeaderPath = Path.Combine(stagedXcframeworkPath, "ios-arm64", "FirebaseFunctions.framework", "Headers", "FirebaseFunctions-umbrella.h"); - Assert.Contains("#import ", File.ReadAllText(stagedHeaderPath)); + var stagedHeaderPath = Path.Combine(stagedXcframeworkPath, "ios-arm64", "FirebaseFunctions.framework", "Headers", umbrellaName); + Assert.Equal(normalize || umbrellaName.EndsWith("-umbrella.h"), File.ReadAllText(stagedHeaderPath).Contains("#import ")); Assert.DoesNotContain("#import ", File.ReadAllText(sourceHeaderPath)); + var stagedModuleMap = Path.Combine(stagedXcframeworkPath, "ios-arm64", "FirebaseFunctions.framework", "Modules", "module.modulemap"); + Assert.Equal(!normalize, File.ReadAllText(stagedModuleMap).Contains("module FirebaseFunctions.Swift")); + Assert.Contains("module FirebaseFunctions.Swift", File.ReadAllText(sourceModuleMap)); Assert.False((new DirectoryInfo(stagedXcframeworkPath).Attributes & FileAttributes.ReparsePoint) != 0); } finally diff --git a/scripts/FirebaseBindingAudit/AuditRunner.cs b/scripts/FirebaseBindingAudit/AuditRunner.cs index 5aa0eebc..9fb55977 100644 --- a/scripts/FirebaseBindingAudit/AuditRunner.cs +++ b/scripts/FirebaseBindingAudit/AuditRunner.cs @@ -723,6 +723,28 @@ private async Task RunSharpieAsync( generatedFiles = FindSharpieBindingFiles(sharpieDirectory); } + // Framework discovery can miss Objective-C declarations in a Swift compatibility + // header. Retry that explicit public header against the installed device SDK. + var swiftHeader = UsesPrebuiltFrameworkLayout(target, attemptedFrameworkPath) ? target.ObjcUmbrellaHeaderImports + .Select(import => Path.Combine(attemptedFrameworkPath, "Headers", Path.GetFileName(import))) + .FirstOrDefault(path => path.EndsWith("-Swift.h", StringComparison.Ordinal) && File.Exists(path)) : null; + if (swiftHeader is not null && + (generatedFiles.Count == 0 || CountComparableSurface(parser.Parse(generatedFiles, [])) == 0)) + { + var sdk = await RunProcessAsync("/usr/bin/xcrun", ["--sdk", "iphoneos", "--show-sdk-version"], tempRoot, null, cancellationToken); + if (sdk.ExitCode != 0) + throw new InvalidOperationException("Cannot resolve the installed iOS SDK for the Swift compatibility-header audit."); + ResetDirectory(sharpieDirectory); + var arguments = BuildSharpieHeaderArguments(swiftHeader, sharpieDirectory, + "iphoneos" + sdk.StandardOutput.Trim(), sharpieFrameworkSearchDirectory); + var result = await RunProcessAsync(sharpieResolution.CommandPath ?? "sharpie", arguments, tempRoot, null, cancellationToken); + WriteLogs(logsDirectory, $"{target.Id}-sharpie-header", result); + warningFindings.AddRange(BuildProcessWarningFindings(result, target, "sharpie public compatibility header", "sharpie-warning")); + if (result.ExitCode != 0) + throw new InvalidOperationException($"Sharpie public compatibility-header audit failed for {target.Id}: {result.StandardError}"); + generatedFiles = FindSharpieBindingFiles(sharpieDirectory); + } + if (generatedFiles.Count == 0) { return new SharpieRunResult( @@ -790,6 +812,11 @@ private async Task RunSharpieAsync( return (processResult, BuildProcessWarningFindings(processResult, target, "sharpie bind", "sharpie-warning")); } + internal static IReadOnlyList BuildSharpieHeaderArguments(string header, string output, string sdk, string frameworkSearchDirectory) => + ["bind", "--header", header, "--scope", Path.GetDirectoryName(header)!, + "--namespace", Path.GetFileNameWithoutExtension(Path.GetDirectoryName(Path.GetDirectoryName(header)))!, + "--sdk", sdk, "--output", output, "-c", "-x", "objective-c", "-F", frameworkSearchDirectory]; + internal static bool TryResolveSharpieCompanionFrameworkPath(string frameworkPath, string stagedFrameworksDirectory, out string companionFrameworkPath) { var frameworkName = Path.GetFileNameWithoutExtension(frameworkPath); @@ -1226,7 +1253,7 @@ internal static void PrepareStagedXcframeworkForTarget(AuditTargetDefinition tar } MaterializeStagedDirectory(stagedXcframeworkPath); - AddObjcUmbrellaHeaderImports(stagedXcframeworkPath, target.ObjcUmbrellaHeaderImports); + AddObjcUmbrellaHeaderImports(stagedXcframeworkPath, target.ObjcUmbrellaHeaderImports, UsesPrebuiltFrameworkLayout(target, stagedXcframeworkPath)); } private static void MaterializeStagedDirectory(string stagedDirectoryPath) @@ -1255,7 +1282,31 @@ private static void MaterializeStagedDirectory(string stagedDirectoryPath) CopyDirectory(sourcePath, stagedDirectoryPath); } - private static void AddObjcUmbrellaHeaderImports(string xcframeworkPath, IReadOnlyList imports) + internal static bool UsesPrebuiltFrameworkLayout(AuditTargetDefinition target, string path) => + target.UsePrebuiltFrameworkLayout && !Directory.EnumerateFiles(path, "*-umbrella.h", SearchOption.AllDirectories).Any(); + + internal static string FlattenSwiftSubmodules(string content) + { + // Tokenize comments and strings first so their braces cannot delimit modules. + var syntax = new Regex("""//[^\r\n]*|/\*[\s\S]*?\*/|"(?:\\.|[^"\\])*"|(?\bmodule\s+[A-Za-z0-9_]+\.Swift\s*\{)|[{}]"""); + while (true) + { + var match = syntax.Matches(content).Cast().FirstOrDefault(m => m.Groups["module"].Success); + if (match is null) break; + var depth = 1; + var end = -1; + foreach (Match token in syntax.Matches(content, match.Index + match.Length)) + { + if (token.Value == "{" || token.Groups["module"].Success) depth++; + else if (token.Value == "}" && --depth == 0) { end = token.Index + 1; break; } + } + if (end < 0) throw new InvalidOperationException("Unbalanced Swift submodule in audit module map."); + content = content.Remove(match.Index, end - match.Index); + } + return content; + } + + private static void AddObjcUmbrellaHeaderImports(string xcframeworkPath, IReadOnlyList imports, bool prebuiltLayout) { var importLines = imports .Select(NormalizeObjcImportLine) @@ -1266,7 +1317,35 @@ private static void AddObjcUmbrellaHeaderImports(string xcframeworkPath, IReadOn return; } - foreach (var umbrellaHeaderPath in Directory.EnumerateFiles(xcframeworkPath, "*-umbrella.h", SearchOption.AllDirectories)) + // Swift compatibility headers assigned to a separate .Swift submodule are + // otherwise excluded from a root-framework Sharpie comparison. The audit + // copy exposes them through its umbrella; original module maps stay intact. + foreach (var moduleMap in prebuiltLayout ? Directory.EnumerateFiles(xcframeworkPath, "module.modulemap", SearchOption.AllDirectories) : []) + { + var content = File.ReadAllText(moduleMap); + var flattened = FlattenSwiftSubmodules(content); + if (flattened != content) + File.WriteAllText(moduleMap, flattened); + } + var umbrellaHeaders = Directory.EnumerateFiles(xcframeworkPath, "*-umbrella.h", SearchOption.AllDirectories).ToList(); + // Official Firebase ZIPs use FrameworkName.h instead of CocoaPods' -umbrella.h. + // Modify only the materialized audit copy, never the shared XBD cache. + if (prebuiltLayout && umbrellaHeaders.Count == 0) + { + foreach (var headersDirectory in Directory.EnumerateDirectories(xcframeworkPath, "Headers", SearchOption.AllDirectories)) + { + var frameworkDirectory = new DirectoryInfo(headersDirectory).Parent; + while (frameworkDirectory is not null && !frameworkDirectory.Name.EndsWith(".framework", StringComparison.Ordinal)) + frameworkDirectory = frameworkDirectory.Parent; + if (frameworkDirectory is null) + continue; + var header = Path.Combine(headersDirectory, Path.GetFileNameWithoutExtension(frameworkDirectory.Name) + ".h"); + if (!File.Exists(header)) + File.WriteAllText(header, "// Audit-only umbrella for Google's prebuilt Swift framework.\n"); + umbrellaHeaders.Add(header); + } + } + foreach (var umbrellaHeaderPath in umbrellaHeaders) { var content = File.ReadAllText(umbrellaHeaderPath); var additions = importLines diff --git a/scripts/FirebaseBindingAudit/Configuration.cs b/scripts/FirebaseBindingAudit/Configuration.cs index d2207fdb..e264c0fe 100644 --- a/scripts/FirebaseBindingAudit/Configuration.cs +++ b/scripts/FirebaseBindingAudit/Configuration.cs @@ -36,6 +36,8 @@ internal sealed class AuditTargetDefinition public string[] ObjcUmbrellaHeaderImports { get; set; } = []; + public bool UsePrebuiltFrameworkLayout { get; set; } + public string[] SharpieFrameworkDependencies { get; set; } = []; public string? SharpieMode { get; set; } diff --git a/scripts/FirebaseReleaseFingerprint/Program.cs b/scripts/FirebaseReleaseFingerprint/Program.cs index 12a431a0..fe7def55 100644 --- a/scripts/FirebaseReleaseFingerprint/Program.cs +++ b/scripts/FirebaseReleaseFingerprint/Program.cs @@ -5,6 +5,11 @@ var selected = JsonSerializer.Deserialize(File.ReadAllText(args[1]))!.ToHashSet(); var symbols = BuildInputs.ArtifactSymbols(File.ReadAllText(Path.Combine(root, "components.cake"))); var excluded = symbols.Where(p => !selected.Contains(p.Value)).Select(p => p.Key).ToHashSet(); +if (args.Contains("--components-only")) +{ + File.WriteAllText(args[2], BuildInputs.NormalizeComponents(File.ReadAllText(Path.Combine(root, "components.cake")), excluded)); + return; +} var paths = new[] { "build.cake", "common.cake", "poco.cake", "custom_externals_download.cake" }; var sources = paths.ToDictionary(p => p, p => File.ReadAllText(Path.Combine(root, p))); var normalized = BuildInputs.Normalize(sources, excluded); diff --git a/scripts/firebase-binding-audit-suppressions.json b/scripts/firebase-binding-audit-suppressions.json index 78e39897..d7a6b416 100644 --- a/scripts/firebase-binding-audit-suppressions.json +++ b/scripts/firebase-binding-audit-suppressions.json @@ -3985,6 +3985,507 @@ "evidence": [ "externals/GoogleSignIn.xcframework/ios-arm64/GoogleSignIn.framework/Headers/GIDAppCheckError.h#L29" ] + }, + { + "id": "cloudmessaging-installation-notification-13-generator-omission", + "target": "CloudMessaging", + "category": "stale-baseline-binding", + "typeName": "Firebase.CloudMessaging.Messaging", + "memberName": "InstallationIdUnregisteredNotification", + "selector": "FIRMessagingInstallationIdUnregisteredNotification", + "comparisonTypeKey": "FIRMessaging", + "comparisonMemberKey": "field|FIRMessagingInstallationIdUnregisteredNotification", + "reason": "The 13.1.1 public header still declares this NSNotificationName and the static binary exports its symbol. The primary generator omits this NS_SWIFT_NAME declaration; preserve the existing managed API.", + "evidence": [ + "externals/FirebaseMessaging.xcframework/ios-arm64/FirebaseMessaging.framework/Headers/FIRMessaging.h#L74", + "tools/firebase13/check_symbols.py" + ] + }, + { + "id": "firebase13-databasesourcestagebridge-explicit-init", + "target": "CloudFirestore", + "category": "stale-baseline-binding", + "typeName": "Firebase.CloudFirestore.DatabaseSourceStageBridge", + "memberName": "Constructor", + "selector": "init", + "comparisonTypeKey": "__FIRDatabaseSourceStageBridge", + "comparisonMemberKey": "export|init", + "reason": "FIRPipelineBridge.h explicitly declares -init. The binding disables implicit default generation and exports that same initializer; Sharpie represents it through implicit NSObject construction. Runtime probes construct this native stage.", + "evidence": [ + "externals/FirebaseFirestoreInternal.xcframework/ios-arm64/FirebaseFirestoreInternal.framework/Headers/FIRPipelineBridge.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-deletestagebridge-explicit-init", + "target": "CloudFirestore", + "category": "stale-baseline-binding", + "typeName": "Firebase.CloudFirestore.DeleteStageBridge", + "memberName": "Constructor", + "selector": "init", + "comparisonTypeKey": "__FIRDeleteStageBridge", + "comparisonMemberKey": "export|init", + "reason": "FIRPipelineBridge.h explicitly declares -init. The binding disables implicit default generation and exports that same initializer; Sharpie represents it through implicit NSObject construction. Runtime probes construct this native stage.", + "evidence": [ + "externals/FirebaseFirestoreInternal.xcframework/ios-arm64/FirebaseFirestoreInternal.framework/Headers/FIRPipelineBridge.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-bsonobjectid-inherited-nsobject-equality", + "target": "CloudFirestore", + "category": "missing-baseline-binding", + "typeName": "FirebaseFirestoreInternal.FIRBSONObjectId", + "memberName": "IsEqual", + "selector": "isEqual:", + "comparisonTypeKey": "FIRBSONObjectId", + "comparisonMemberKey": "export|isEqual:", + "reason": "The native class overrides NSObject isEqual:. Managed NSObject.IsEqual(NSObject) already sends this selector with the same nullable object/BOOL contract, so no duplicate managed wrapper is required.", + "evidence": [ + "externals/FirebaseFirestoreInternal.xcframework/ios-arm64/FirebaseFirestoreInternal.framework/Headers/FIRBSONObjectId.h", + "https://learn.microsoft.com/dotnet/api/foundation.nsobject.isequal" + ] + }, + { + "id": "firebase13-bsontimestamp-inherited-nsobject-equality", + "target": "CloudFirestore", + "category": "missing-baseline-binding", + "typeName": "FirebaseFirestoreInternal.FIRBSONTimestamp", + "memberName": "IsEqual", + "selector": "isEqual:", + "comparisonTypeKey": "FIRBSONTimestamp", + "comparisonMemberKey": "export|isEqual:", + "reason": "The native class overrides NSObject isEqual:. Managed NSObject.IsEqual(NSObject) already sends this selector with the same nullable object/BOOL contract, so no duplicate managed wrapper is required.", + "evidence": [ + "externals/FirebaseFirestoreInternal.xcframework/ios-arm64/FirebaseFirestoreInternal.framework/Headers/FIRBSONTimestamp.h", + "https://learn.microsoft.com/dotnet/api/foundation.nsobject.isequal" + ] + }, + { + "id": "firebase13-blob-inherited-nsobject-equality", + "target": "CloudFirestore", + "category": "missing-baseline-binding", + "typeName": "FirebaseFirestoreInternal.FIRBlob", + "memberName": "IsEqual", + "selector": "isEqual:", + "comparisonTypeKey": "FIRBlob", + "comparisonMemberKey": "export|isEqual:", + "reason": "The native class overrides NSObject isEqual:. Managed NSObject.IsEqual(NSObject) already sends this selector with the same nullable object/BOOL contract, so no duplicate managed wrapper is required.", + "evidence": [ + "externals/FirebaseFirestoreInternal.xcframework/ios-arm64/FirebaseFirestoreInternal.framework/Headers/FIRBlob.h", + "https://learn.microsoft.com/dotnet/api/foundation.nsobject.isequal" + ] + }, + { + "id": "firebase13-decimal128value-inherited-nsobject-equality", + "target": "CloudFirestore", + "category": "missing-baseline-binding", + "typeName": "FirebaseFirestoreInternal.FIRDecimal128Value", + "memberName": "IsEqual", + "selector": "isEqual:", + "comparisonTypeKey": "FIRDecimal128Value", + "comparisonMemberKey": "export|isEqual:", + "reason": "The native class overrides NSObject isEqual:. Managed NSObject.IsEqual(NSObject) already sends this selector with the same nullable object/BOOL contract, so no duplicate managed wrapper is required.", + "evidence": [ + "externals/FirebaseFirestoreInternal.xcframework/ios-arm64/FirebaseFirestoreInternal.framework/Headers/FIRDecimal128Value.h", + "https://learn.microsoft.com/dotnet/api/foundation.nsobject.isequal" + ] + }, + { + "id": "firebase13-int32value-inherited-nsobject-equality", + "target": "CloudFirestore", + "category": "missing-baseline-binding", + "typeName": "FirebaseFirestoreInternal.FIRInt32Value", + "memberName": "IsEqual", + "selector": "isEqual:", + "comparisonTypeKey": "FIRInt32Value", + "comparisonMemberKey": "export|isEqual:", + "reason": "The native class overrides NSObject isEqual:. Managed NSObject.IsEqual(NSObject) already sends this selector with the same nullable object/BOOL contract, so no duplicate managed wrapper is required.", + "evidence": [ + "externals/FirebaseFirestoreInternal.xcframework/ios-arm64/FirebaseFirestoreInternal.framework/Headers/FIRInt32Value.h", + "https://learn.microsoft.com/dotnet/api/foundation.nsobject.isequal" + ] + }, + { + "id": "firebase13-maxkey-inherited-nsobject-equality", + "target": "CloudFirestore", + "category": "missing-baseline-binding", + "typeName": "FirebaseFirestoreInternal.FIRMaxKey", + "memberName": "IsEqual", + "selector": "isEqual:", + "comparisonTypeKey": "FIRMaxKey", + "comparisonMemberKey": "export|isEqual:", + "reason": "The native class overrides NSObject isEqual:. Managed NSObject.IsEqual(NSObject) already sends this selector with the same nullable object/BOOL contract, so no duplicate managed wrapper is required.", + "evidence": [ + "externals/FirebaseFirestoreInternal.xcframework/ios-arm64/FirebaseFirestoreInternal.framework/Headers/FIRMaxKey.h", + "https://learn.microsoft.com/dotnet/api/foundation.nsobject.isequal" + ] + }, + { + "id": "firebase13-minkey-inherited-nsobject-equality", + "target": "CloudFirestore", + "category": "missing-baseline-binding", + "typeName": "FirebaseFirestoreInternal.FIRMinKey", + "memberName": "IsEqual", + "selector": "isEqual:", + "comparisonTypeKey": "FIRMinKey", + "comparisonMemberKey": "export|isEqual:", + "reason": "The native class overrides NSObject isEqual:. Managed NSObject.IsEqual(NSObject) already sends this selector with the same nullable object/BOOL contract, so no duplicate managed wrapper is required.", + "evidence": [ + "externals/FirebaseFirestoreInternal.xcframework/ios-arm64/FirebaseFirestoreInternal.framework/Headers/FIRMinKey.h", + "https://learn.microsoft.com/dotnet/api/foundation.nsobject.isequal" + ] + }, + { + "id": "firebase13-regexvalue-inherited-nsobject-equality", + "target": "CloudFirestore", + "category": "missing-baseline-binding", + "typeName": "FirebaseFirestoreInternal.FIRRegexValue", + "memberName": "IsEqual", + "selector": "isEqual:", + "comparisonTypeKey": "FIRRegexValue", + "comparisonMemberKey": "export|isEqual:", + "reason": "The native class overrides NSObject isEqual:. Managed NSObject.IsEqual(NSObject) already sends this selector with the same nullable object/BOOL contract, so no duplicate managed wrapper is required.", + "evidence": [ + "externals/FirebaseFirestoreInternal.xcframework/ios-arm64/FirebaseFirestoreInternal.framework/Headers/FIRRegexValue.h", + "https://learn.microsoft.com/dotnet/api/foundation.nsobject.isequal" + ] + }, + { + "id": "firebase13-storage-firstorage-copy-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorage", + "memberName": "Copy", + "selector": "copy", + "comparisonTypeKey": "FIRStorage", + "comparisonMemberKey": "export|copy", + "reason": "The baseline inherits Foundation.NSObject (and NSCopying where applicable). Its existing Copy/IsEqual/GetNativeHash/Description methods dispatch these native selectors. No duplicate managed declaration is required for the native override.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstorage-isequal-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorage", + "memberName": "IsEqual", + "selector": "isEqual:", + "comparisonTypeKey": "FIRStorage", + "comparisonMemberKey": "export|isEqual:", + "reason": "The baseline inherits Foundation.NSObject (and NSCopying where applicable). Its existing Copy/IsEqual/GetNativeHash/Description methods dispatch these native selectors. No duplicate managed declaration is required for the native override.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstorage-hash-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorage", + "memberName": "Hash", + "selector": "hash", + "comparisonTypeKey": "FIRStorage", + "comparisonMemberKey": "export|hash", + "reason": "The baseline inherits Foundation.NSObject (and NSCopying where applicable). Its existing Copy/IsEqual/GetNativeHash/Description methods dispatch these native selectors. No duplicate managed declaration is required for the native override.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstoragedownloadtask-enqueue-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageDownloadTask", + "memberName": "Enqueue", + "selector": "enqueue", + "comparisonTypeKey": "FIRStorageDownloadTask", + "comparisonMemberKey": "export|enqueue", + "reason": "The baseline adopts StorageTaskManagement; bgen generates this exact public selector on both concrete task classes from that protocol. The generated StorageDownloadTask.g.cs and StorageUploadTask.g.cs confirm these methods already exist.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstoragedownloadtask-pause-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageDownloadTask", + "memberName": "Pause", + "selector": "pause", + "comparisonTypeKey": "FIRStorageDownloadTask", + "comparisonMemberKey": "export|pause", + "reason": "The baseline adopts StorageTaskManagement; bgen generates this exact public selector on both concrete task classes from that protocol. The generated StorageDownloadTask.g.cs and StorageUploadTask.g.cs confirm these methods already exist.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstoragedownloadtask-cancel-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageDownloadTask", + "memberName": "Cancel", + "selector": "cancel", + "comparisonTypeKey": "FIRStorageDownloadTask", + "comparisonMemberKey": "export|cancel", + "reason": "The baseline adopts StorageTaskManagement; bgen generates this exact public selector on both concrete task classes from that protocol. The generated StorageDownloadTask.g.cs and StorageUploadTask.g.cs confirm these methods already exist.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstoragedownloadtask-resume-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageDownloadTask", + "memberName": "Resume", + "selector": "resume", + "comparisonTypeKey": "FIRStorageDownloadTask", + "comparisonMemberKey": "export|resume", + "reason": "The baseline adopts StorageTaskManagement; bgen generates this exact public selector on both concrete task classes from that protocol. The generated StorageDownloadTask.g.cs and StorageUploadTask.g.cs confirm these methods already exist.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstoragelistresult-copy-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageListResult", + "memberName": "Copy", + "selector": "copy", + "comparisonTypeKey": "FIRStorageListResult", + "comparisonMemberKey": "export|copy", + "reason": "The baseline inherits Foundation.NSObject (and NSCopying where applicable). Its existing Copy/IsEqual/GetNativeHash/Description methods dispatch these native selectors. No duplicate managed declaration is required for the native override.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstoragemetadata-copy-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageMetadata", + "memberName": "Copy", + "selector": "copy", + "comparisonTypeKey": "FIRStorageMetadata", + "comparisonMemberKey": "export|copy", + "reason": "The baseline inherits Foundation.NSObject (and NSCopying where applicable). Its existing Copy/IsEqual/GetNativeHash/Description methods dispatch these native selectors. No duplicate managed declaration is required for the native override.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstoragemetadata-isequal-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageMetadata", + "memberName": "IsEqual", + "selector": "isEqual:", + "comparisonTypeKey": "FIRStorageMetadata", + "comparisonMemberKey": "export|isEqual:", + "reason": "The baseline inherits Foundation.NSObject (and NSCopying where applicable). Its existing Copy/IsEqual/GetNativeHash/Description methods dispatch these native selectors. No duplicate managed declaration is required for the native override.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstoragemetadata-hash-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageMetadata", + "memberName": "Hash", + "selector": "hash", + "comparisonTypeKey": "FIRStorageMetadata", + "comparisonMemberKey": "export|hash", + "reason": "The baseline inherits Foundation.NSObject (and NSCopying where applicable). Its existing Copy/IsEqual/GetNativeHash/Description methods dispatch these native selectors. No duplicate managed declaration is required for the native override.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstoragemetadata-description-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageMetadata", + "memberName": "Description", + "selector": "description", + "comparisonTypeKey": "FIRStorageMetadata", + "comparisonMemberKey": "export|description", + "reason": "The baseline inherits Foundation.NSObject (and NSCopying where applicable). Its existing Copy/IsEqual/GetNativeHash/Description methods dispatch these native selectors. No duplicate managed declaration is required for the native override.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstoragereference-copy-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageReference", + "memberName": "Copy", + "selector": "copy", + "comparisonTypeKey": "FIRStorageReference", + "comparisonMemberKey": "export|copy", + "reason": "The baseline inherits Foundation.NSObject (and NSCopying where applicable). Its existing Copy/IsEqual/GetNativeHash/Description methods dispatch these native selectors. No duplicate managed declaration is required for the native override.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstoragereference-isequal-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageReference", + "memberName": "IsEqual", + "selector": "isEqual:", + "comparisonTypeKey": "FIRStorageReference", + "comparisonMemberKey": "export|isEqual:", + "reason": "The baseline inherits Foundation.NSObject (and NSCopying where applicable). Its existing Copy/IsEqual/GetNativeHash/Description methods dispatch these native selectors. No duplicate managed declaration is required for the native override.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstoragereference-hash-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageReference", + "memberName": "Hash", + "selector": "hash", + "comparisonTypeKey": "FIRStorageReference", + "comparisonMemberKey": "export|hash", + "reason": "The baseline inherits Foundation.NSObject (and NSCopying where applicable). Its existing Copy/IsEqual/GetNativeHash/Description methods dispatch these native selectors. No duplicate managed declaration is required for the native override.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstoragereference-description-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageReference", + "memberName": "Description", + "selector": "description", + "comparisonTypeKey": "FIRStorageReference", + "comparisonMemberKey": "export|description", + "reason": "The baseline inherits Foundation.NSObject (and NSCopying where applicable). Its existing Copy/IsEqual/GetNativeHash/Description methods dispatch these native selectors. No duplicate managed declaration is required for the native override.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstoragetasksnapshot-description-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageTaskSnapshot", + "memberName": "Description", + "selector": "description", + "comparisonTypeKey": "FIRStorageTaskSnapshot", + "comparisonMemberKey": "export|description", + "reason": "The baseline inherits Foundation.NSObject (and NSCopying where applicable). Its existing Copy/IsEqual/GetNativeHash/Description methods dispatch these native selectors. No duplicate managed declaration is required for the native override.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstorageuploadtask-enqueue-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageUploadTask", + "memberName": "Enqueue", + "selector": "enqueue", + "comparisonTypeKey": "FIRStorageUploadTask", + "comparisonMemberKey": "export|enqueue", + "reason": "The baseline adopts StorageTaskManagement; bgen generates this exact public selector on both concrete task classes from that protocol. The generated StorageDownloadTask.g.cs and StorageUploadTask.g.cs confirm these methods already exist.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstorageuploadtask-pause-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageUploadTask", + "memberName": "Pause", + "selector": "pause", + "comparisonTypeKey": "FIRStorageUploadTask", + "comparisonMemberKey": "export|pause", + "reason": "The baseline adopts StorageTaskManagement; bgen generates this exact public selector on both concrete task classes from that protocol. The generated StorageDownloadTask.g.cs and StorageUploadTask.g.cs confirm these methods already exist.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstorageuploadtask-cancel-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageUploadTask", + "memberName": "Cancel", + "selector": "cancel", + "comparisonTypeKey": "FIRStorageUploadTask", + "comparisonMemberKey": "export|cancel", + "reason": "The baseline adopts StorageTaskManagement; bgen generates this exact public selector on both concrete task classes from that protocol. The generated StorageDownloadTask.g.cs and StorageUploadTask.g.cs confirm these methods already exist.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] + }, + { + "id": "firebase13-storage-firstorageuploadtask-resume-existing-managed-api", + "target": "Storage", + "category": "missing-baseline-binding", + "typeName": "FirebaseStorage.FIRStorageUploadTask", + "memberName": "Resume", + "selector": "resume", + "comparisonTypeKey": "FIRStorageUploadTask", + "comparisonMemberKey": "export|resume", + "reason": "The baseline adopts StorageTaskManagement; bgen generates this exact public selector on both concrete task classes from that protocol. The generated StorageDownloadTask.g.cs and StorageUploadTask.g.cs confirm these methods already exist.", + "evidence": [ + "source/Firebase/Storage/ApiDefinition.cs", + "externals/FirebaseStorage.xcframework/ios-arm64/FirebaseStorage.framework/Headers/FirebaseStorage-Swift.h", + "tools/firebase13/consumers.py" + ] } ] } diff --git a/scripts/firebase-binding-audit.json b/scripts/firebase-binding-audit.json index b6b7d976..5011c68c 100644 --- a/scripts/firebase-binding-audit.json +++ b/scripts/firebase-binding-audit.json @@ -124,7 +124,8 @@ "objcUmbrellaHeaderImports": [ "FirebaseFunctions/FirebaseFunctions-Swift.h" ], - "sharpieMode": "auto" + "sharpieMode": "auto", + "usePrebuiltFrameworkLayout": true }, { "id": "CloudMessaging", @@ -232,7 +233,12 @@ "helperFiles": [ "Extension.cs" ], - "sharpieMode": "auto" + "sharpieMode": "forceFallback", + "objcUmbrellaHeaderImports": [ + "FirebaseStorage/FirebaseStorage-Swift.h" + ], + "useSharpieComparisonFallback": true, + "usePrebuiltFrameworkLayout": true }, { "id": "SignIn", diff --git a/scripts/firebase-release/release.py b/scripts/firebase-release/release.py index 36cf3904..42a415f0 100644 --- a/scripts/firebase-release/release.py +++ b/scripts/firebase-release/release.py @@ -199,14 +199,15 @@ def previous_release(): return manifest -def build_fingerprint(metadata): +def build_fingerprint(metadata, input_root=None): + input_root = input_root or ROOT with tempfile.TemporaryDirectory() as temp: selected = Path(temp) / 'selected.json' output = Path(temp) / 'normalized.json' write(selected, [p['key'] for p in metadata]) # The result is a file; stream build output so compiler/restore errors reach CI logs. subprocess.run(['dotnet', 'run', '--project', str(ROOT / 'scripts/FirebaseReleaseFingerprint'), - '--verbosity', 'minimal', '--', str(ROOT), str(selected), str(output)], + '--verbosity', 'minimal', '--', str(input_root), str(selected), str(output)], cwd=ROOT, check=True, # This net10.0 console tool does not consume Apple workloads. Keep the # repository SDK pin, but do not require its Apple workload set on Linux. @@ -214,13 +215,33 @@ def build_fingerprint(metadata): return digest(output.read_bytes()) +def legacy_inputs(root=None): + root=root or ROOT + if not (root/'eng/legacy-producer.json').exists():return None + import importlib.util + spec=importlib.util.spec_from_file_location('legacy_producer_inputs',root/'tools/legacy/producer.py') + legacy=importlib.util.module_from_spec(spec);spec.loader.exec_module(legacy) + return legacy + + def snapshot(metadata): + """Fingerprint the source tree actually used for production, including legacy inputs.""" + legacy=legacy_inputs() + if legacy and legacy.matches_metadata(metadata,ROOT): + with legacy.source_tree(ROOT) as source: + manifest=read(ROOT/'source/Firebase/native-assets.json') + legacy.verify_nonfirebase_inputs(ROOT,source,legacy.lock(ROOT),manifest) + tracked=set(subprocess.check_output(['git','ls-tree','-r','--name-only',legacy.lock(ROOT)['commit']],cwd=ROOT,text=True).splitlines()) + return snapshot_at(metadata,source,tracked) + return snapshot_at(metadata,ROOT,set(run('git','ls-files').splitlines())) + + +def snapshot_at(metadata, input_root, tracked): """Fingerprint tracked inputs, not generated outputs or archive timestamps.""" - tracked = set(run('git', 'ls-files').splitlines()) shared = ['Directory.Build.props', 'global.json', '.config/dotnet-tools.json', 'source/AssemblyInfo.cs'] - shared_data = {p: digest((ROOT / p).read_bytes()) for p in shared} - shared_data['cakeBuild'] = build_fingerprint(metadata) - shared_data['nativeBuild'] = native_build(read(ROOT / CONFIG)) + shared_data = {p: digest((input_root / p).read_bytes()) for p in shared} + shared_data['cakeBuild'] = build_fingerprint(metadata, input_root) + shared_data['nativeBuild'] = native_build(read(input_root / CONFIG)) ids = {p['id']: p for p in metadata} require(len(ids) == len(metadata), 'Duplicate package IDs') records = [] @@ -229,20 +250,20 @@ def snapshot(metadata): require(package['id'].startswith(('AdamE.Firebase.iOS.', 'AdamE.Google.iOS.')), 'Unexpected package scope') require(set(package['dependencies']) <= seen, 'Metadata is not in dependency order') seen.add(package['id']) - project = ROOT / package['project'] + project = input_root / package['project'] xml = ET.parse(project) require(xml.findtext('.//PackageId') == package['id'], 'Package ID differs from Cake export') require(version(xml.findtext('.//PackageVersion')) == version(package['version']), f"Project/Cake versions differ: {package['id']}") - files = {p for p in tracked if p.startswith(project.parent.relative_to(ROOT).as_posix() + '/')} + files = {p for p in tracked if p.startswith(project.parent.relative_to(input_root).as_posix() + '/')} for element in xml.iter(): if element.get('Pack', '').lower() == 'true' or element.tag in ('Compile', 'Import'): include = element.get('Include') or element.get('Project') if include and '$(' not in include and '*' not in include: path = (project.parent / include.replace('\\', '/')).resolve() - require(path.is_relative_to(ROOT), f'Input outside repository: {include}') + require(path.is_relative_to(input_root), f'Input outside repository: {include}') if path.is_file(): - files.add(path.relative_to(ROOT).as_posix()) + files.add(path.relative_to(input_root).as_posix()) references = {} for element in xml.findall('.//ProjectReference'): path = (project.parent / element.attrib['Include'].replace('\\', '/')).resolve() @@ -250,7 +271,7 @@ def snapshot(metadata): require(dependency_id in ids, f'Out-of-scope project reference: {dependency_id}') references[dependency_id] = ids[dependency_id]['version'] inputs = {'metadata': package, 'shared': shared_data, 'projectReferences': references, - 'files': {p: digest((ROOT / p).read_bytes()) for p in sorted(files)}} + 'files': {p: digest((input_root / p).read_bytes()) for p in sorted(files)}} records.append({**package, 'fingerprint': digest(json.dumps(inputs, sort_keys=True).encode())}) return records @@ -327,10 +348,10 @@ def validation_reasons(files, packages, channel, integration_metadata=()): 'source/AssemblyInfo.cs', '.github/workflows/firebase-release.yml', 'tools/ci/select-xcode.sh', 'tools/e2e/select-simulator.sh', 'build.cake', 'common.cake', 'poco.cake', 'custom_externals_download.cake', 'components.cake', - 'firebase_publish.cake', 'firebase_release.cake', + 'firebase_publish.cake', 'firebase_release.cake', 'legacy.cake', 'legacy_production.cake', 'eng/legacy-producer.json', f'eng/{channel}-release.json', f'eng/{channel}-release-baseline.json', } - prefixes = ['scripts/firebase-release/', 'scripts/FirebaseReleaseFingerprint/', 'tests/firebase-release/'] + prefixes = ['tools/legacy/', 'tests/legacy-producer/', 'scripts/firebase-release/', 'scripts/FirebaseReleaseFingerprint/', 'tests/firebase-release/'] if channel == 'firebase': exact.update(('tools/e2e/run-firebase-foundation.sh', 'scripts/firebase-binding-audit.json', 'scripts/firebase-binding-audit-suppressions.json')) @@ -351,6 +372,13 @@ def validation_reasons(files, packages, channel, integration_metadata=()): return sorted({p for p in files if p in exact or p.startswith(directories + tuple(prefixes))}) + +def requires_new_channel_release(changed): + # Shared dependencies have their own package versions and may advance through + # Firebase while the published Sign-In root is reused byte-for-byte. + return bool(changed) if CHANNEL == 'firebase' else 'AdamE.Google.iOS.SignIn' in changed + + def plan(args): packages = snapshot(read(args.metadata)) validate_scope(packages) @@ -378,7 +406,7 @@ def plan(args): require(version(p['version']) >= version(config['minimumFirebaseVersion']), 'Firebase package predates 12.12') if latest: require(version(release_version) >= version(latest['releaseVersion']), 'Release version went backwards') - require(not changed or version(release_version) > version(latest['releaseVersion']), + require(not requires_new_channel_release(changed) or version(release_version) > version(latest['releaseVersion']), 'Package changes require a new release version') reasons = [] if args.manual: @@ -397,6 +425,9 @@ def plan(args): result = {'schemaVersion': 1, 'sourceCommit': run('git', 'rev-parse', 'HEAD'), 'releaseVersion': release_version, 'packages': packages, 'changed': changed, 'eligible': eligible, 'relevant': bool(reasons), 'reasons': reasons, 'nativeBuild': native_build(config)} + legacy=legacy_inputs() + if legacy and legacy.matches_metadata(packages,ROOT): + result['legacyProducerBaseline']=legacy.lock(ROOT)['commit'] if CHANNEL == 'signin': result['channel'] = CHANNEL write(args.output, result) @@ -513,6 +544,14 @@ def bound(s): and (not high or v < bound(high) or (spec[-1] == ']' and v == bound(high)))) +def effective_project_tree(package, root=None): + root=root or ROOT + legacy=legacy_inputs(root) + if legacy and legacy.matches_metadata([package],root): + with legacy.source_tree(root) as source:return ET.parse(source/package['project']) + return ET.parse(root/package['project']) + + def inspect_package(data, package, packages, new_commit=None): info = package_info(data) require(info['id'] == package['id'] and version(info['version']) == version(package['version']), 'Package identity mismatch') @@ -546,7 +585,7 @@ def inspect_package(data, package, packages, new_commit=None): prefix = framework + '/' + lib['LibraryIdentifier'] + '/' + lib['LibraryPath'] require(any(n.startswith(prefix + '/') for n in native.namelist()), f'Missing native library: {prefix}') if new_commit and package.get('project'): - project = ET.parse(ROOT / package['project']) + project = effective_project_tree(package) expected = {Path(e.attrib['Include'].replace('\\', '/')).name: e for e in project.iter() if e.tag in ('NativeReference', '_NativeReference')} actual_names = {r.attrib['Name'] for r in references} diff --git a/scripts/signin-release/validate.py b/scripts/signin-release/validate.py index 333accf8..62de21f3 100644 --- a/scripts/signin-release/validate.py +++ b/scripts/signin-release/validate.py @@ -114,7 +114,7 @@ def signin_bundle(data, platform, rid): def inspect(data, package): - project = ET.parse(ROOT / package['project']) + project = release.effective_project_tree(package,ROOT) expected = {Path(e.attrib['Include'].replace('\\', '/')).name for e in project.iter() if e.tag in ('NativeReference', '_NativeReference')} versions = {p['FrameworkName'] + '.xcframework': p['Version'] for p in package['pods']} diff --git a/signin_publish.cake b/signin_publish.cake index 6da185a9..32b86260 100644 --- a/signin_publish.cake +++ b/signin_publish.cake @@ -1,3 +1,4 @@ +#load "legacy_production.cake" #load "poco.cake" #load "components.cake" #load "common.cake" @@ -36,4 +37,7 @@ Task ("google-signin-publish-metadata").Does (() => { EnsureDirectoryExists (System.IO.Path.GetDirectoryName (destination)); System.IO.File.WriteAllText (destination, JsonSerializer.Serialize (records, new JsonSerializerOptions { WriteIndented = true })); }); -RunTarget ("google-signin-publish-metadata"); +if (FileExists("eng/legacy-producer.json")) + RunLegacyProductionCommand("metadata", "", "", "legacy", "signin", Argument("metadata-output", "output/signin-metadata.json")); +else + RunTarget ("google-signin-publish-metadata"); diff --git a/source/Firebase/ABTesting/ABTesting.csproj b/source/Firebase/ABTesting/ABTesting.csproj index d7fbd1b1..8eaeafee 100644 --- a/source/Firebase/ABTesting/ABTesting.csproj +++ b/source/Firebase/ABTesting/ABTesting.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.ABTesting Firebase.ABTesting - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -27,10 +27,10 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 - + @@ -41,15 +41,6 @@ - - - Framework - True - True - -ObjC -lz - Security SystemConfiguration - - @@ -57,6 +48,21 @@ - + + + + + + + + + + + + + + + + diff --git a/source/Firebase/Analytics/Analytics.csproj b/source/Firebase/Analytics/Analytics.csproj index 609b2334..a8550422 100644 --- a/source/Firebase/Analytics/Analytics.csproj +++ b/source/Firebase/Analytics/Analytics.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.Analytics Firebase.Analytics - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -28,10 +28,10 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 - + @@ -41,24 +41,28 @@ - - - Framework - True - True - -ObjC -lc++ -lsqlite3 -lz - StoreKit - - - + + + + + + + + + + + - - + + + + + diff --git a/source/Firebase/AppCheck/AppCheck.csproj b/source/Firebase/AppCheck/AppCheck.csproj index d9a6d882..a8064d37 100644 --- a/source/Firebase/AppCheck/AppCheck.csproj +++ b/source/Firebase/AppCheck/AppCheck.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.AppCheck Firebase.AppCheck - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -27,10 +27,10 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 - + @@ -40,25 +40,27 @@ - - - Framework - True - True - DeviceCheck - -ObjC - - - - PackageVersion - - - PackageVersion - + + + + + + + + + + + + + + + + + diff --git a/source/Firebase/AppDistribution/AppDistribution.csproj b/source/Firebase/AppDistribution/AppDistribution.csproj index 4a9c2499..6cab379e 100644 --- a/source/Firebase/AppDistribution/AppDistribution.csproj +++ b/source/Firebase/AppDistribution/AppDistribution.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.AppDistribution Firebase.AppDistribution - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -27,10 +27,10 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 - + @@ -40,15 +40,6 @@ - - - Framework - UIKit - True - True - -ObjC - - @@ -56,7 +47,22 @@ - - + + + + + + + + + + + + + + + + + diff --git a/source/Firebase/Auth/Auth.csproj b/source/Firebase/Auth/Auth.csproj index 6a2d3151..6d834e30 100644 --- a/source/Firebase/Auth/Auth.csproj +++ b/source/Firebase/Auth/Auth.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.Auth Firebase.Auth - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -27,10 +27,10 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 - + @@ -57,9 +57,22 @@ - + + + + + + + - + + + + + + + + diff --git a/source/Firebase/CloudFirestore/ApiDefinition.cs b/source/Firebase/CloudFirestore/ApiDefinition.cs index f7d254fc..ab019809 100644 --- a/source/Firebase/CloudFirestore/ApiDefinition.cs +++ b/source/Firebase/CloudFirestore/ApiDefinition.cs @@ -388,14 +388,14 @@ interface VectorValue // @interface FIRExprBridge : NSObject [DisableDefaultCtor] - [BaseType (typeof (NSObject), Name = "FIRExprBridge")] + [BaseType (typeof (NSObject), Name = "__FIRExprBridge")] interface ExprBridge { } // @interface FIRFieldBridge : FIRExprBridge [DisableDefaultCtor] - [BaseType (typeof (ExprBridge), Name = "FIRFieldBridge")] + [BaseType (typeof (ExprBridge), Name = "__FIRFieldBridge")] interface FieldBridge { // - (id)initWithName:(NSString *)name; @@ -413,7 +413,7 @@ interface FieldBridge // @interface FIRConstantBridge : FIRExprBridge [DisableDefaultCtor] - [BaseType (typeof (ExprBridge), Name = "FIRConstantBridge")] + [BaseType (typeof (ExprBridge), Name = "__FIRConstantBridge")] interface ConstantBridge { // - (id)init:(id)input; @@ -423,7 +423,7 @@ interface ConstantBridge // @interface FIRFunctionExprBridge : FIRExprBridge [DisableDefaultCtor] - [BaseType (typeof (ExprBridge), Name = "FIRFunctionExprBridge")] + [BaseType (typeof (ExprBridge), Name = "__FIRFunctionExprBridge")] interface FunctionExprBridge { // - (id)initWithName:(NSString *)name Args:(NSArray *)args Options:(NSDictionary * _Nullable)options; @@ -432,7 +432,7 @@ interface FunctionExprBridge } [DisableDefaultCtor] - [BaseType (typeof (ExprBridge), Name = "FIRVariableBridge")] + [BaseType (typeof (ExprBridge), Name = "__FIRVariableBridge")] interface VariableBridge { [Export ("initWithName:")] @@ -440,7 +440,7 @@ interface VariableBridge } [DisableDefaultCtor] - [BaseType (typeof (ExprBridge), Name = "FIRPipelineExprBridge")] + [BaseType (typeof (ExprBridge), Name = "__FIRPipelineExprBridge")] interface PipelineExprBridge { [Export ("initWithStages:")] @@ -449,7 +449,7 @@ interface PipelineExprBridge // @interface FIRAggregateFunctionBridge : NSObject [DisableDefaultCtor] - [BaseType (typeof (NSObject), Name = "FIRAggregateFunctionBridge")] + [BaseType (typeof (NSObject), Name = "__FIRAggregateFunctionBridge")] interface AggregateFunctionBridge { // - (id)initWithName:(NSString *)name Args:(NSArray *)args; @@ -459,7 +459,7 @@ interface AggregateFunctionBridge // @interface FIROrderingBridge : NSObject [DisableDefaultCtor] - [BaseType (typeof (NSObject), Name = "FIROrderingBridge")] + [BaseType (typeof (NSObject), Name = "__FIROrderingBridge")] interface OrderingBridge { // - (id)initWithExpr:(FIRExprBridge *)expr Direction:(NSString *)direction; @@ -469,7 +469,7 @@ interface OrderingBridge // @interface FIRStageBridge : NSObject [DisableDefaultCtor] - [BaseType (typeof (NSObject), Name = "FIRStageBridge")] + [BaseType (typeof (NSObject), Name = "__FIRStageBridge")] interface StageBridge { // @property(nonatomic, readonly) NSString *name; @@ -478,7 +478,7 @@ interface StageBridge } [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRSubcollectionSourceStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRSubcollectionSourceStageBridge")] interface SubcollectionSourceStageBridge { [Export ("initWithPath:")] @@ -486,7 +486,7 @@ interface SubcollectionSourceStageBridge } [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRDefineStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRDefineStageBridge")] interface DefineStageBridge { [Export ("initWithVariables:")] @@ -494,7 +494,7 @@ interface DefineStageBridge } [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRSearchStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRSearchStageBridge")] interface SearchStageBridge { [Export ("initWithOptions:addFields:select:sort:")] @@ -503,7 +503,7 @@ interface SearchStageBridge // @interface FIRCollectionSourceStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRCollectionSourceStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRCollectionSourceStageBridge")] interface CollectionSourceStageBridge { // FIRPipelineBridge.h (12.14): forceIndex is nullable. @@ -513,7 +513,7 @@ interface CollectionSourceStageBridge // @interface FIRDatabaseSourceStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRDatabaseSourceStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRDatabaseSourceStageBridge")] interface DatabaseSourceStageBridge { // - (id)init; @@ -523,7 +523,7 @@ interface DatabaseSourceStageBridge // @interface FIRCollectionGroupSourceStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRCollectionGroupSourceStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRCollectionGroupSourceStageBridge")] interface CollectionGroupSourceStageBridge { // FIRPipelineBridge.h (12.14): forceIndex is nullable. @@ -533,7 +533,7 @@ interface CollectionGroupSourceStageBridge // @interface FIRDocumentsSourceStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRDocumentsSourceStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRDocumentsSourceStageBridge")] interface DocumentsSourceStageBridge { // - (id)initWithDocuments:(NSArray *)documents firestore:(FIRFirestore *)db; @@ -543,7 +543,7 @@ interface DocumentsSourceStageBridge // @interface FIRWhereStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRWhereStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRWhereStageBridge")] interface WhereStageBridge { // - (id)initWithExpr:(FIRExprBridge *)expr; @@ -553,7 +553,7 @@ interface WhereStageBridge // @interface FIRLimitStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRLimitStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRLimitStageBridge")] interface LimitStageBridge { // - (id)initWithLimit:(NSInteger)value; @@ -563,7 +563,7 @@ interface LimitStageBridge // @interface FIROffsetStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIROffsetStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIROffsetStageBridge")] interface OffsetStageBridge { // - (id)initWithOffset:(NSInteger)value; @@ -573,7 +573,7 @@ interface OffsetStageBridge // @interface FIRAddFieldsStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRAddFieldsStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRAddFieldsStageBridge")] interface AddFieldsStageBridge { // - (id)initWithFields:(NSDictionary *)fields; @@ -583,7 +583,7 @@ interface AddFieldsStageBridge // @interface FIRRemoveFieldsStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRRemoveFieldsStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRRemoveFieldsStageBridge")] interface RemoveFieldsStageBridge { // - (id)initWithFields:(NSArray *)fields; @@ -593,7 +593,7 @@ interface RemoveFieldsStageBridge // @interface FIRSelectStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRSelectStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRSelectStageBridge")] interface SelectStageBridge { // - (id)initWithSelections:(NSDictionary *)selections; @@ -603,7 +603,7 @@ interface SelectStageBridge // @interface FIRDistinctStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRDistinctStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRDistinctStageBridge")] interface DistinctStageBridge { // - (id)initWithGroups:(NSDictionary *)groups; @@ -613,7 +613,7 @@ interface DistinctStageBridge // @interface FIRAggregateStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRAggregateStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRAggregateStageBridge")] interface AggregateStageBridge { // - (id)initWithAccumulators:(NSDictionary *)accumulators groups:(NSDictionary *)groups; @@ -623,7 +623,7 @@ interface AggregateStageBridge // @interface FIRFindNearestStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRFindNearestStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRFindNearestStageBridge")] interface FindNearestStageBridge { // - (id)initWithField:(FIRFieldBridge *)field vectorValue:(FIRVectorValue *)vectorValue distanceMeasure:(NSString *)distanceMeasure limit:(NSNumber * _Nullable)limit distanceField:(FIRExprBridge * _Nullable)distanceField; @@ -633,7 +633,7 @@ interface FindNearestStageBridge // @interface FIRSorStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRSorStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRSortStageBridge")] interface SortStageBridge { // - (id)initWithOrderings:(NSArray *)orderings; @@ -643,7 +643,7 @@ interface SortStageBridge // @interface FIRReplaceWithStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRReplaceWithStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRReplaceWithStageBridge")] interface ReplaceWithStageBridge { // - (id)initWithExpr:(FIRExprBridge *)expr; @@ -653,7 +653,7 @@ interface ReplaceWithStageBridge // @interface FIRSampleStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRSampleStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRSampleStageBridge")] interface SampleStageBridge { // - (id)initWithCount:(int64_t)count; @@ -667,7 +667,7 @@ interface SampleStageBridge // @interface FIRUnionStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRUnionStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRUnionStageBridge")] interface UnionStageBridge { // - (id)initWithOther:(FIRPipelineBridge *)other; @@ -677,7 +677,7 @@ interface UnionStageBridge // @interface FIRUnnestStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRUnnestStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRUnnestStageBridge")] interface UnnestStageBridge { // - (id)initWithField:(FIRExprBridge *)field alias:(FIRExprBridge *)alias indexField:(FIRExprBridge * _Nullable)index_field; @@ -687,7 +687,7 @@ interface UnnestStageBridge // @interface FIRRawStageBridge : FIRStageBridge [DisableDefaultCtor] - [BaseType (typeof (StageBridge), Name = "FIRRawStageBridge")] + [BaseType (typeof (StageBridge), Name = "__FIRRawStageBridge")] interface RawStageBridge { // - (id)initWithName:(NSString *)name params:(NSArray *)params options:(NSDictionary * _Nullable)options; @@ -777,13 +777,16 @@ interface PipelineSnapshotBridge // @interface FIRPipelineBridge : NSObject [DisableDefaultCtor] - [BaseType (typeof (NSObject), Name = "FIRPipelineBridge")] + [BaseType (typeof (NSObject), Name = "__FIRPipelineBridge")] interface PipelineBridge { // - (id)initWithStages:(NSArray *)stages db:(FIRFirestore *)db; [Export ("initWithStages:db:")] NativeHandle Constructor (StageBridge [] stages, Firestore db); + [Export ("initWithStages:db:atomic:")] + NativeHandle Constructor (StageBridge [] stages, Firestore db, bool atomic); + // - (void)executeWithCompletion:(void (^)(__FIRPipelineSnapshotBridge * _Nullable result, NSError * _Nullable error))completion; [Async] [Export ("executeWithCompletion:")] @@ -838,7 +841,7 @@ interface PipelineListenOptionsBridge // @interface FIRRealtimePipelineBridge : NSObject [DisableDefaultCtor] - [BaseType (typeof (NSObject), Name = "FIRRealtimePipelineBridge")] + [BaseType (typeof (NSObject), Name = "__FIRRealtimePipelineBridge")] interface RealtimePipelineBridge { // - (id)initWithStages:(NSArray *)stages db:(FIRFirestore *)db; @@ -1887,4 +1890,141 @@ interface WriteBatch [Export ("commitWithCompletion:")] void Commit ([NullAllowed] CommitCompletionHandler completion); } + // Additional BSON value types exported by FirebaseFirestoreInternal 13.1.1. + [DisableDefaultCtor] + [BaseType (typeof (NSObject), Name = "FIRBSONObjectId")] + interface BsonObjectId : INSCopying + { + [Export ("initWithValue:")] + NativeHandle Constructor (string value); + [Export ("value", ArgumentSemantic.Copy)] + string Value { get; } + } + + [DisableDefaultCtor] + [BaseType (typeof (NSObject), Name = "FIRBSONTimestamp")] + interface BsonTimestamp : INSCopying + { + [Export ("initWithSeconds:increment:")] + NativeHandle Constructor (uint seconds, uint increment); + [Export ("seconds")] + uint Seconds { get; } + [Export ("increment")] + uint Increment { get; } + } + + [DisableDefaultCtor] + [BaseType (typeof (NSObject), Name = "FIRBlob")] + interface Blob : INSCopying + { + [Export ("subtype")] + byte Subtype { get; } + [Export ("bytes", ArgumentSemantic.Copy)] + NSData Bytes { get; } + [Static] + [Export ("blobWithBytes:")] + Blob FromBytes (NSData bytes); + [Static] + [Export ("blobWithBSONBinary:")] + Blob FromBsonBinary (NSData bytes); + [Static] + [Export ("blobWithBSONBinary:subtype:")] + Blob FromBsonBinary (NSData bytes, byte subtype); + [Export ("compare:")] + NSComparisonResult Compare (Blob other); + } + + [DisableDefaultCtor] + [BaseType (typeof (NSObject), Name = "FIRDecimal128Value")] + interface Decimal128Value : INSCopying + { + [Export ("initWithValue:")] + NativeHandle Constructor (string value); + [Export ("value", ArgumentSemantic.Copy)] + string Value { get; } + } + + [DisableDefaultCtor] + [BaseType (typeof (NSObject), Name = "FIRInt32Value")] + interface Int32Value : INSCopying + { + [Export ("initWithValue:")] + NativeHandle Constructor (int value); + [Export ("value")] + int Value { get; } + } + + [DisableDefaultCtor] + [BaseType (typeof (NSObject), Name = "FIRMaxKey")] + interface MaxKey + { + [Static] + [Export ("shared")] + MaxKey SharedInstance { get; } + } + + [DisableDefaultCtor] + [BaseType (typeof (NSObject), Name = "FIRMinKey")] + interface MinKey + { + [Static] + [Export ("shared")] + MinKey SharedInstance { get; } + } + + [DisableDefaultCtor] + [BaseType (typeof (NSObject), Name = "FIRRegexValue")] + interface RegexValue : INSCopying + { + [Export ("initWithPattern:options:")] + NativeHandle Constructor (string pattern, string options); + [Export ("pattern", ArgumentSemantic.Copy)] + string Pattern { get; } + [Export ("options", ArgumentSemantic.Copy)] + string Options { get; } + } + + [DisableDefaultCtor] + [BaseType (typeof (StageBridge), Name = "__FIRLiteralsSourceStageBridge")] + interface LiteralsSourceStageBridge + { + [Internal] + [Export ("initWithData:")] + NativeHandle Constructor (NSDictionary [] data); + } + + [DisableDefaultCtor] + [BaseType (typeof (StageBridge), Name = "__FIRDeleteStageBridge")] + interface DeleteStageBridge + { + [Export ("init")] + NativeHandle Constructor (); + } + + [DisableDefaultCtor] + [BaseType (typeof (StageBridge), Name = "__FIRUpdateStageBridge")] + interface UpdateStageBridge + { + [Internal] + [Export ("initWithFields:")] + NativeHandle Constructor (NSDictionary fields); + } + + [DisableDefaultCtor] + [BaseType (typeof (StageBridge), Name = "__FIRInsertStageBridge")] + interface InsertStageBridge + { + [Export ("initWithCollectionPath:documentIdExpression:")] + NativeHandle Constructor ([NullAllowed] string collectionPath, [NullAllowed] ExprBridge documentIdExpression); + } + + [DisableDefaultCtor] + [BaseType (typeof (StageBridge), Name = "__FIRUpsertStageBridge")] + interface UpsertStageBridge + { + [Internal] + [Export ("initWithAdditionalFields:collectionPath:documentIdExpression:")] + NativeHandle Constructor (NSDictionary additionalFields, [NullAllowed] string collectionPath, [NullAllowed] ExprBridge documentIdExpression); + } + } diff --git a/source/Firebase/CloudFirestore/CloudFirestore.csproj b/source/Firebase/CloudFirestore/CloudFirestore.csproj index f8aac3d4..631728e4 100644 --- a/source/Firebase/CloudFirestore/CloudFirestore.csproj +++ b/source/Firebase/CloudFirestore/CloudFirestore.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.CloudFirestore Firebase.CloudFirestore - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -27,10 +27,10 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 - + @@ -41,45 +41,6 @@ - - - Framework - MobileCoreServices SystemConfiguration - True - True - -ObjC -lc++ - - - Framework - MobileCoreServices SystemConfiguration UIKit Network - True - True - -ObjC -lc++ - - - Framework - True - True - -lc++ -lz - - - Framework - True - True - -lc++ - - - Framework - True - True - - - Framework - True - True - -lc++ - - @@ -87,6 +48,21 @@ - + + + + + + + + + + + + + + + + diff --git a/source/Firebase/CloudFirestore/Extensions.cs b/source/Firebase/CloudFirestore/Extensions.cs index 6104bf3d..6c4e164e 100644 --- a/source/Firebase/CloudFirestore/Extensions.cs +++ b/source/Firebase/CloudFirestore/Extensions.cs @@ -6,6 +6,33 @@ namespace Firebase.CloudFirestore { + // Binding-definition interfaces cannot satisfy NSDictionary's INativeObject + // constraint before bgen runs. Keep raw initializers internal, and expose the + // native expression-valued contract through these generated-class constructors. + public partial class LiteralsSourceStageBridge + { + public LiteralsSourceStageBridge (NSDictionary [] data) + : this ((NSDictionary []) (data ?? throw new ArgumentNullException (nameof (data)))) + { + } + } + + public partial class UpdateStageBridge + { + public UpdateStageBridge (NSDictionary fields) + : this ((NSDictionary) (fields ?? throw new ArgumentNullException (nameof (fields)))) + { + } + } + + public partial class UpsertStageBridge + { + public UpsertStageBridge (NSDictionary additionalFields, string? collectionPath, ExprBridge? documentIdExpression) + : this ((NSDictionary) (additionalFields ?? throw new ArgumentNullException (nameof (additionalFields))), collectionPath, documentIdExpression) + { + } + } + public partial class CollectionSourceStageBridge { // Preserve the pre-12.14 managed overload using the new native initializer. diff --git a/source/Firebase/CloudFunctions/CloudFunctions.csproj b/source/Firebase/CloudFunctions/CloudFunctions.csproj index d8bb2e2e..a61ae73b 100644 --- a/source/Firebase/CloudFunctions/CloudFunctions.csproj +++ b/source/Firebase/CloudFunctions/CloudFunctions.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.CloudFunctions Firebase.CloudFunctions - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -27,10 +27,10 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 - + @@ -41,14 +41,6 @@ - - - Framework - True - True - -ObjC - - @@ -56,9 +48,22 @@ - + + + + + + + + + + - + + + + + diff --git a/source/Firebase/CloudMessaging/CloudMessaging.csproj b/source/Firebase/CloudMessaging/CloudMessaging.csproj index fbd46c75..f72bbc84 100644 --- a/source/Firebase/CloudMessaging/CloudMessaging.csproj +++ b/source/Firebase/CloudMessaging/CloudMessaging.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.CloudMessaging Firebase.CloudMessaging - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -27,10 +27,10 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 - + @@ -41,16 +41,6 @@ - - - Framework - SystemConfiguration - UserNotifications - True - True - -lsqlite3 - - @@ -58,7 +48,22 @@ - - + + + + + + + + + + + + + + + + + diff --git a/source/Firebase/Core/Core.csproj b/source/Firebase/Core/Core.csproj index 9006b5c4..2f914f3b 100644 --- a/source/Firebase/Core/Core.csproj +++ b/source/Firebase/Core/Core.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.Core Firebase.Core - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -27,78 +27,44 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 - + - + - - - Framework - True - True - Foundation UIKit - - - Framework - True - True - -lc++ - - - Framework - True - True - - - Framework - True - True - - - Framework - True - True - - - Framework - True - True - - - Framework - True - True - - - Framework - True - True - - - Framework - True - True - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/source/Firebase/Crashlytics/Crashlytics.csproj b/source/Firebase/Crashlytics/Crashlytics.csproj index eb624bea..cb16aca9 100644 --- a/source/Firebase/Crashlytics/Crashlytics.csproj +++ b/source/Firebase/Crashlytics/Crashlytics.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.Crashlytics Firebase.Crashlytics - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -27,17 +27,15 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 - + - - @@ -45,15 +43,6 @@ - - - Framework - True - True - -lc++ -lz - Security SystemConfiguration - - @@ -61,10 +50,25 @@ - + + + + + + + + + + + + + - - + + + + + diff --git a/source/Firebase/Crashlytics/Crashlytics.targets b/source/Firebase/Crashlytics/Crashlytics.targets index 6621db5a..62c3ba73 100644 --- a/source/Firebase/Crashlytics/Crashlytics.targets +++ b/source/Firebase/Crashlytics/Crashlytics.targets @@ -1,13 +1,11 @@ - <_FirebaseCrashlyticsAssemblyName>Firebase.Crashlytics, Version=12.19.3, Culture=neutral, PublicKeyToken=null - <_FirebaseCrashlyticsItemsFolder>FCrshlytcs-12.19.3 - <_FirebaseCrashlyticsSDKBaseFolder>$(XamarinBuildDownloadDir)$(_FirebaseCrashlyticsItemsFolder)\ - - <_FirebaseScriptName>upload-symbols.sh + <_FirebaseCrashlyticsAssemblyName>Firebase.Crashlytics, Version=13.1.1.0, Culture=neutral, PublicKeyToken=null + <_FirebaseCrashlyticsItemsFolder>FirebaseiOSSDK-13.1.1 + <_FirebaseCrashlyticsSDKBaseFolder>$(_FirebaseNativeRoot)Firebase/FirebaseCrashlytics/ + <_FirebaseScriptName>upload-symbols <_FirebaseCrashlyticsScriptSha256>ad9cd5816b9abe1f746ff37b073d3b3cf3a2dc835f1a1476bc30ba5bf66e2822 - - <_FirebaseCrashlyticsDownloadCache>$(_FirebaseCrashlyticsItemsFolder)$([System.IO.Path]::GetExtension('$(_FirebaseScriptName)')) + <_FirebaseCrashlyticsUploadSymbolsContinueOnError Condition="'$(FirebaseCrashlyticsUploadSymbolsContinueOnError)'=='True'">True <_FirebaseCrashlyticsUploadSymbolsContinueOnError Condition="'$(FirebaseCrashlyticsUploadSymbolsContinueOnError)'!='True'">False @@ -22,14 +20,6 @@ <_FirebaseCrashlyticsUploadDSymToFirebaseMasterBeforeTargets Condition="'$(OS)'!='Unix'">_SayGoodbye <_FirebaseCrashlyticsUploadDSymToFirebaseMasterDependsOnTargets Condition="'$(OS)'!='Unix'">_FirebaseCrashlyticsUploadDSymToFirebaseOnWindows - - - - https://raw.githubusercontent.com/firebase/firebase-ios-sdk/42cf1417c51c5e3bfbae5d3ab89b778f8fdc4bb8/Crashlytics/upload-symbols - $(_FirebaseCrashlyticsSDKBaseFolder)$(_FirebaseScriptName) - Uncompressed - - + Text="Crashlytics upload tool is missing. $(_FirebaseNativeCleanup)" /> + Text="Crashlytics upload tool SHA-256 mismatch; it was not executed. $(_FirebaseNativeCleanup)" /> + DependsOnTargets="_XamarinBuildDownload;_FirebaseCrashlyticsVerifyUploadTool"> @@ -60,7 +50,7 @@ + DependsOnTargets="_XamarinBuildDownload;_FirebaseCrashlyticsVerifyUploadTool"> <_CopyFilesToMacOutput Include="$(_FirebaseCrashlyticsSDKBaseFolder)$(_FirebaseScriptName)"> $(_FirebaseScriptName) diff --git a/source/Firebase/Database/Database.csproj b/source/Firebase/Database/Database.csproj index 38f0d37b..68ed8e18 100644 --- a/source/Firebase/Database/Database.csproj +++ b/source/Firebase/Database/Database.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.Database Firebase.Database - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -27,10 +27,10 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 - + @@ -41,15 +41,6 @@ - - - Framework - -ObjC -lc++ -licucore - CFNetwork Security SystemConfiguration - True - True - - @@ -57,6 +48,21 @@ - + + + + + + + + + + + + + + + + diff --git a/source/Firebase/InAppMessaging/InAppMessaging.csproj b/source/Firebase/InAppMessaging/InAppMessaging.csproj index 94fcee16..ff8d9853 100644 --- a/source/Firebase/InAppMessaging/InAppMessaging.csproj +++ b/source/Firebase/InAppMessaging/InAppMessaging.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.InAppMessaging Firebase.InAppMessaging - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -27,10 +27,10 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 - + @@ -41,15 +41,6 @@ - - - Framework - True - True - CoreTelephony QuartzCore SystemConfiguration UIKit - -ObjC - - @@ -57,8 +48,23 @@ - - - + + + + + + + + + + + + + + + + + + diff --git a/source/Firebase/Installations/Installations.csproj b/source/Firebase/Installations/Installations.csproj index ffab754e..be2a8dd5 100644 --- a/source/Firebase/Installations/Installations.csproj +++ b/source/Firebase/Installations/Installations.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.Installations Firebase.Installations - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -27,10 +27,10 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 - + @@ -41,19 +41,6 @@ - - - Framework - True - True - Security - - - Framework - True - True - - @@ -61,6 +48,21 @@ - + + + + + + + + + + + + + + + + diff --git a/source/Firebase/PerformanceMonitoring/PerformanceMonitoring.csproj b/source/Firebase/PerformanceMonitoring/PerformanceMonitoring.csproj index 65bece1e..b3eec6ed 100644 --- a/source/Firebase/PerformanceMonitoring/PerformanceMonitoring.csproj +++ b/source/Firebase/PerformanceMonitoring/PerformanceMonitoring.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.PerformanceMonitoring Firebase.PerformanceMonitoring - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -27,10 +27,10 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 - + @@ -40,15 +40,6 @@ - - - Framework - True - True - -ObjC -lc++ - CoreTelephony QuartzCore SystemConfiguration - - @@ -56,9 +47,24 @@ - - - - + + + + + + + + + + + + + + + + + + + diff --git a/source/Firebase/RemoteConfig/RemoteConfig.csproj b/source/Firebase/RemoteConfig/RemoteConfig.csproj index 40064338..58919081 100644 --- a/source/Firebase/RemoteConfig/RemoteConfig.csproj +++ b/source/Firebase/RemoteConfig/RemoteConfig.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.RemoteConfig Firebase.RemoteConfig - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -27,10 +27,10 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 - + @@ -41,15 +41,6 @@ - - - Framework - True - True - -ObjC -lsqlite3 -lz - Security StoreKit SystemConfiguration - - @@ -57,8 +48,23 @@ - - - + + + + + + + + + + + + + + + + + + diff --git a/source/Firebase/Storage/Storage.csproj b/source/Firebase/Storage/Storage.csproj index ffc6291d..a71eb11e 100644 --- a/source/Firebase/Storage/Storage.csproj +++ b/source/Firebase/Storage/Storage.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Firebase.Storage Firebase.Storage - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true @@ -27,7 +27,7 @@ License.md NUGET_README.md true - 12.19.3 + 13.1.1.0 @@ -38,13 +38,6 @@ - - - Framework - True - True - - @@ -52,9 +45,22 @@ - + + + + + + + + + + - + + + + + diff --git a/source/Firebase/native-assets.json b/source/Firebase/native-assets.json new file mode 100644 index 00000000..eae04633 --- /dev/null +++ b/source/Firebase/native-assets.json @@ -0,0 +1,1497 @@ +{ + "schema": 1, + "releaseVersion": "13.1.1", + "publicationEnabled": false, + "source": { + "id": "FirebaseiOSSDK-13.1.1", + "version": "13.1.1", + "url": "https://github.com/firebase/firebase-ios-sdk/releases/download/13.1.1/Firebase.zip", + "sha256": "eab04111b6b6ebd2bbd9264b452b2eec5be13703207f32f7cf10d9040e246b70", + "kind": "Zip", + "extractionRoot": "Firebase", + "lockTimeout": 1800 + }, + "packages": [ + { + "id": "Firebase.ABTesting", + "project": "source/Firebase/ABTesting/ABTesting.csproj", + "package": "AdamE.Firebase.iOS.ABTesting", + "assets": [ + { + "id": "firebase-ab-testing", + "path": "Firebase/FirebaseABTesting/FirebaseABTesting.xcframework", + "kind": "XCFramework", + "owner": "Firebase.ABTesting", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++ -lz", + "Frameworks": "Security SystemConfiguration", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-ab-testing-FirebaseABTesting_Privacy.bundle-device", + "path": "Firebase/FirebaseABTesting/FirebaseABTesting.xcframework/ios-arm64/FirebaseABTesting.framework/FirebaseABTesting_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.ABTesting", + "logical": "FirebaseABTesting_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-ab-testing-FirebaseABTesting_Privacy.bundle-simulator", + "path": "Firebase/FirebaseABTesting/FirebaseABTesting.xcframework/ios-arm64_x86_64-simulator/FirebaseABTesting.framework/FirebaseABTesting_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.ABTesting", + "logical": "FirebaseABTesting_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-ab-testing-FirebaseABTesting_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseABTesting/FirebaseABTesting.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseABTesting.framework/Versions/A/Resources/FirebaseABTesting_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.ABTesting", + "logical": "FirebaseABTesting_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Firebase.iOS.Core" + ] + }, + { + "id": "Firebase.Analytics", + "project": "source/Firebase/Analytics/Analytics.csproj", + "package": "AdamE.Firebase.iOS.Analytics", + "assets": [ + { + "id": "firebase-analytics", + "path": "Firebase/FirebaseAnalytics/FirebaseAnalytics.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Analytics", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++ -lsqlite3 -lz", + "Frameworks": "StoreKit", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.0.1" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Firebase.iOS.Core", + "AdamE.Firebase.iOS.Installations", + "AdamE.Google.iOS.GoogleAppMeasurement" + ] + }, + { + "id": "Firebase.Auth", + "project": "source/Firebase/Auth/Auth.csproj", + "package": "AdamE.Firebase.iOS.Auth", + "assets": [ + { + "id": "firebase-auth", + "path": "Firebase/FirebaseAuth/FirebaseAuth.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Auth", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++ -lsqlite3 -lz", + "Frameworks": "Security SafariServices", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-auth-FirebaseAuth_Privacy.bundle-device", + "path": "Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-arm64/FirebaseAuth.framework/FirebaseAuth_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Auth", + "logical": "FirebaseAuth_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-auth-FirebaseAuth_Privacy.bundle-simulator", + "path": "Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-arm64_x86_64-simulator/FirebaseAuth.framework/FirebaseAuth_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Auth", + "logical": "FirebaseAuth_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-auth-FirebaseAuth_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseAuth.framework/Versions/A/Resources/FirebaseAuth_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Auth", + "logical": "FirebaseAuth_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Firebase.iOS.Core", + "AdamE.Google.iOS.GTMSessionFetcher" + ] + }, + { + "id": "Firebase.CloudFirestore", + "project": "source/Firebase/CloudFirestore/CloudFirestore.csproj", + "package": "AdamE.Firebase.iOS.CloudFirestore", + "assets": [ + { + "id": "firebase-firestore", + "path": "Firebase/FirebaseFirestore/FirebaseFirestore.xcframework", + "kind": "XCFramework", + "owner": "Firebase.CloudFirestore", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Frameworks": "MobileCoreServices SystemConfiguration", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-firestore-FirebaseFirestore_Privacy.bundle-device", + "path": "Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-arm64/FirebaseFirestore.framework/FirebaseFirestore_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "FirebaseFirestore_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-firestore-FirebaseFirestore_Privacy.bundle-simulator", + "path": "Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-arm64_x86_64-simulator/FirebaseFirestore.framework/FirebaseFirestore_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "FirebaseFirestore_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-firestore-FirebaseFirestore_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseFirestore.framework/Versions/A/Resources/FirebaseFirestore_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "FirebaseFirestore_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + }, + { + "id": "firebase-firestore-internal", + "path": "Firebase/FirebaseFirestore/FirebaseFirestoreInternal.xcframework", + "kind": "XCFramework", + "owner": "Firebase.CloudFirestore", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Frameworks": "MobileCoreServices SystemConfiguration UIKit Network", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-firestore-internal-FirebaseFirestoreInternal_Privacy.bundle-device", + "path": "Firebase/FirebaseFirestore/FirebaseFirestoreInternal.xcframework/ios-arm64/FirebaseFirestoreInternal.framework/FirebaseFirestoreInternal_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "FirebaseFirestoreInternal_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-firestore-internal-FirebaseFirestoreInternal_Privacy.bundle-simulator", + "path": "Firebase/FirebaseFirestore/FirebaseFirestoreInternal.xcframework/ios-arm64_x86_64-simulator/FirebaseFirestoreInternal.framework/FirebaseFirestoreInternal_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "FirebaseFirestoreInternal_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-firestore-internal-FirebaseFirestoreInternal_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseFirestore/FirebaseFirestoreInternal.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseFirestoreInternal.framework/Versions/A/Resources/FirebaseFirestoreInternal_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "FirebaseFirestoreInternal_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + }, + { + "id": "firebase-firestore-absl", + "path": "Firebase/FirebaseFirestore/absl.xcframework", + "kind": "XCFramework", + "owner": "Firebase.CloudFirestore", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "1.20250512.2" + }, + { + "id": "firebase-firestore-absl-xcprivacy.bundle-device", + "path": "Firebase/FirebaseFirestore/absl.xcframework/ios-arm64/absl.framework/xcprivacy.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "xcprivacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-firestore-absl-xcprivacy.bundle-simulator", + "path": "Firebase/FirebaseFirestore/absl.xcframework/ios-arm64_x86_64-simulator/absl.framework/xcprivacy.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "xcprivacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-firestore-absl-xcprivacy.bundle-catalyst", + "path": "Firebase/FirebaseFirestore/absl.xcframework/ios-arm64_x86_64-maccatalyst/absl.framework/Versions/A/Resources/xcprivacy.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "xcprivacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + }, + { + "id": "firebase-firestore-grpc", + "path": "Firebase/FirebaseFirestore/grpc.xcframework", + "kind": "XCFramework", + "owner": "Firebase.CloudFirestore", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++ -lz", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "1.83.1" + }, + { + "id": "firebase-firestore-grpc-grpc.bundle-device", + "path": "Firebase/FirebaseFirestore/grpc.xcframework/ios-arm64/grpc.framework/grpc.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "grpc.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-firestore-grpc-grpc.bundle-simulator", + "path": "Firebase/FirebaseFirestore/grpc.xcframework/ios-arm64_x86_64-simulator/grpc.framework/grpc.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "grpc.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-firestore-grpc-grpc.bundle-catalyst", + "path": "Firebase/FirebaseFirestore/grpc.xcframework/ios-arm64_x86_64-maccatalyst/grpc.framework/Versions/A/Resources/grpc.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "grpc.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + }, + { + "id": "firebase-firestore-grpcpp", + "path": "Firebase/FirebaseFirestore/grpcpp.xcframework", + "kind": "XCFramework", + "owner": "Firebase.CloudFirestore", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "1.83.1" + }, + { + "id": "firebase-firestore-grpcpp-grpcpp.bundle-device", + "path": "Firebase/FirebaseFirestore/grpcpp.xcframework/ios-arm64/grpcpp.framework/grpcpp.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "grpcpp.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-firestore-grpcpp-grpcpp.bundle-simulator", + "path": "Firebase/FirebaseFirestore/grpcpp.xcframework/ios-arm64_x86_64-simulator/grpcpp.framework/grpcpp.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "grpcpp.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-firestore-grpcpp-grpcpp.bundle-catalyst", + "path": "Firebase/FirebaseFirestore/grpcpp.xcframework/ios-arm64_x86_64-maccatalyst/grpcpp.framework/Versions/A/Resources/grpcpp.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "grpcpp.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + }, + { + "id": "firebase-firestore-openssl-grpc", + "path": "Firebase/FirebaseFirestore/openssl_grpc.xcframework", + "kind": "XCFramework", + "owner": "Firebase.CloudFirestore", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "0.0.42" + }, + { + "id": "firebase-firestore-openssl-grpc-openssl_grpc.bundle-device", + "path": "Firebase/FirebaseFirestore/openssl_grpc.xcframework/ios-arm64/openssl_grpc.framework/openssl_grpc.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "openssl_grpc.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-firestore-openssl-grpc-openssl_grpc.bundle-simulator", + "path": "Firebase/FirebaseFirestore/openssl_grpc.xcframework/ios-arm64_x86_64-simulator/openssl_grpc.framework/openssl_grpc.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "openssl_grpc.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-firestore-openssl-grpc-openssl_grpc.bundle-catalyst", + "path": "Firebase/FirebaseFirestore/openssl_grpc.xcframework/ios-arm64_x86_64-maccatalyst/openssl_grpc.framework/Versions/A/Resources/openssl_grpc.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudFirestore", + "logical": "openssl_grpc.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Firebase.iOS.Core" + ] + }, + { + "id": "Firebase.CloudFunctions", + "project": "source/Firebase/CloudFunctions/CloudFunctions.csproj", + "package": "AdamE.Firebase.iOS.CloudFunctions", + "assets": [ + { + "id": "firebase-functions", + "path": "Firebase/FirebaseFunctions/FirebaseFunctions.xcframework", + "kind": "XCFramework", + "owner": "Firebase.CloudFunctions", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Firebase.iOS.Core", + "AdamE.Google.iOS.GTMSessionFetcher" + ] + }, + { + "id": "Firebase.CloudMessaging", + "project": "source/Firebase/CloudMessaging/CloudMessaging.csproj", + "package": "AdamE.Firebase.iOS.CloudMessaging", + "assets": [ + { + "id": "firebase-messaging", + "path": "Firebase/FirebaseMessaging/FirebaseMessaging.xcframework", + "kind": "XCFramework", + "owner": "Firebase.CloudMessaging", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++ -lsqlite3", + "Frameworks": "SystemConfiguration", + "WeakFrameworks": "UserNotifications", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-messaging-FirebaseMessaging_Privacy.bundle-device", + "path": "Firebase/FirebaseMessaging/FirebaseMessaging.xcframework/ios-arm64/FirebaseMessaging.framework/FirebaseMessaging_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudMessaging", + "logical": "FirebaseMessaging_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-messaging-FirebaseMessaging_Privacy.bundle-simulator", + "path": "Firebase/FirebaseMessaging/FirebaseMessaging.xcframework/ios-arm64_x86_64-simulator/FirebaseMessaging.framework/FirebaseMessaging_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudMessaging", + "logical": "FirebaseMessaging_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-messaging-FirebaseMessaging_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseMessaging/FirebaseMessaging.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseMessaging.framework/Versions/A/Resources/FirebaseMessaging_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.CloudMessaging", + "logical": "FirebaseMessaging_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Firebase.iOS.Core", + "AdamE.Firebase.iOS.Installations" + ] + }, + { + "id": "Firebase.Core", + "project": "source/Firebase/Core/Core.csproj", + "package": "AdamE.Firebase.iOS.Core", + "assets": [ + { + "id": "firebase-core", + "path": "Firebase/FirebaseAnalytics/FirebaseCore.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Core", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Frameworks": "Foundation UIKit", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-core-FirebaseCore_Privacy.bundle-device", + "path": "Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-arm64/FirebaseCore.framework/FirebaseCore_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Core", + "logical": "FirebaseCore_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-core-FirebaseCore_Privacy.bundle-simulator", + "path": "Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-arm64_x86_64-simulator/FirebaseCore.framework/FirebaseCore_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Core", + "logical": "FirebaseCore_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-core-FirebaseCore_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseCore.framework/Versions/A/Resources/FirebaseCore_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Core", + "logical": "FirebaseCore_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + }, + { + "id": "firebase-core-internal", + "path": "Firebase/FirebaseAnalytics/FirebaseCoreInternal.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Core", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-core-internal-FirebaseCoreInternal_Privacy.bundle-device", + "path": "Firebase/FirebaseAnalytics/FirebaseCoreInternal.xcframework/ios-arm64/FirebaseCoreInternal.framework/FirebaseCoreInternal_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Core", + "logical": "FirebaseCoreInternal_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-core-internal-FirebaseCoreInternal_Privacy.bundle-simulator", + "path": "Firebase/FirebaseAnalytics/FirebaseCoreInternal.xcframework/ios-arm64_x86_64-simulator/FirebaseCoreInternal.framework/FirebaseCoreInternal_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Core", + "logical": "FirebaseCoreInternal_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-core-internal-FirebaseCoreInternal_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseAnalytics/FirebaseCoreInternal.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseCoreInternal.framework/Versions/A/Resources/FirebaseCoreInternal_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Core", + "logical": "FirebaseCoreInternal_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + }, + { + "id": "firebase-leveldb", + "path": "Firebase/FirebaseFirestore/leveldb.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Core", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "1.22.6" + }, + { + "id": "firebase-leveldb-leveldb_Privacy.bundle-device", + "path": "Firebase/FirebaseFirestore/leveldb.xcframework/ios-arm64/leveldb.framework/leveldb_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Core", + "logical": "leveldb_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-leveldb-leveldb_Privacy.bundle-simulator", + "path": "Firebase/FirebaseFirestore/leveldb.xcframework/ios-arm64_x86_64-simulator/leveldb.framework/leveldb_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Core", + "logical": "leveldb_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-leveldb-leveldb_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseFirestore/leveldb.xcframework/ios-arm64_x86_64-maccatalyst/leveldb.framework/Versions/A/Resources/leveldb_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Core", + "logical": "leveldb_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + }, + { + "id": "firebase-app-check-interop", + "path": "Firebase/FirebaseAppCheck/FirebaseAppCheckInterop.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Core", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-auth-interop", + "path": "Firebase/FirebaseAuth/FirebaseAuthInterop.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Core", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-core-extension", + "path": "Firebase/FirebaseAuth/FirebaseCoreExtension.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Core", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-core-extension-FirebaseCoreExtension_Privacy.bundle-device", + "path": "Firebase/FirebaseAuth/FirebaseCoreExtension.xcframework/ios-arm64/FirebaseCoreExtension.framework/FirebaseCoreExtension_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Core", + "logical": "FirebaseCoreExtension_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-core-extension-FirebaseCoreExtension_Privacy.bundle-simulator", + "path": "Firebase/FirebaseAuth/FirebaseCoreExtension.xcframework/ios-arm64_x86_64-simulator/FirebaseCoreExtension.framework/FirebaseCoreExtension_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Core", + "logical": "FirebaseCoreExtension_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-core-extension-FirebaseCoreExtension_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseAuth/FirebaseCoreExtension.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseCoreExtension.framework/Versions/A/Resources/FirebaseCoreExtension_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Core", + "logical": "FirebaseCoreExtension_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + }, + { + "id": "firebase-messaging-interop", + "path": "Firebase/FirebaseFunctions/FirebaseMessagingInterop.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Core", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-remote-config-interop", + "path": "Firebase/FirebaseRemoteConfig/FirebaseRemoteConfigInterop.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Core", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-shared-swift", + "path": "Firebase/FirebaseFunctions/FirebaseSharedSwift.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Core", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Google.iOS.AppCheckCore", + "AdamE.Google.iOS.GoogleDataTransport", + "AdamE.Google.iOS.GoogleUtilities", + "AdamE.Google.iOS.Nanopb", + "AdamE.Google.iOS.PromisesObjC" + ] + }, + { + "id": "Firebase.Crashlytics", + "project": "source/Firebase/Crashlytics/Crashlytics.csproj", + "package": "AdamE.Firebase.iOS.Crashlytics", + "assets": [ + { + "id": "firebase-crashlytics", + "path": "Firebase/FirebaseCrashlytics/FirebaseCrashlytics.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Crashlytics", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++ -lz", + "Frameworks": "Security SystemConfiguration", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-crashlytics-FirebaseCrashlytics_Privacy.bundle-device", + "path": "Firebase/FirebaseCrashlytics/FirebaseCrashlytics.xcframework/ios-arm64/FirebaseCrashlytics.framework/FirebaseCrashlytics_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Crashlytics", + "logical": "FirebaseCrashlytics_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-crashlytics-FirebaseCrashlytics_Privacy.bundle-simulator", + "path": "Firebase/FirebaseCrashlytics/FirebaseCrashlytics.xcframework/ios-arm64_x86_64-simulator/FirebaseCrashlytics.framework/FirebaseCrashlytics_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Crashlytics", + "logical": "FirebaseCrashlytics_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-crashlytics-FirebaseCrashlytics_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseCrashlytics/FirebaseCrashlytics.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseCrashlytics.framework/Versions/A/Resources/FirebaseCrashlytics_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Crashlytics", + "logical": "FirebaseCrashlytics_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + }, + { + "id": "firebase-crashlytics-run", + "path": "Firebase/FirebaseCrashlytics/run", + "kind": "Tool", + "owner": "Firebase.Crashlytics", + "logical": null, + "condition": null, + "sha256": "dda60b841d76e71a0c05afbbd2691fb80ec614565960a14df2b85b31065e531d" + }, + { + "id": "firebase-crashlytics-upload-symbols", + "path": "Firebase/FirebaseCrashlytics/upload-symbols", + "kind": "Tool", + "owner": "Firebase.Crashlytics", + "logical": null, + "condition": null, + "sha256": "ad9cd5816b9abe1f746ff37b073d3b3cf3a2dc835f1a1476bc30ba5bf66e2822" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Firebase.iOS.Core", + "AdamE.Firebase.iOS.Installations" + ] + }, + { + "id": "Firebase.Database", + "project": "source/Firebase/Database/Database.csproj", + "package": "AdamE.Firebase.iOS.Database", + "assets": [ + { + "id": "firebase-database", + "path": "Firebase/FirebaseDatabase/FirebaseDatabase.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Database", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++ -licucore", + "Frameworks": "CFNetwork Security SystemConfiguration", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Firebase.iOS.Core" + ] + }, + { + "id": "Firebase.InAppMessaging", + "project": "source/Firebase/InAppMessaging/InAppMessaging.csproj", + "package": "AdamE.Firebase.iOS.InAppMessaging", + "assets": [ + { + "id": "firebase-in-app-messaging", + "path": "Firebase/FirebaseInAppMessaging/FirebaseInAppMessaging.xcframework", + "kind": "XCFramework", + "owner": "Firebase.InAppMessaging", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Frameworks": "CoreTelephony QuartzCore SystemConfiguration UIKit", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-in-app-messaging-InAppMessagingDisplayResources.bundle-device", + "path": "Firebase/FirebaseInAppMessaging/FirebaseInAppMessaging.xcframework/ios-arm64/FirebaseInAppMessaging.framework/InAppMessagingDisplayResources.bundle", + "kind": "Bundle", + "owner": "Firebase.InAppMessaging", + "logical": "InAppMessagingDisplayResources.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-in-app-messaging-InAppMessagingDisplayResources.bundle-simulator", + "path": "Firebase/FirebaseInAppMessaging/FirebaseInAppMessaging.xcframework/ios-arm64_x86_64-simulator/FirebaseInAppMessaging.framework/InAppMessagingDisplayResources.bundle", + "kind": "Bundle", + "owner": "Firebase.InAppMessaging", + "logical": "InAppMessagingDisplayResources.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-in-app-messaging-InAppMessagingDisplayResources.bundle-catalyst", + "path": "Firebase/FirebaseInAppMessaging/FirebaseInAppMessaging.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseInAppMessaging.framework/Versions/A/Resources/InAppMessagingDisplayResources.bundle", + "kind": "Bundle", + "owner": "Firebase.InAppMessaging", + "logical": "InAppMessagingDisplayResources.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Firebase.iOS.ABTesting", + "AdamE.Firebase.iOS.Core", + "AdamE.Firebase.iOS.Installations" + ] + }, + { + "id": "Firebase.Installations", + "project": "source/Firebase/Installations/Installations.csproj", + "package": "AdamE.Firebase.iOS.Installations", + "assets": [ + { + "id": "firebase-installations", + "path": "Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Installations", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Frameworks": "Security", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-installations-FirebaseInstallations_Privacy.bundle-device", + "path": "Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-arm64/FirebaseInstallations.framework/FirebaseInstallations_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Installations", + "logical": "FirebaseInstallations_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-installations-FirebaseInstallations_Privacy.bundle-simulator", + "path": "Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-arm64_x86_64-simulator/FirebaseInstallations.framework/FirebaseInstallations_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Installations", + "logical": "FirebaseInstallations_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-installations-FirebaseInstallations_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseInstallations.framework/Versions/A/Resources/FirebaseInstallations_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.Installations", + "logical": "FirebaseInstallations_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + }, + { + "id": "firebase-sessions", + "path": "Firebase/FirebaseCrashlytics/FirebaseSessions.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Installations", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Firebase.iOS.Core" + ] + }, + { + "id": "Firebase.PerformanceMonitoring", + "project": "source/Firebase/PerformanceMonitoring/PerformanceMonitoring.csproj", + "package": "AdamE.Firebase.iOS.PerformanceMonitoring", + "assets": [ + { + "id": "firebase-performance", + "path": "Firebase/FirebasePerformance/FirebasePerformance.xcframework", + "kind": "XCFramework", + "owner": "Firebase.PerformanceMonitoring", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Frameworks": "CoreTelephony QuartzCore SystemConfiguration", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Firebase.iOS.ABTesting", + "AdamE.Firebase.iOS.Core", + "AdamE.Firebase.iOS.Installations", + "AdamE.Firebase.iOS.RemoteConfig" + ] + }, + { + "id": "Firebase.RemoteConfig", + "project": "source/Firebase/RemoteConfig/RemoteConfig.csproj", + "package": "AdamE.Firebase.iOS.RemoteConfig", + "assets": [ + { + "id": "firebase-remote-config", + "path": "Firebase/FirebaseRemoteConfig/FirebaseRemoteConfig.xcframework", + "kind": "XCFramework", + "owner": "Firebase.RemoteConfig", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++ -lsqlite3 -lz", + "Frameworks": "Security StoreKit SystemConfiguration", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + }, + { + "id": "firebase-remote-config-FirebaseRemoteConfig_Privacy.bundle-device", + "path": "Firebase/FirebaseRemoteConfig/FirebaseRemoteConfig.xcframework/ios-arm64/FirebaseRemoteConfig.framework/FirebaseRemoteConfig_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.RemoteConfig", + "logical": "FirebaseRemoteConfig_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-remote-config-FirebaseRemoteConfig_Privacy.bundle-simulator", + "path": "Firebase/FirebaseRemoteConfig/FirebaseRemoteConfig.xcframework/ios-arm64_x86_64-simulator/FirebaseRemoteConfig.framework/FirebaseRemoteConfig_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.RemoteConfig", + "logical": "FirebaseRemoteConfig_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "firebase-remote-config-FirebaseRemoteConfig_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseRemoteConfig/FirebaseRemoteConfig.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseRemoteConfig.framework/Versions/A/Resources/FirebaseRemoteConfig_Privacy.bundle", + "kind": "Bundle", + "owner": "Firebase.RemoteConfig", + "logical": "FirebaseRemoteConfig_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Firebase.iOS.ABTesting", + "AdamE.Firebase.iOS.Core", + "AdamE.Firebase.iOS.Installations" + ] + }, + { + "id": "Firebase.Storage", + "project": "source/Firebase/Storage/Storage.csproj", + "package": "AdamE.Firebase.iOS.Storage", + "assets": [ + { + "id": "firebase-storage", + "path": "Firebase/FirebaseStorage/FirebaseStorage.xcframework", + "kind": "XCFramework", + "owner": "Firebase.Storage", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Firebase.iOS.Core", + "AdamE.Google.iOS.GTMSessionFetcher" + ] + }, + { + "id": "Firebase.AppDistribution", + "project": "source/Firebase/AppDistribution/AppDistribution.csproj", + "package": "AdamE.Firebase.iOS.AppDistribution", + "assets": [ + { + "id": "firebase-app-distribution", + "path": "Firebase/FirebaseAppDistribution/FirebaseAppDistribution.xcframework", + "kind": "XCFramework", + "owner": "Firebase.AppDistribution", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Frameworks": "UIKit", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Firebase.iOS.Core", + "AdamE.Firebase.iOS.Installations" + ] + }, + { + "id": "Firebase.AppCheck", + "project": "source/Firebase/AppCheck/AppCheck.csproj", + "package": "AdamE.Firebase.iOS.AppCheck", + "assets": [ + { + "id": "firebase-app-check", + "path": "Firebase/FirebaseAppCheck/FirebaseAppCheck.xcframework", + "kind": "XCFramework", + "owner": "Firebase.AppCheck", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "WeakFrameworks": "DeviceCheck", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "13.1.1" + } + ], + "version": "13.1.1.0", + "dependencies": [ + "AdamE.Firebase.iOS.Core", + "AdamE.Google.iOS.AppCheckCore" + ] + }, + { + "id": "Google.AppCheckCore", + "project": "source/Google/AppCheckCore/AppCheckCore.csproj", + "package": "AdamE.Google.iOS.AppCheckCore", + "assets": [ + { + "id": "app-check-core", + "path": "Firebase/FirebaseAppCheck/AppCheckCore.xcframework", + "kind": "XCFramework", + "owner": "Google.AppCheckCore", + "logical": null, + "condition": null, + "metadata": { + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "IsCxx": "True", + "LinkWithSwiftSystemLibraries": "true", + "LinkerFlags": "-ObjC -lc++", + "WeakFrameworks": "DeviceCheck" + }, + "binaryVersion": "12.0.0" + }, + { + "id": "recaptcha-interop", + "path": "Firebase/FirebaseAuth/RecaptchaInterop.xcframework", + "kind": "XCFramework", + "owner": "Google.AppCheckCore", + "logical": null, + "condition": null, + "metadata": { + "LinkerFlags": "-ObjC -lc++", + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "LinkWithSwiftSystemLibraries": "true" + }, + "binaryVersion": "101.0.0" + } + ], + "version": "12.0.0.0", + "dependencies": [ + "AdamE.Google.iOS.GoogleUtilities", + "AdamE.Google.iOS.PromisesObjC" + ] + }, + { + "id": "Google.AppMeasurement", + "project": "source/Google/GoogleAppMeasurement/GoogleAppMeasurement.csproj", + "package": "AdamE.Google.iOS.GoogleAppMeasurement", + "assets": [ + { + "id": "google-app-measurement", + "path": "Firebase/FirebaseAnalytics/GoogleAppMeasurement.xcframework", + "kind": "XCFramework", + "owner": "Google.AppMeasurement", + "logical": null, + "condition": null, + "metadata": { + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "IsCxx": "True", + "LinkWithSwiftSystemLibraries": "true", + "LinkerFlags": "-ObjC -lc++ -lsqlite3 -lz", + "Frameworks": "StoreKit" + }, + "binaryVersion": "13.0.1" + }, + { + "id": "google-app-measurement-identity", + "path": "Firebase/FirebaseAnalytics/GoogleAppMeasurementIdentitySupport.xcframework", + "kind": "XCFramework", + "owner": "Google.AppMeasurement", + "logical": null, + "condition": "'$(FirebaseWithoutAdIdSupport)' != 'True'", + "metadata": { + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "IsCxx": "True", + "LinkWithSwiftSystemLibraries": "true", + "LinkerFlags": "-ObjC -lc++ -lsqlite3 -lz", + "Frameworks": "StoreKit" + }, + "binaryVersion": "13.0.1" + }, + { + "id": "google-ads-on-device-conversion", + "path": "Firebase/FirebaseAnalytics/GoogleAdsOnDeviceConversion.xcframework", + "kind": "XCFramework", + "owner": "Google.AppMeasurement", + "logical": null, + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And '$(FirebaseWithoutAdIdSupport)' != 'True'", + "metadata": { + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "IsCxx": "True", + "LinkWithSwiftSystemLibraries": "true", + "LinkerFlags": "-ObjC -lc++" + }, + "binaryVersion": "3.7.0" + } + ], + "version": "13.1.1.0", + "dependencies": [] + }, + { + "id": "Google.PromisesObjC", + "project": "source/Google/PromisesObjC/PromisesObjC.csproj", + "package": "AdamE.Google.iOS.PromisesObjC", + "assets": [ + { + "id": "fbl-promises", + "path": "Firebase/FirebaseAnalytics/FBLPromises.xcframework", + "kind": "XCFramework", + "owner": "Google.PromisesObjC", + "logical": null, + "condition": null, + "metadata": { + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "IsCxx": "True", + "LinkWithSwiftSystemLibraries": "true", + "LinkerFlags": "-ObjC -lc++" + }, + "binaryVersion": "2.4.1" + }, + { + "id": "fbl-promises-FBLPromises_Privacy.bundle-device", + "path": "Firebase/FirebaseAnalytics/FBLPromises.xcframework/ios-arm64/FBLPromises.framework/FBLPromises_Privacy.bundle", + "kind": "Bundle", + "owner": "Google.PromisesObjC", + "logical": "FBLPromises_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "fbl-promises-FBLPromises_Privacy.bundle-simulator", + "path": "Firebase/FirebaseAnalytics/FBLPromises.xcframework/ios-arm64_x86_64-simulator/FBLPromises.framework/FBLPromises_Privacy.bundle", + "kind": "Bundle", + "owner": "Google.PromisesObjC", + "logical": "FBLPromises_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "fbl-promises-FBLPromises_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseAnalytics/FBLPromises.xcframework/ios-arm64_x86_64-maccatalyst/FBLPromises.framework/Versions/A/Resources/FBLPromises_Privacy.bundle", + "kind": "Bundle", + "owner": "Google.PromisesObjC", + "logical": "FBLPromises_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + } + ], + "version": "2.4.1.0", + "dependencies": [] + }, + { + "id": "Google.GTMSessionFetcher", + "project": "source/Google/GTMSessionFetcher/GTMSessionFetcher.csproj", + "package": "AdamE.Google.iOS.GTMSessionFetcher", + "assets": [ + { + "id": "gtm-session-fetcher", + "path": "Firebase/FirebaseAuth/GTMSessionFetcher.xcframework", + "kind": "XCFramework", + "owner": "Google.GTMSessionFetcher", + "logical": null, + "condition": null, + "metadata": { + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "IsCxx": "True", + "LinkWithSwiftSystemLibraries": "true", + "LinkerFlags": "-ObjC -lc++" + }, + "binaryVersion": "5.3.1" + }, + { + "id": "gtm-session-fetcher-GTMSessionFetcher_Core_Privacy.bundle-device", + "path": "Firebase/FirebaseAuth/GTMSessionFetcher.xcframework/ios-arm64/GTMSessionFetcher.framework/GTMSessionFetcher_Core_Privacy.bundle", + "kind": "Bundle", + "owner": "Google.GTMSessionFetcher", + "logical": "GTMSessionFetcher_Core_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "gtm-session-fetcher-GTMSessionFetcher_Core_Privacy.bundle-simulator", + "path": "Firebase/FirebaseAuth/GTMSessionFetcher.xcframework/ios-arm64_x86_64-simulator/GTMSessionFetcher.framework/GTMSessionFetcher_Core_Privacy.bundle", + "kind": "Bundle", + "owner": "Google.GTMSessionFetcher", + "logical": "GTMSessionFetcher_Core_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "gtm-session-fetcher-GTMSessionFetcher_Core_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseAuth/GTMSessionFetcher.xcframework/ios-arm64_x86_64-maccatalyst/GTMSessionFetcher.framework/Versions/A/Resources/GTMSessionFetcher_Core_Privacy.bundle", + "kind": "Bundle", + "owner": "Google.GTMSessionFetcher", + "logical": "GTMSessionFetcher_Core_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + } + ], + "version": "5.3.1.0", + "dependencies": [] + }, + { + "id": "Google.Nanopb", + "project": "source/Google/Nanopb/Nanopb.csproj", + "package": "AdamE.Google.iOS.Nanopb", + "assets": [ + { + "id": "nanopb", + "path": "Firebase/FirebaseAnalytics/nanopb.xcframework", + "kind": "XCFramework", + "owner": "Google.Nanopb", + "logical": null, + "condition": null, + "metadata": { + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "IsCxx": "True", + "LinkWithSwiftSystemLibraries": "true", + "LinkerFlags": "-ObjC -lc++" + }, + "binaryVersion": "3.30910.0" + }, + { + "id": "nanopb-nanopb_Privacy.bundle-device", + "path": "Firebase/FirebaseAnalytics/nanopb.xcframework/ios-arm64/nanopb.framework/nanopb_Privacy.bundle", + "kind": "Bundle", + "owner": "Google.Nanopb", + "logical": "nanopb_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "nanopb-nanopb_Privacy.bundle-simulator", + "path": "Firebase/FirebaseAnalytics/nanopb.xcframework/ios-arm64_x86_64-simulator/nanopb.framework/nanopb_Privacy.bundle", + "kind": "Bundle", + "owner": "Google.Nanopb", + "logical": "nanopb_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "nanopb-nanopb_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseAnalytics/nanopb.xcframework/ios-arm64_x86_64-maccatalyst/nanopb.framework/Versions/A/Resources/nanopb_Privacy.bundle", + "kind": "Bundle", + "owner": "Google.Nanopb", + "logical": "nanopb_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + } + ], + "version": "3.30910.0.7", + "dependencies": [] + }, + { + "id": "Google.GoogleUtilities", + "project": "source/Google/GoogleUtilities/GoogleUtilities.csproj", + "package": "AdamE.Google.iOS.GoogleUtilities", + "assets": [ + { + "id": "google-utilities", + "path": "Firebase/FirebaseAnalytics/GoogleUtilities.xcframework", + "kind": "XCFramework", + "owner": "Google.GoogleUtilities", + "logical": null, + "condition": null, + "metadata": { + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "IsCxx": "True", + "LinkWithSwiftSystemLibraries": "true", + "LinkerFlags": "-ObjC -lc++", + "Frameworks": "Security SystemConfiguration" + }, + "binaryVersion": "8.1.5" + }, + { + "id": "google-utilities-GoogleUtilities_Privacy.bundle-device", + "path": "Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-arm64/GoogleUtilities.framework/GoogleUtilities_Privacy.bundle", + "kind": "Bundle", + "owner": "Google.GoogleUtilities", + "logical": "GoogleUtilities_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "google-utilities-GoogleUtilities_Privacy.bundle-simulator", + "path": "Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-arm64_x86_64-simulator/GoogleUtilities.framework/GoogleUtilities_Privacy.bundle", + "kind": "Bundle", + "owner": "Google.GoogleUtilities", + "logical": "GoogleUtilities_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "google-utilities-GoogleUtilities_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-arm64_x86_64-maccatalyst/GoogleUtilities.framework/Versions/A/Resources/GoogleUtilities_Privacy.bundle", + "kind": "Bundle", + "owner": "Google.GoogleUtilities", + "logical": "GoogleUtilities_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + } + ], + "version": "8.1.5.1", + "dependencies": [] + }, + { + "id": "Google.GoogleDataTransport", + "project": "source/Google/GoogleDataTransport/GoogleDataTransport.csproj", + "package": "AdamE.Google.iOS.GoogleDataTransport", + "assets": [ + { + "id": "google-data-transport", + "path": "Firebase/FirebaseCrashlytics/GoogleDataTransport.xcframework", + "kind": "XCFramework", + "owner": "Google.GoogleDataTransport", + "logical": null, + "condition": null, + "metadata": { + "Kind": "Framework", + "SmartLink": "True", + "ForceLoad": "True", + "IsCxx": "True", + "LinkWithSwiftSystemLibraries": "true", + "LinkerFlags": "-ObjC -lc++", + "Frameworks": "SystemConfiguration CoreTelephony" + }, + "binaryVersion": "10.1.1" + }, + { + "id": "google-data-transport-GoogleDataTransport_Privacy.bundle-device", + "path": "Firebase/FirebaseCrashlytics/GoogleDataTransport.xcframework/ios-arm64/GoogleDataTransport.framework/GoogleDataTransport_Privacy.bundle", + "kind": "Bundle", + "owner": "Google.GoogleDataTransport", + "logical": "GoogleDataTransport_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "google-data-transport-GoogleDataTransport_Privacy.bundle-simulator", + "path": "Firebase/FirebaseCrashlytics/GoogleDataTransport.xcframework/ios-arm64_x86_64-simulator/GoogleDataTransport.framework/GoogleDataTransport_Privacy.bundle", + "kind": "Bundle", + "owner": "Google.GoogleDataTransport", + "logical": "GoogleDataTransport_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" + }, + { + "id": "google-data-transport-GoogleDataTransport_Privacy.bundle-catalyst", + "path": "Firebase/FirebaseCrashlytics/GoogleDataTransport.xcframework/ios-arm64_x86_64-maccatalyst/GoogleDataTransport.framework/Versions/A/Resources/GoogleDataTransport_Privacy.bundle", + "kind": "Bundle", + "owner": "Google.GoogleDataTransport", + "logical": "GoogleDataTransport_Privacy.bundle", + "condition": "'$(TargetPlatformIdentifier)' == 'maccatalyst'" + } + ], + "version": "10.1.1.0", + "dependencies": [ + "AdamE.Google.iOS.Nanopb", + "AdamE.Google.iOS.PromisesObjC" + ] + } + ] +} diff --git a/source/Firebase/native/AdamE.Firebase.iOS.ABTesting.targets b/source/Firebase/native/AdamE.Firebase.iOS.ABTesting.targets new file mode 100644 index 00000000..b47fa9c3 --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.ABTesting.targets @@ -0,0 +1,37 @@ + + + + + + + + + + -ObjC -lc++ -lz + Security SystemConfiguration + Framework + True + True + true + + <_FirebaseBundle_firebase_ab_testing_FirebaseABTesting_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseABTesting/FirebaseABTesting.xcframework/ios-arm64/FirebaseABTesting.framework/FirebaseABTesting_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_ab_testing_FirebaseABTesting_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseABTesting/FirebaseABTesting.xcframework/ios-arm64_x86_64-simulator/FirebaseABTesting.framework/FirebaseABTesting_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_ab_testing_FirebaseABTesting_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseABTesting/FirebaseABTesting.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseABTesting.framework/Versions/A/Resources/FirebaseABTesting_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + + + FirebaseABTesting_Privacy.bundle/%(_FirebaseBundle_firebase_ab_testing_FirebaseABTesting_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_ab_testing_FirebaseABTesting_Privacy_bundle_device.Filename)%(_FirebaseBundle_firebase_ab_testing_FirebaseABTesting_Privacy_bundle_device.Extension) + + + + + FirebaseABTesting_Privacy.bundle/%(_FirebaseBundle_firebase_ab_testing_FirebaseABTesting_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_ab_testing_FirebaseABTesting_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_firebase_ab_testing_FirebaseABTesting_Privacy_bundle_simulator.Extension) + + + + + FirebaseABTesting_Privacy.bundle/%(_FirebaseBundle_firebase_ab_testing_FirebaseABTesting_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_ab_testing_FirebaseABTesting_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_ab_testing_FirebaseABTesting_Privacy_bundle_catalyst.Extension) + + + + diff --git a/source/Firebase/native/AdamE.Firebase.iOS.Analytics.targets b/source/Firebase/native/AdamE.Firebase.iOS.Analytics.targets new file mode 100644 index 00000000..31425493 --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.Analytics.targets @@ -0,0 +1,16 @@ + + + + + + + -ObjC -lc++ -lsqlite3 -lz + StoreKit + Framework + True + True + true + + + + diff --git a/source/Firebase/native/AdamE.Firebase.iOS.AppCheck.targets b/source/Firebase/native/AdamE.Firebase.iOS.AppCheck.targets new file mode 100644 index 00000000..55addd64 --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.AppCheck.targets @@ -0,0 +1,16 @@ + + + + + + + -ObjC -lc++ + DeviceCheck + Framework + True + True + true + + + + diff --git a/source/Firebase/native/AdamE.Firebase.iOS.AppDistribution.targets b/source/Firebase/native/AdamE.Firebase.iOS.AppDistribution.targets new file mode 100644 index 00000000..9d3a2b69 --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.AppDistribution.targets @@ -0,0 +1,16 @@ + + + + + + + -ObjC -lc++ + UIKit + Framework + True + True + true + + + + diff --git a/source/Firebase/native/AdamE.Firebase.iOS.Auth.targets b/source/Firebase/native/AdamE.Firebase.iOS.Auth.targets new file mode 100644 index 00000000..a0158425 --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.Auth.targets @@ -0,0 +1,37 @@ + + + + + + + + + + -ObjC -lc++ -lsqlite3 -lz + Security SafariServices + Framework + True + True + true + + <_FirebaseBundle_firebase_auth_FirebaseAuth_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-arm64/FirebaseAuth.framework/FirebaseAuth_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_auth_FirebaseAuth_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-arm64_x86_64-simulator/FirebaseAuth.framework/FirebaseAuth_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_auth_FirebaseAuth_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseAuth/FirebaseAuth.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseAuth.framework/Versions/A/Resources/FirebaseAuth_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + + + FirebaseAuth_Privacy.bundle/%(_FirebaseBundle_firebase_auth_FirebaseAuth_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_auth_FirebaseAuth_Privacy_bundle_device.Filename)%(_FirebaseBundle_firebase_auth_FirebaseAuth_Privacy_bundle_device.Extension) + + + + + FirebaseAuth_Privacy.bundle/%(_FirebaseBundle_firebase_auth_FirebaseAuth_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_auth_FirebaseAuth_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_firebase_auth_FirebaseAuth_Privacy_bundle_simulator.Extension) + + + + + FirebaseAuth_Privacy.bundle/%(_FirebaseBundle_firebase_auth_FirebaseAuth_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_auth_FirebaseAuth_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_auth_FirebaseAuth_Privacy_bundle_catalyst.Extension) + + + + diff --git a/source/Firebase/native/AdamE.Firebase.iOS.CloudFirestore.targets b/source/Firebase/native/AdamE.Firebase.iOS.CloudFirestore.targets new file mode 100644 index 00000000..e560131a --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.CloudFirestore.targets @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -ObjC -lc++ + MobileCoreServices SystemConfiguration + Framework + True + True + true + + <_FirebaseBundle_firebase_firestore_FirebaseFirestore_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-arm64/FirebaseFirestore.framework/FirebaseFirestore_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_firestore_FirebaseFirestore_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-arm64_x86_64-simulator/FirebaseFirestore.framework/FirebaseFirestore_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_firestore_FirebaseFirestore_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/FirebaseFirestore.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseFirestore.framework/Versions/A/Resources/FirebaseFirestore_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + -ObjC -lc++ + MobileCoreServices SystemConfiguration UIKit Network + Framework + True + True + true + + <_FirebaseBundle_firebase_firestore_internal_FirebaseFirestoreInternal_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/FirebaseFirestoreInternal.xcframework/ios-arm64/FirebaseFirestoreInternal.framework/FirebaseFirestoreInternal_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_firestore_internal_FirebaseFirestoreInternal_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/FirebaseFirestoreInternal.xcframework/ios-arm64_x86_64-simulator/FirebaseFirestoreInternal.framework/FirebaseFirestoreInternal_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_firestore_internal_FirebaseFirestoreInternal_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/FirebaseFirestoreInternal.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseFirestoreInternal.framework/Versions/A/Resources/FirebaseFirestoreInternal_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + -ObjC -lc++ + Framework + True + True + true + + <_FirebaseBundle_firebase_firestore_absl_xcprivacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/absl.xcframework/ios-arm64/absl.framework/xcprivacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_firestore_absl_xcprivacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/absl.xcframework/ios-arm64_x86_64-simulator/absl.framework/xcprivacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_firestore_absl_xcprivacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/absl.xcframework/ios-arm64_x86_64-maccatalyst/absl.framework/Versions/A/Resources/xcprivacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + -ObjC -lc++ -lz + Framework + True + True + true + + <_FirebaseBundle_firebase_firestore_grpc_grpc_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/grpc.xcframework/ios-arm64/grpc.framework/grpc.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_firestore_grpc_grpc_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/grpc.xcframework/ios-arm64_x86_64-simulator/grpc.framework/grpc.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_firestore_grpc_grpc_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/grpc.xcframework/ios-arm64_x86_64-maccatalyst/grpc.framework/Versions/A/Resources/grpc.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + -ObjC -lc++ + Framework + True + True + true + + <_FirebaseBundle_firebase_firestore_grpcpp_grpcpp_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/grpcpp.xcframework/ios-arm64/grpcpp.framework/grpcpp.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_firestore_grpcpp_grpcpp_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/grpcpp.xcframework/ios-arm64_x86_64-simulator/grpcpp.framework/grpcpp.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_firestore_grpcpp_grpcpp_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/grpcpp.xcframework/ios-arm64_x86_64-maccatalyst/grpcpp.framework/Versions/A/Resources/grpcpp.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + -ObjC -lc++ + Framework + True + True + true + + <_FirebaseBundle_firebase_firestore_openssl_grpc_openssl_grpc_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/openssl_grpc.xcframework/ios-arm64/openssl_grpc.framework/openssl_grpc.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_firestore_openssl_grpc_openssl_grpc_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/openssl_grpc.xcframework/ios-arm64_x86_64-simulator/openssl_grpc.framework/openssl_grpc.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_firestore_openssl_grpc_openssl_grpc_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/openssl_grpc.xcframework/ios-arm64_x86_64-maccatalyst/openssl_grpc.framework/Versions/A/Resources/openssl_grpc.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + + + FirebaseFirestore_Privacy.bundle/%(_FirebaseBundle_firebase_firestore_FirebaseFirestore_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_firestore_FirebaseFirestore_Privacy_bundle_device.Filename)%(_FirebaseBundle_firebase_firestore_FirebaseFirestore_Privacy_bundle_device.Extension) + + + + + FirebaseFirestore_Privacy.bundle/%(_FirebaseBundle_firebase_firestore_FirebaseFirestore_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_firestore_FirebaseFirestore_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_firebase_firestore_FirebaseFirestore_Privacy_bundle_simulator.Extension) + + + + + FirebaseFirestore_Privacy.bundle/%(_FirebaseBundle_firebase_firestore_FirebaseFirestore_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_firestore_FirebaseFirestore_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_firestore_FirebaseFirestore_Privacy_bundle_catalyst.Extension) + + + + + FirebaseFirestoreInternal_Privacy.bundle/%(_FirebaseBundle_firebase_firestore_internal_FirebaseFirestoreInternal_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_firestore_internal_FirebaseFirestoreInternal_Privacy_bundle_device.Filename)%(_FirebaseBundle_firebase_firestore_internal_FirebaseFirestoreInternal_Privacy_bundle_device.Extension) + + + + + FirebaseFirestoreInternal_Privacy.bundle/%(_FirebaseBundle_firebase_firestore_internal_FirebaseFirestoreInternal_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_firestore_internal_FirebaseFirestoreInternal_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_firebase_firestore_internal_FirebaseFirestoreInternal_Privacy_bundle_simulator.Extension) + + + + + FirebaseFirestoreInternal_Privacy.bundle/%(_FirebaseBundle_firebase_firestore_internal_FirebaseFirestoreInternal_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_firestore_internal_FirebaseFirestoreInternal_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_firestore_internal_FirebaseFirestoreInternal_Privacy_bundle_catalyst.Extension) + + + + + xcprivacy.bundle/%(_FirebaseBundle_firebase_firestore_absl_xcprivacy_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_firestore_absl_xcprivacy_bundle_device.Filename)%(_FirebaseBundle_firebase_firestore_absl_xcprivacy_bundle_device.Extension) + + + + + xcprivacy.bundle/%(_FirebaseBundle_firebase_firestore_absl_xcprivacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_firestore_absl_xcprivacy_bundle_simulator.Filename)%(_FirebaseBundle_firebase_firestore_absl_xcprivacy_bundle_simulator.Extension) + + + + + xcprivacy.bundle/%(_FirebaseBundle_firebase_firestore_absl_xcprivacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_firestore_absl_xcprivacy_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_firestore_absl_xcprivacy_bundle_catalyst.Extension) + + + + + grpc.bundle/%(_FirebaseBundle_firebase_firestore_grpc_grpc_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_firestore_grpc_grpc_bundle_device.Filename)%(_FirebaseBundle_firebase_firestore_grpc_grpc_bundle_device.Extension) + + + + + grpc.bundle/%(_FirebaseBundle_firebase_firestore_grpc_grpc_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_firestore_grpc_grpc_bundle_simulator.Filename)%(_FirebaseBundle_firebase_firestore_grpc_grpc_bundle_simulator.Extension) + + + + + grpc.bundle/%(_FirebaseBundle_firebase_firestore_grpc_grpc_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_firestore_grpc_grpc_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_firestore_grpc_grpc_bundle_catalyst.Extension) + + + + + grpcpp.bundle/%(_FirebaseBundle_firebase_firestore_grpcpp_grpcpp_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_firestore_grpcpp_grpcpp_bundle_device.Filename)%(_FirebaseBundle_firebase_firestore_grpcpp_grpcpp_bundle_device.Extension) + + + + + grpcpp.bundle/%(_FirebaseBundle_firebase_firestore_grpcpp_grpcpp_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_firestore_grpcpp_grpcpp_bundle_simulator.Filename)%(_FirebaseBundle_firebase_firestore_grpcpp_grpcpp_bundle_simulator.Extension) + + + + + grpcpp.bundle/%(_FirebaseBundle_firebase_firestore_grpcpp_grpcpp_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_firestore_grpcpp_grpcpp_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_firestore_grpcpp_grpcpp_bundle_catalyst.Extension) + + + + + openssl_grpc.bundle/%(_FirebaseBundle_firebase_firestore_openssl_grpc_openssl_grpc_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_firestore_openssl_grpc_openssl_grpc_bundle_device.Filename)%(_FirebaseBundle_firebase_firestore_openssl_grpc_openssl_grpc_bundle_device.Extension) + + + + + openssl_grpc.bundle/%(_FirebaseBundle_firebase_firestore_openssl_grpc_openssl_grpc_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_firestore_openssl_grpc_openssl_grpc_bundle_simulator.Filename)%(_FirebaseBundle_firebase_firestore_openssl_grpc_openssl_grpc_bundle_simulator.Extension) + + + + + openssl_grpc.bundle/%(_FirebaseBundle_firebase_firestore_openssl_grpc_openssl_grpc_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_firestore_openssl_grpc_openssl_grpc_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_firestore_openssl_grpc_openssl_grpc_bundle_catalyst.Extension) + + + + diff --git a/source/Firebase/native/AdamE.Firebase.iOS.CloudFunctions.targets b/source/Firebase/native/AdamE.Firebase.iOS.CloudFunctions.targets new file mode 100644 index 00000000..76427162 --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.CloudFunctions.targets @@ -0,0 +1,15 @@ + + + + + + + -ObjC -lc++ + Framework + True + True + true + + + + diff --git a/source/Firebase/native/AdamE.Firebase.iOS.CloudMessaging.targets b/source/Firebase/native/AdamE.Firebase.iOS.CloudMessaging.targets new file mode 100644 index 00000000..a1d83603 --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.CloudMessaging.targets @@ -0,0 +1,38 @@ + + + + + + + + + + -ObjC -lc++ -lsqlite3 + SystemConfiguration + UserNotifications + Framework + True + True + true + + <_FirebaseBundle_firebase_messaging_FirebaseMessaging_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseMessaging/FirebaseMessaging.xcframework/ios-arm64/FirebaseMessaging.framework/FirebaseMessaging_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_messaging_FirebaseMessaging_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseMessaging/FirebaseMessaging.xcframework/ios-arm64_x86_64-simulator/FirebaseMessaging.framework/FirebaseMessaging_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_messaging_FirebaseMessaging_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseMessaging/FirebaseMessaging.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseMessaging.framework/Versions/A/Resources/FirebaseMessaging_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + + + FirebaseMessaging_Privacy.bundle/%(_FirebaseBundle_firebase_messaging_FirebaseMessaging_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_messaging_FirebaseMessaging_Privacy_bundle_device.Filename)%(_FirebaseBundle_firebase_messaging_FirebaseMessaging_Privacy_bundle_device.Extension) + + + + + FirebaseMessaging_Privacy.bundle/%(_FirebaseBundle_firebase_messaging_FirebaseMessaging_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_messaging_FirebaseMessaging_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_firebase_messaging_FirebaseMessaging_Privacy_bundle_simulator.Extension) + + + + + FirebaseMessaging_Privacy.bundle/%(_FirebaseBundle_firebase_messaging_FirebaseMessaging_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_messaging_FirebaseMessaging_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_messaging_FirebaseMessaging_Privacy_bundle_catalyst.Extension) + + + + diff --git a/source/Firebase/native/AdamE.Firebase.iOS.Core.targets b/source/Firebase/native/AdamE.Firebase.iOS.Core.targets new file mode 100644 index 00000000..865330cf --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.Core.targets @@ -0,0 +1,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + -ObjC -lc++ + Foundation UIKit + Framework + True + True + true + + <_FirebaseBundle_firebase_core_FirebaseCore_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-arm64/FirebaseCore.framework/FirebaseCore_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_core_FirebaseCore_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-arm64_x86_64-simulator/FirebaseCore.framework/FirebaseCore_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_core_FirebaseCore_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/FirebaseCore.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseCore.framework/Versions/A/Resources/FirebaseCore_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + -ObjC -lc++ + Framework + True + True + true + + <_FirebaseBundle_firebase_core_internal_FirebaseCoreInternal_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/FirebaseCoreInternal.xcframework/ios-arm64/FirebaseCoreInternal.framework/FirebaseCoreInternal_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_core_internal_FirebaseCoreInternal_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/FirebaseCoreInternal.xcframework/ios-arm64_x86_64-simulator/FirebaseCoreInternal.framework/FirebaseCoreInternal_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_core_internal_FirebaseCoreInternal_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/FirebaseCoreInternal.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseCoreInternal.framework/Versions/A/Resources/FirebaseCoreInternal_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + -ObjC -lc++ + Framework + True + True + true + + <_FirebaseBundle_firebase_leveldb_leveldb_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/leveldb.xcframework/ios-arm64/leveldb.framework/leveldb_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_leveldb_leveldb_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/leveldb.xcframework/ios-arm64_x86_64-simulator/leveldb.framework/leveldb_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_leveldb_leveldb_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseFirestore/leveldb.xcframework/ios-arm64_x86_64-maccatalyst/leveldb.framework/Versions/A/Resources/leveldb_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + -ObjC -lc++ + Framework + True + True + true + + + -ObjC -lc++ + Framework + True + True + true + + + -ObjC -lc++ + Framework + True + True + true + + <_FirebaseBundle_firebase_core_extension_FirebaseCoreExtension_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseAuth/FirebaseCoreExtension.xcframework/ios-arm64/FirebaseCoreExtension.framework/FirebaseCoreExtension_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_core_extension_FirebaseCoreExtension_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseAuth/FirebaseCoreExtension.xcframework/ios-arm64_x86_64-simulator/FirebaseCoreExtension.framework/FirebaseCoreExtension_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_core_extension_FirebaseCoreExtension_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseAuth/FirebaseCoreExtension.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseCoreExtension.framework/Versions/A/Resources/FirebaseCoreExtension_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + -ObjC -lc++ + Framework + True + True + true + + + -ObjC -lc++ + Framework + True + True + true + + + -ObjC -lc++ + Framework + True + True + true + + + + + FirebaseCore_Privacy.bundle/%(_FirebaseBundle_firebase_core_FirebaseCore_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_core_FirebaseCore_Privacy_bundle_device.Filename)%(_FirebaseBundle_firebase_core_FirebaseCore_Privacy_bundle_device.Extension) + + + + + FirebaseCore_Privacy.bundle/%(_FirebaseBundle_firebase_core_FirebaseCore_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_core_FirebaseCore_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_firebase_core_FirebaseCore_Privacy_bundle_simulator.Extension) + + + + + FirebaseCore_Privacy.bundle/%(_FirebaseBundle_firebase_core_FirebaseCore_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_core_FirebaseCore_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_core_FirebaseCore_Privacy_bundle_catalyst.Extension) + + + + + FirebaseCoreInternal_Privacy.bundle/%(_FirebaseBundle_firebase_core_internal_FirebaseCoreInternal_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_core_internal_FirebaseCoreInternal_Privacy_bundle_device.Filename)%(_FirebaseBundle_firebase_core_internal_FirebaseCoreInternal_Privacy_bundle_device.Extension) + + + + + FirebaseCoreInternal_Privacy.bundle/%(_FirebaseBundle_firebase_core_internal_FirebaseCoreInternal_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_core_internal_FirebaseCoreInternal_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_firebase_core_internal_FirebaseCoreInternal_Privacy_bundle_simulator.Extension) + + + + + FirebaseCoreInternal_Privacy.bundle/%(_FirebaseBundle_firebase_core_internal_FirebaseCoreInternal_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_core_internal_FirebaseCoreInternal_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_core_internal_FirebaseCoreInternal_Privacy_bundle_catalyst.Extension) + + + + + leveldb_Privacy.bundle/%(_FirebaseBundle_firebase_leveldb_leveldb_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_leveldb_leveldb_Privacy_bundle_device.Filename)%(_FirebaseBundle_firebase_leveldb_leveldb_Privacy_bundle_device.Extension) + + + + + leveldb_Privacy.bundle/%(_FirebaseBundle_firebase_leveldb_leveldb_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_leveldb_leveldb_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_firebase_leveldb_leveldb_Privacy_bundle_simulator.Extension) + + + + + leveldb_Privacy.bundle/%(_FirebaseBundle_firebase_leveldb_leveldb_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_leveldb_leveldb_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_leveldb_leveldb_Privacy_bundle_catalyst.Extension) + + + + + FirebaseCoreExtension_Privacy.bundle/%(_FirebaseBundle_firebase_core_extension_FirebaseCoreExtension_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_core_extension_FirebaseCoreExtension_Privacy_bundle_device.Filename)%(_FirebaseBundle_firebase_core_extension_FirebaseCoreExtension_Privacy_bundle_device.Extension) + + + + + FirebaseCoreExtension_Privacy.bundle/%(_FirebaseBundle_firebase_core_extension_FirebaseCoreExtension_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_core_extension_FirebaseCoreExtension_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_firebase_core_extension_FirebaseCoreExtension_Privacy_bundle_simulator.Extension) + + + + + FirebaseCoreExtension_Privacy.bundle/%(_FirebaseBundle_firebase_core_extension_FirebaseCoreExtension_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_core_extension_FirebaseCoreExtension_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_core_extension_FirebaseCoreExtension_Privacy_bundle_catalyst.Extension) + + + + diff --git a/source/Firebase/native/AdamE.Firebase.iOS.Crashlytics.targets b/source/Firebase/native/AdamE.Firebase.iOS.Crashlytics.targets new file mode 100644 index 00000000..8a903c79 --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.Crashlytics.targets @@ -0,0 +1,40 @@ + + + + + + + + + + + + -ObjC -lc++ -lz + Security SystemConfiguration + Framework + True + True + true + + <_FirebaseBundle_firebase_crashlytics_FirebaseCrashlytics_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseCrashlytics/FirebaseCrashlytics.xcframework/ios-arm64/FirebaseCrashlytics.framework/FirebaseCrashlytics_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_crashlytics_FirebaseCrashlytics_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseCrashlytics/FirebaseCrashlytics.xcframework/ios-arm64_x86_64-simulator/FirebaseCrashlytics.framework/FirebaseCrashlytics_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_crashlytics_FirebaseCrashlytics_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseCrashlytics/FirebaseCrashlytics.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseCrashlytics.framework/Versions/A/Resources/FirebaseCrashlytics_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + + + FirebaseCrashlytics_Privacy.bundle/%(_FirebaseBundle_firebase_crashlytics_FirebaseCrashlytics_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_crashlytics_FirebaseCrashlytics_Privacy_bundle_device.Filename)%(_FirebaseBundle_firebase_crashlytics_FirebaseCrashlytics_Privacy_bundle_device.Extension) + + + + + FirebaseCrashlytics_Privacy.bundle/%(_FirebaseBundle_firebase_crashlytics_FirebaseCrashlytics_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_crashlytics_FirebaseCrashlytics_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_firebase_crashlytics_FirebaseCrashlytics_Privacy_bundle_simulator.Extension) + + + + + FirebaseCrashlytics_Privacy.bundle/%(_FirebaseBundle_firebase_crashlytics_FirebaseCrashlytics_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_crashlytics_FirebaseCrashlytics_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_crashlytics_FirebaseCrashlytics_Privacy_bundle_catalyst.Extension) + + + + + diff --git a/source/Firebase/native/AdamE.Firebase.iOS.Database.targets b/source/Firebase/native/AdamE.Firebase.iOS.Database.targets new file mode 100644 index 00000000..6d97839f --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.Database.targets @@ -0,0 +1,16 @@ + + + + + + + -ObjC -lc++ -licucore + CFNetwork Security SystemConfiguration + Framework + True + True + true + + + + diff --git a/source/Firebase/native/AdamE.Firebase.iOS.InAppMessaging.targets b/source/Firebase/native/AdamE.Firebase.iOS.InAppMessaging.targets new file mode 100644 index 00000000..b83e9275 --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.InAppMessaging.targets @@ -0,0 +1,37 @@ + + + + + + + + + + -ObjC -lc++ + CoreTelephony QuartzCore SystemConfiguration UIKit + Framework + True + True + true + + <_FirebaseBundle_firebase_in_app_messaging_InAppMessagingDisplayResources_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseInAppMessaging/FirebaseInAppMessaging.xcframework/ios-arm64/FirebaseInAppMessaging.framework/InAppMessagingDisplayResources.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_in_app_messaging_InAppMessagingDisplayResources_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseInAppMessaging/FirebaseInAppMessaging.xcframework/ios-arm64_x86_64-simulator/FirebaseInAppMessaging.framework/InAppMessagingDisplayResources.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_in_app_messaging_InAppMessagingDisplayResources_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseInAppMessaging/FirebaseInAppMessaging.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseInAppMessaging.framework/Versions/A/Resources/InAppMessagingDisplayResources.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + + + InAppMessagingDisplayResources.bundle/%(_FirebaseBundle_firebase_in_app_messaging_InAppMessagingDisplayResources_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_in_app_messaging_InAppMessagingDisplayResources_bundle_device.Filename)%(_FirebaseBundle_firebase_in_app_messaging_InAppMessagingDisplayResources_bundle_device.Extension) + + + + + InAppMessagingDisplayResources.bundle/%(_FirebaseBundle_firebase_in_app_messaging_InAppMessagingDisplayResources_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_in_app_messaging_InAppMessagingDisplayResources_bundle_simulator.Filename)%(_FirebaseBundle_firebase_in_app_messaging_InAppMessagingDisplayResources_bundle_simulator.Extension) + + + + + InAppMessagingDisplayResources.bundle/%(_FirebaseBundle_firebase_in_app_messaging_InAppMessagingDisplayResources_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_in_app_messaging_InAppMessagingDisplayResources_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_in_app_messaging_InAppMessagingDisplayResources_bundle_catalyst.Extension) + + + + diff --git a/source/Firebase/native/AdamE.Firebase.iOS.Installations.targets b/source/Firebase/native/AdamE.Firebase.iOS.Installations.targets new file mode 100644 index 00000000..a564b9d4 --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.Installations.targets @@ -0,0 +1,45 @@ + + + + + + + + + + + -ObjC -lc++ + Security + Framework + True + True + true + + <_FirebaseBundle_firebase_installations_FirebaseInstallations_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-arm64/FirebaseInstallations.framework/FirebaseInstallations_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_installations_FirebaseInstallations_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-arm64_x86_64-simulator/FirebaseInstallations.framework/FirebaseInstallations_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_installations_FirebaseInstallations_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/FirebaseInstallations.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseInstallations.framework/Versions/A/Resources/FirebaseInstallations_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + -ObjC -lc++ + Framework + True + True + true + + + + + FirebaseInstallations_Privacy.bundle/%(_FirebaseBundle_firebase_installations_FirebaseInstallations_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_installations_FirebaseInstallations_Privacy_bundle_device.Filename)%(_FirebaseBundle_firebase_installations_FirebaseInstallations_Privacy_bundle_device.Extension) + + + + + FirebaseInstallations_Privacy.bundle/%(_FirebaseBundle_firebase_installations_FirebaseInstallations_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_installations_FirebaseInstallations_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_firebase_installations_FirebaseInstallations_Privacy_bundle_simulator.Extension) + + + + + FirebaseInstallations_Privacy.bundle/%(_FirebaseBundle_firebase_installations_FirebaseInstallations_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_installations_FirebaseInstallations_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_installations_FirebaseInstallations_Privacy_bundle_catalyst.Extension) + + + + diff --git a/source/Firebase/native/AdamE.Firebase.iOS.PerformanceMonitoring.targets b/source/Firebase/native/AdamE.Firebase.iOS.PerformanceMonitoring.targets new file mode 100644 index 00000000..ae0c247a --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.PerformanceMonitoring.targets @@ -0,0 +1,16 @@ + + + + + + + -ObjC -lc++ + CoreTelephony QuartzCore SystemConfiguration + Framework + True + True + true + + + + diff --git a/source/Firebase/native/AdamE.Firebase.iOS.RemoteConfig.targets b/source/Firebase/native/AdamE.Firebase.iOS.RemoteConfig.targets new file mode 100644 index 00000000..caa890b0 --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.RemoteConfig.targets @@ -0,0 +1,37 @@ + + + + + + + + + + -ObjC -lc++ -lsqlite3 -lz + Security StoreKit SystemConfiguration + Framework + True + True + true + + <_FirebaseBundle_firebase_remote_config_FirebaseRemoteConfig_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseRemoteConfig/FirebaseRemoteConfig.xcframework/ios-arm64/FirebaseRemoteConfig.framework/FirebaseRemoteConfig_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_remote_config_FirebaseRemoteConfig_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseRemoteConfig/FirebaseRemoteConfig.xcframework/ios-arm64_x86_64-simulator/FirebaseRemoteConfig.framework/FirebaseRemoteConfig_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_firebase_remote_config_FirebaseRemoteConfig_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseRemoteConfig/FirebaseRemoteConfig.xcframework/ios-arm64_x86_64-maccatalyst/FirebaseRemoteConfig.framework/Versions/A/Resources/FirebaseRemoteConfig_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + + + FirebaseRemoteConfig_Privacy.bundle/%(_FirebaseBundle_firebase_remote_config_FirebaseRemoteConfig_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_firebase_remote_config_FirebaseRemoteConfig_Privacy_bundle_device.Filename)%(_FirebaseBundle_firebase_remote_config_FirebaseRemoteConfig_Privacy_bundle_device.Extension) + + + + + FirebaseRemoteConfig_Privacy.bundle/%(_FirebaseBundle_firebase_remote_config_FirebaseRemoteConfig_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_firebase_remote_config_FirebaseRemoteConfig_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_firebase_remote_config_FirebaseRemoteConfig_Privacy_bundle_simulator.Extension) + + + + + FirebaseRemoteConfig_Privacy.bundle/%(_FirebaseBundle_firebase_remote_config_FirebaseRemoteConfig_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_firebase_remote_config_FirebaseRemoteConfig_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_firebase_remote_config_FirebaseRemoteConfig_Privacy_bundle_catalyst.Extension) + + + + diff --git a/source/Firebase/native/AdamE.Firebase.iOS.Storage.targets b/source/Firebase/native/AdamE.Firebase.iOS.Storage.targets new file mode 100644 index 00000000..e1a94ab2 --- /dev/null +++ b/source/Firebase/native/AdamE.Firebase.iOS.Storage.targets @@ -0,0 +1,15 @@ + + + + + + + -ObjC -lc++ + Framework + True + True + true + + + + diff --git a/source/Firebase/native/AdamE.Google.iOS.AppCheckCore.targets b/source/Firebase/native/AdamE.Google.iOS.AppCheckCore.targets new file mode 100644 index 00000000..3bfd7c30 --- /dev/null +++ b/source/Firebase/native/AdamE.Google.iOS.AppCheckCore.targets @@ -0,0 +1,25 @@ + + + + + + + + Framework + True + True + True + true + -ObjC -lc++ + DeviceCheck + + + -ObjC -lc++ + Framework + True + True + true + + + + diff --git a/source/Firebase/native/AdamE.Google.iOS.GTMSessionFetcher.targets b/source/Firebase/native/AdamE.Google.iOS.GTMSessionFetcher.targets new file mode 100644 index 00000000..d245de1a --- /dev/null +++ b/source/Firebase/native/AdamE.Google.iOS.GTMSessionFetcher.targets @@ -0,0 +1,37 @@ + + + + + + + + + + Framework + True + True + True + true + -ObjC -lc++ + + <_FirebaseBundle_gtm_session_fetcher_GTMSessionFetcher_Core_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseAuth/GTMSessionFetcher.xcframework/ios-arm64/GTMSessionFetcher.framework/GTMSessionFetcher_Core_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_gtm_session_fetcher_GTMSessionFetcher_Core_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseAuth/GTMSessionFetcher.xcframework/ios-arm64_x86_64-simulator/GTMSessionFetcher.framework/GTMSessionFetcher_Core_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_gtm_session_fetcher_GTMSessionFetcher_Core_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseAuth/GTMSessionFetcher.xcframework/ios-arm64_x86_64-maccatalyst/GTMSessionFetcher.framework/Versions/A/Resources/GTMSessionFetcher_Core_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + + + GTMSessionFetcher_Core_Privacy.bundle/%(_FirebaseBundle_gtm_session_fetcher_GTMSessionFetcher_Core_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_gtm_session_fetcher_GTMSessionFetcher_Core_Privacy_bundle_device.Filename)%(_FirebaseBundle_gtm_session_fetcher_GTMSessionFetcher_Core_Privacy_bundle_device.Extension) + + + + + GTMSessionFetcher_Core_Privacy.bundle/%(_FirebaseBundle_gtm_session_fetcher_GTMSessionFetcher_Core_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_gtm_session_fetcher_GTMSessionFetcher_Core_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_gtm_session_fetcher_GTMSessionFetcher_Core_Privacy_bundle_simulator.Extension) + + + + + GTMSessionFetcher_Core_Privacy.bundle/%(_FirebaseBundle_gtm_session_fetcher_GTMSessionFetcher_Core_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_gtm_session_fetcher_GTMSessionFetcher_Core_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_gtm_session_fetcher_GTMSessionFetcher_Core_Privacy_bundle_catalyst.Extension) + + + + diff --git a/source/Firebase/native/AdamE.Google.iOS.GoogleAppMeasurement.targets b/source/Firebase/native/AdamE.Google.iOS.GoogleAppMeasurement.targets new file mode 100644 index 00000000..3ced95e8 --- /dev/null +++ b/source/Firebase/native/AdamE.Google.iOS.GoogleAppMeasurement.targets @@ -0,0 +1,36 @@ + + + + + + + + + Framework + True + True + True + true + -ObjC -lc++ -lsqlite3 -lz + StoreKit + + + Framework + True + True + True + true + -ObjC -lc++ -lsqlite3 -lz + StoreKit + + + Framework + True + True + True + true + -ObjC -lc++ + + + + diff --git a/source/Firebase/native/AdamE.Google.iOS.GoogleDataTransport.targets b/source/Firebase/native/AdamE.Google.iOS.GoogleDataTransport.targets new file mode 100644 index 00000000..339ffddc --- /dev/null +++ b/source/Firebase/native/AdamE.Google.iOS.GoogleDataTransport.targets @@ -0,0 +1,38 @@ + + + + + + + + + + Framework + True + True + True + true + -ObjC -lc++ + SystemConfiguration CoreTelephony + + <_FirebaseBundle_google_data_transport_GoogleDataTransport_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseCrashlytics/GoogleDataTransport.xcframework/ios-arm64/GoogleDataTransport.framework/GoogleDataTransport_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_google_data_transport_GoogleDataTransport_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseCrashlytics/GoogleDataTransport.xcframework/ios-arm64_x86_64-simulator/GoogleDataTransport.framework/GoogleDataTransport_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_google_data_transport_GoogleDataTransport_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseCrashlytics/GoogleDataTransport.xcframework/ios-arm64_x86_64-maccatalyst/GoogleDataTransport.framework/Versions/A/Resources/GoogleDataTransport_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + + + GoogleDataTransport_Privacy.bundle/%(_FirebaseBundle_google_data_transport_GoogleDataTransport_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_google_data_transport_GoogleDataTransport_Privacy_bundle_device.Filename)%(_FirebaseBundle_google_data_transport_GoogleDataTransport_Privacy_bundle_device.Extension) + + + + + GoogleDataTransport_Privacy.bundle/%(_FirebaseBundle_google_data_transport_GoogleDataTransport_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_google_data_transport_GoogleDataTransport_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_google_data_transport_GoogleDataTransport_Privacy_bundle_simulator.Extension) + + + + + GoogleDataTransport_Privacy.bundle/%(_FirebaseBundle_google_data_transport_GoogleDataTransport_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_google_data_transport_GoogleDataTransport_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_google_data_transport_GoogleDataTransport_Privacy_bundle_catalyst.Extension) + + + + diff --git a/source/Firebase/native/AdamE.Google.iOS.GoogleUtilities.targets b/source/Firebase/native/AdamE.Google.iOS.GoogleUtilities.targets new file mode 100644 index 00000000..51b6dc4d --- /dev/null +++ b/source/Firebase/native/AdamE.Google.iOS.GoogleUtilities.targets @@ -0,0 +1,38 @@ + + + + + + + + + + Framework + True + True + True + true + -ObjC -lc++ + Security SystemConfiguration + + <_FirebaseBundle_google_utilities_GoogleUtilities_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-arm64/GoogleUtilities.framework/GoogleUtilities_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_google_utilities_GoogleUtilities_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-arm64_x86_64-simulator/GoogleUtilities.framework/GoogleUtilities_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_google_utilities_GoogleUtilities_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/GoogleUtilities.xcframework/ios-arm64_x86_64-maccatalyst/GoogleUtilities.framework/Versions/A/Resources/GoogleUtilities_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + + + GoogleUtilities_Privacy.bundle/%(_FirebaseBundle_google_utilities_GoogleUtilities_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_google_utilities_GoogleUtilities_Privacy_bundle_device.Filename)%(_FirebaseBundle_google_utilities_GoogleUtilities_Privacy_bundle_device.Extension) + + + + + GoogleUtilities_Privacy.bundle/%(_FirebaseBundle_google_utilities_GoogleUtilities_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_google_utilities_GoogleUtilities_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_google_utilities_GoogleUtilities_Privacy_bundle_simulator.Extension) + + + + + GoogleUtilities_Privacy.bundle/%(_FirebaseBundle_google_utilities_GoogleUtilities_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_google_utilities_GoogleUtilities_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_google_utilities_GoogleUtilities_Privacy_bundle_catalyst.Extension) + + + + diff --git a/source/Firebase/native/AdamE.Google.iOS.Nanopb.targets b/source/Firebase/native/AdamE.Google.iOS.Nanopb.targets new file mode 100644 index 00000000..012c1bbd --- /dev/null +++ b/source/Firebase/native/AdamE.Google.iOS.Nanopb.targets @@ -0,0 +1,37 @@ + + + + + + + + + + Framework + True + True + True + true + -ObjC -lc++ + + <_FirebaseBundle_nanopb_nanopb_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/nanopb.xcframework/ios-arm64/nanopb.framework/nanopb_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_nanopb_nanopb_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/nanopb.xcframework/ios-arm64_x86_64-simulator/nanopb.framework/nanopb_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_nanopb_nanopb_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/nanopb.xcframework/ios-arm64_x86_64-maccatalyst/nanopb.framework/Versions/A/Resources/nanopb_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + + + nanopb_Privacy.bundle/%(_FirebaseBundle_nanopb_nanopb_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_nanopb_nanopb_Privacy_bundle_device.Filename)%(_FirebaseBundle_nanopb_nanopb_Privacy_bundle_device.Extension) + + + + + nanopb_Privacy.bundle/%(_FirebaseBundle_nanopb_nanopb_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_nanopb_nanopb_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_nanopb_nanopb_Privacy_bundle_simulator.Extension) + + + + + nanopb_Privacy.bundle/%(_FirebaseBundle_nanopb_nanopb_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_nanopb_nanopb_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_nanopb_nanopb_Privacy_bundle_catalyst.Extension) + + + + diff --git a/source/Firebase/native/AdamE.Google.iOS.PromisesObjC.targets b/source/Firebase/native/AdamE.Google.iOS.PromisesObjC.targets new file mode 100644 index 00000000..aa8f868a --- /dev/null +++ b/source/Firebase/native/AdamE.Google.iOS.PromisesObjC.targets @@ -0,0 +1,37 @@ + + + + + + + + + + Framework + True + True + True + true + -ObjC -lc++ + + <_FirebaseBundle_fbl_promises_FBLPromises_Privacy_bundle_device Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/FBLPromises.xcframework/ios-arm64/FBLPromises.framework/FBLPromises_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And !$([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_fbl_promises_FBLPromises_Privacy_bundle_simulator Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/FBLPromises.xcframework/ios-arm64_x86_64-simulator/FBLPromises.framework/FBLPromises_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'ios' And $([System.String]::Copy('$(RuntimeIdentifier)').StartsWith('iossimulator-'))" /> + <_FirebaseBundle_fbl_promises_FBLPromises_Privacy_bundle_catalyst Include="$(_FirebaseNativeRoot)Firebase/FirebaseAnalytics/FBLPromises.xcframework/ios-arm64_x86_64-maccatalyst/FBLPromises.framework/Versions/A/Resources/FBLPromises_Privacy.bundle/**/*" Condition="'$(TargetPlatformIdentifier)' == 'maccatalyst'" /> + + + + FBLPromises_Privacy.bundle/%(_FirebaseBundle_fbl_promises_FBLPromises_Privacy_bundle_device.RecursiveDir)%(_FirebaseBundle_fbl_promises_FBLPromises_Privacy_bundle_device.Filename)%(_FirebaseBundle_fbl_promises_FBLPromises_Privacy_bundle_device.Extension) + + + + + FBLPromises_Privacy.bundle/%(_FirebaseBundle_fbl_promises_FBLPromises_Privacy_bundle_simulator.RecursiveDir)%(_FirebaseBundle_fbl_promises_FBLPromises_Privacy_bundle_simulator.Filename)%(_FirebaseBundle_fbl_promises_FBLPromises_Privacy_bundle_simulator.Extension) + + + + + FBLPromises_Privacy.bundle/%(_FirebaseBundle_fbl_promises_FBLPromises_Privacy_bundle_catalyst.RecursiveDir)%(_FirebaseBundle_fbl_promises_FBLPromises_Privacy_bundle_catalyst.Filename)%(_FirebaseBundle_fbl_promises_FBLPromises_Privacy_bundle_catalyst.Extension) + + + + diff --git a/source/Firebase/native/Firebase.Native.Common.targets b/source/Firebase/native/Firebase.Native.Common.targets new file mode 100644 index 00000000..57bd6802 --- /dev/null +++ b/source/Firebase/native/Firebase.Native.Common.targets @@ -0,0 +1,18 @@ + + + <_FirebaseNativeSourceId Condition="'$(_FirebaseNativeSourceId)' == ''">FirebaseiOSSDK-13.1.1 + <_FirebaseNativeRoot>$(XamarinBuildDownloadDir)FirebaseiOSSDK-13.1.1/ + <_FirebaseNativeCleanup>Remove FirebaseiOSSDK-13.1.1, FirebaseiOSSDK-13.1.1.unpacked, and any FirebaseiOSSDK-13.1.1.zip from $(XamarinBuildDownloadDir), then rebuild online. + + + + https://github.com/firebase/firebase-ios-sdk/releases/download/13.1.1/Firebase.zip + Zip + eab04111b6b6ebd2bbd9264b452b2eec5be13703207f32f7cf10d9040e246b70 + 1800 + + + + + + diff --git a/source/Firebase/native/Firebase.Native.Pack.targets b/source/Firebase/native/Firebase.Native.Pack.targets new file mode 100644 index 00000000..64ea77f5 --- /dev/null +++ b/source/Firebase/native/Firebase.Native.Pack.targets @@ -0,0 +1,10 @@ + + + + + <_ProjectReferencesWithVersions> + [%(_ProjectReferencesWithVersions.ProjectVersion)] + + + + diff --git a/source/Firebase/native/UPSTREAM-NOTICES.txt b/source/Firebase/native/UPSTREAM-NOTICES.txt new file mode 100644 index 00000000..65b2cc8b --- /dev/null +++ b/source/Firebase/native/UPSTREAM-NOTICES.txt @@ -0,0 +1,3201 @@ +AppCheckCore +Firebase +FirebaseABTesting +FirebaseAILogic +FirebaseAppCheck +FirebaseAppCheckInterop +FirebaseAppDistribution +FirebaseAuth +FirebaseAuthInterop +FirebaseCore +FirebaseCoreExtension +FirebaseCoreInternal +FirebaseFunctions +FirebaseInAppMessaging +FirebaseInstallations +FirebaseMessaging +FirebaseMessagingInterop +FirebasePerformance +FirebaseRemoteConfig +FirebaseRemoteConfigInterop +FirebaseSessions +FirebaseStorage +GTMSessionFetcher +GoogleDataTransport +PromisesObjC +RecaptchaInterop + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +BoringSSL-GRPC + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +Licenses for support code +------------------------- + +Parts of the TLS test suite are under the Go license. This code is not included +in BoringSSL (i.e. libcrypto and libssl) when compiled, however, so +distributing code linked against BoringSSL does not trigger this license: + +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +FirebaseAnalytics +GoogleAdsOnDeviceConversion +GoogleAppMeasurement + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + +FirebaseCrashlytics + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + +================================================================================ + +The following copyright from Hewlett-Packard Development Company, L.P. +applies to the dwarf.h file in third_party/libunwind + + libunwind - a platform-independent unwind library + Copyright (c) 2003-2005 Hewlett-Packard Development Company, L.P. + Contributed by David Mosberger-Tang + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +FirebaseDatabase + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +-------------------------- +FImmutableSortedDictionary +-------------------------- + Copyright (c) 2012 Mads Hartmann Jensen + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +-------------------------- +Wrap-leveldb +-------------------------- +Created by Adam Preble on 1/23/12. +Copyright (c) 2012 Adam Preble. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +Portions of APLevelDB are based on LevelDB-ObjC: + https:github.com/hoisie/LevelDB-ObjC +Specifically the SliceFromString/StringFromSlice macros, and the structure of +the enumeration methods. License for those potions follows: + +Copyright (c) 2011 Pave Labs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + +-------------------------- +SocketRocket +-------------------------- +Copyright 2012 Square Inc. + +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. + +$OpenBSD: base64.c,v 1.5 2006/10/21 09:55:03 otto Exp $ + +Copyright (c) 1996 by Internet Software Consortium. + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS +ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE +CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL +DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +Portions Copyright (c) 1995 by International Business Machines, Inc. + +International Business Machines, Inc. (hereinafter called IBM) grants +permission under its copyrights to use, copy, modify, and distribute this +Software with or without fee, provided that the above copyright notice and +all paragraphs of this notice appear in all copies, and that the name of IBM +not be used in connection with the marketing of any product incorporating +the Software or modifications thereof, without specific, written prior +permission. + +To the extent it has a right to do so, IBM grants an immunity from suit +under its patents, if any, for the use, sale or manufacture of products to +the extent that such products are used for performing Domain Name System +dynamic updates in TCP/IP networks by means of the Software. No immunity is +granted for any product per se or for any other function of any product. + +THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, +DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING +OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN +IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + + +FirebaseFirestore +FirebaseFirestoreInternal + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +-------------------------- +nlohmann_json +-------------------------- +MIT License + +Copyright (c) 2013-2020 Niels Lohmann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +-------------------------- +FirestoreEncoder +-------------------------- + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + + +## Runtime Library Exception to the Apache 2.0 License: ## + + + As an exception, if you use this Software to compile your source code and + portions of this Software are embedded into the binary product as a result, + you may redistribute such product without providing attribution as would + otherwise be required by Sections 4(a), 4(b) and 4(d) of the License. + + + +FirebaseSharedSwift + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + ## Runtime Library Exception to the Apache 2.0 License: ## + + + As an exception, if you use this Software to compile your source code and + portions of this Software are embedded into the binary product as a result, + you may redistribute such product without providing attribution as would + otherwise be required by Sections 4(a), 4(b) and 4(d) of the License. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + + +GoogleUtilities + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + +================================================================================ + +Copyright (c) 2017 Landon J. Fuller +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +abseil + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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 + + https://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. + + + +gRPC-C++ +gRPC-Core + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. + +----------------------------------------------------------- + +Following applies to: +./src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec +./src/objective-c/!ProtoCompiler-gRPCPlugin.podspec +./src/objective-c/!ProtoCompiler.podspec +./src/objective-c/BoringSSL-GRPC.podspec +./templates/src/objective-c/!ProtoCompiler-gRPCCppPlugin.podspec.inja +./templates/src/objective-c/!ProtoCompiler-gRPCPlugin.podspec.inja +./templates/src/objective-c/!ProtoCompiler.podspec.inja +./templates/src/objective-c/BoringSSL-GRPC.podspec.template + +BSD 3-Clause License + +Copyright 2016, Google Inc. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from this +software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +----------------------------------------------------------- + +Following applies to: +./etc/roots.pem + +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + + +leveldb-library +Copyright (c) 2011 The LevelDB Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +nanopb +Copyright (c) 2011 Petteri Aimonen + +This software is provided 'as-is', without any express or +implied warranty. In no event will the authors be held liable +for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any +purpose, including commercial applications, and to alter it and +redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you + must not claim that you wrote the original software. If you use + this software in a product, an acknowledgment in the product + documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and + must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source + distribution. diff --git a/source/Google/AppCheckCore/AppCheckCore.csproj b/source/Google/AppCheckCore/AppCheckCore.csproj index 46fb1fcc..92e29b93 100644 --- a/source/Google/AppCheckCore/AppCheckCore.csproj +++ b/source/Google/AppCheckCore/AppCheckCore.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,56 +8,57 @@ 15.0 Google.AppCheckCore Google.AppCheckCore - 11.3.2 - 11.3.2 + 12.0.0.0 + 12.0.0.0 Resources true true $(NoWarn);NU1603 + NUGET_README.md AdamE.Google.iOS.AppCheckCore AppCheckCore - AppCheckCore packed for .NET for iOS - AppCheckCore packed for .NET for iOS + AppCheckCore managed bindings and XBD native delivery for .NET for iOS + AppCheckCore managed bindings and XBD native delivery for .NET for iOS Microsoft, Adam Essenmacher, Jean-Emmanuel Baillat Adam Essenmacher © Microsoft Corporation. All rights reserved. © 2026, Adam Essenmacher. https://github.com/AdamEssenmacher/GoogleApisForiOSComponents License.md true - 11.3.2 + 12.0.0.0 - + - - Framework - True - True - DeviceCheck - - - Framework - True - True - - - Framework - True - True - + - + + + + + + + + + + + + + - - + + + + + diff --git a/source/Google/GTMSessionFetcher/GTMSessionFetcher.csproj b/source/Google/GTMSessionFetcher/GTMSessionFetcher.csproj index 48fd2825..46f5dc4d 100644 --- a/source/Google/GTMSessionFetcher/GTMSessionFetcher.csproj +++ b/source/Google/GTMSessionFetcher/GTMSessionFetcher.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Google.GTMSessionFetcher Google.GTMSessionFetcher - 3.5.0.8 - 3.5.0.8 + 5.3.1.0 + 5.3.1.0 Resources true true @@ -17,8 +17,8 @@ AdamE.Google.iOS.GTMSessionFetcher GTMSessionFetcher - GTMSessionFetcher packed for .NET for iOS - GTMSessionFetcher packed for .NET for iOS + GTMSessionFetcher managed bindings and XBD native delivery for .NET for iOS + GTMSessionFetcher managed bindings and XBD native delivery for .NET for iOS Microsoft, Adam Essenmacher Adam Essenmacher © Microsoft Corporation. All rights reserved. © 2024, Adam Essenmacher. @@ -26,23 +26,33 @@ License.md NUGET_README.md true - 3.5.0.8 + 5.3.1.0 - + - + - - Framework - True - True - + - + + + + + + + + + + + + + + + diff --git a/source/Google/GoogleAppMeasurement/GoogleAppMeasurement.csproj b/source/Google/GoogleAppMeasurement/GoogleAppMeasurement.csproj index 9318a46d..1dc368be 100644 --- a/source/Google/GoogleAppMeasurement/GoogleAppMeasurement.csproj +++ b/source/Google/GoogleAppMeasurement/GoogleAppMeasurement.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,48 +8,53 @@ 15.0 Google.GoogleAppMeasurement Google.GoogleAppMeasurement - 12.19.3 - 12.19.3 + 13.1.1.0 + 13.1.1.0 Resources true true + NUGET_README.md AdamE.Google.iOS.GoogleAppMeasurement GoogleAppMeasurement - GoogleAppMeasurement packed for .NET for iOS - GoogleAppMeasurement packed for .NET for iOS + GoogleAppMeasurement managed bindings and XBD native delivery for .NET for iOS + GoogleAppMeasurement managed bindings and XBD native delivery for .NET for iOS Microsoft, Adam Essenmacher Adam Essenmacher © Microsoft Corporation. All rights reserved. © 2024, Adam Essenmacher. https://github.com/AdamEssenmacher/GoogleApisForiOSComponents License.md true - 12.19.3 + 13.1.1.0 - + - - Framework - True - True - -ObjC -lc++ -lsqlite3 -lz - StoreKit - - - Framework - True - True - -ObjC -lc++ -lsqlite3 -lz - StoreKit - + - + + + + + + + + + + + + + + + + + + diff --git a/source/Google/GoogleDataTransport/GoogleDataTransport.csproj b/source/Google/GoogleDataTransport/GoogleDataTransport.csproj index 71ff8481..6218c44f 100644 --- a/source/Google/GoogleDataTransport/GoogleDataTransport.csproj +++ b/source/Google/GoogleDataTransport/GoogleDataTransport.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,44 +8,55 @@ 15.0 Google.GoogleDataTransport Google.GoogleDataTransport - 10.1.0.6 - 10.1.0.6 + 10.1.1.0 + 10.1.1.0 Resources true true + NUGET_README.md AdamE.Google.iOS.GoogleDataTransport GoogleDataTransport - GoogleDataTransport packed for .NET for iOS - GoogleDataTransport packed for .NET for iOS + GoogleDataTransport managed bindings and XBD native delivery for .NET for iOS + GoogleDataTransport managed bindings and XBD native delivery for .NET for iOS Microsoft, Adam Essenmacher Adam Essenmacher © Microsoft Corporation. All rights reserved. © 2024, Adam Essenmacher. https://github.com/AdamEssenmacher/GoogleApisForiOSComponents License.md true - 10.1.0.6 + 10.1.1.0 - + - + - - Framework - True - True - SystemConfiguration CoreTelephony - + - + + + + + + + + + + + + + - - + + + + + diff --git a/source/Google/GoogleUtilities/GoogleUtilities.csproj b/source/Google/GoogleUtilities/GoogleUtilities.csproj index fd3380ae..98e1c953 100644 --- a/source/Google/GoogleUtilities/GoogleUtilities.csproj +++ b/source/Google/GoogleUtilities/GoogleUtilities.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Google.GoogleUtilities Google.GoogleUtilities - 8.1.5 - 8.1.5 + 8.1.5.1 + 8.1.5.1 Resources true true @@ -17,8 +17,8 @@ AdamE.Google.iOS.GoogleUtilities GoogleUtilities - GoogleUtilities packed for .NET for iOS - GoogleUtilities packed for .NET for iOS + GoogleUtilities managed bindings and XBD native delivery for .NET for iOS + GoogleUtilities managed bindings and XBD native delivery for .NET for iOS Microsoft, Adam Essenmacher Adam Essenmacher © Microsoft Corporation. All rights reserved. © 2024, Adam Essenmacher. @@ -26,24 +26,33 @@ License.md NUGET_README.md true - 8.1.5 + 8.1.5.1 - + - + - - Framework - True - True - Security SystemConfiguration - + - + + + + + + + + + + + + + + + diff --git a/source/Google/Nanopb/Nanopb.csproj b/source/Google/Nanopb/Nanopb.csproj index fd98b92d..7737d04f 100644 --- a/source/Google/Nanopb/Nanopb.csproj +++ b/source/Google/Nanopb/Nanopb.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,39 +8,53 @@ 15.0 Google.Nanopb Google.Nanopb - 3.30910.0.6 - 3.30910.0.6 + 3.30910.0.7 + 3.30910.0.7 Resources true true + NUGET_README.md AdamE.Google.iOS.Nanopb Nanopb - Nanopb packed for .NET for iOS - Nanopb packed for .NET for iOS + Nanopb managed bindings and XBD native delivery for .NET for iOS + Nanopb managed bindings and XBD native delivery for .NET for iOS Microsoft, Adam Essenmacher Adam Essenmacher © Microsoft Corporation. All rights reserved. © 2024, Adam Essenmacher. https://github.com/AdamEssenmacher/GoogleApisForiOSComponents License.md true - 3.30910.0.6 + 3.30910.0.7 - + - + - - Framework - True - True - + - + + + + + + + + + + + + + + + + + + diff --git a/source/Google/PromisesObjC/PromisesObjC.csproj b/source/Google/PromisesObjC/PromisesObjC.csproj index 84734584..ed47c965 100644 --- a/source/Google/PromisesObjC/PromisesObjC.csproj +++ b/source/Google/PromisesObjC/PromisesObjC.csproj @@ -1,4 +1,4 @@ - + net10.0-ios;net10.0-maccatalyst enable @@ -8,8 +8,8 @@ 15.0 Google.PromisesObjC Google.PromisesObjC - 2.4.0.8 - 2.4.0.8 + 2.4.1.0 + 2.4.1.0 Resources true true @@ -17,8 +17,8 @@ AdamE.Google.iOS.PromisesObjC PromisesObjC - PromisesObjC packed for .NET for iOS - PromisesObjC packed for .NET for iOS + PromisesObjC managed bindings and XBD native delivery for .NET for iOS + PromisesObjC managed bindings and XBD native delivery for .NET for iOS Microsoft, Adam Essenmacher Adam Essenmacher © Microsoft Corporation. All rights reserved. © 2024, Adam Essenmacher. @@ -26,23 +26,33 @@ License.md NUGET_README.md true - 2.4.0.8 + 2.4.1.0 - + - + - - Framework - True - True - + - + + + + + + + + + + + + + + + diff --git a/tests/crashlytics/test_download_cache_recovery.py b/tests/crashlytics/test_download_cache_recovery.py index e551f256..025dab50 100644 --- a/tests/crashlytics/test_download_cache_recovery.py +++ b/tests/crashlytics/test_download_cache_recovery.py @@ -1,174 +1,99 @@ -"""Drive the real Xamarin.Build.Download path to check the digest pin and what the documented recovery depends on. +"""Exercise stock XBD ZIP caching with a small local archive, not a raw script download. -The recovery steps themselves live in the integrity error text, which -test_upload_integrity.py asserts; this suite establishes that the cache behaves the -way those steps claim. - -These tests download the pinned upload-symbols source, so they need network access. -Set CRASHLYTICS_SKIP_NETWORK_TESTS=1 to skip them when working offline. +The fixture imports the shipped common declaration, then replaces its URL/digest +only inside the test project. Production declarations stay pinned to Google. +The full official archive and consumer matrix run in firebase13-xbd.yml. """ import hashlib +from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer +import io +import json import os from pathlib import Path import shutil import subprocess import tempfile +import threading import unittest -import xml.etree.ElementTree as ET +import zipfile ROOT = Path(__file__).resolve().parents[2] -TARGETS = ROOT / 'source/Firebase/Crashlytics/Crashlytics.targets' -CSPROJ = ROOT / 'source/Firebase/Crashlytics/Crashlytics.csproj' -POISON = b'stale download cache, not the pinned tool\n' -# The fixture imports the shipped targets, so the download item, cache folder and digest -# under test are the ones consumers get rather than a copy that can drift. -PROJECT = ''' - net10.0 - - - - - - -''' - - -def targets_property(name): - value = ET.parse(TARGETS).findtext('.//' + name) - if not value: - raise AssertionError('Crashlytics.targets is missing ' + name) - return value.strip() - - -def xbd_version(): - for reference in ET.parse(CSPROJ).iter('PackageReference'): - if reference.get('Include') == 'Xamarin.Build.Download': - return reference.get('Version') - raise AssertionError('Crashlytics.csproj no longer references Xamarin.Build.Download') +COMMON = ROOT / 'source/Firebase/native/Firebase.Native.Common.targets' +TOOL = b'#!/bin/sh\nexit 0\n' -@unittest.skipIf(os.environ.get('CRASHLYTICS_SKIP_NETWORK_TESTS') == '1', 'network-dependent') +@unittest.skipIf(os.environ.get('CRASHLYTICS_SKIP_NETWORK_TESTS') == '1', 'XBD package restore/local HTTP tests disabled') class DownloadCacheRecoveryTests(unittest.TestCase): - """One shared baseline download; each test works on its own copy of that cache.""" - @classmethod def setUpClass(cls): - cls.folder = targets_property('_FirebaseCrashlyticsItemsFolder') - cls.script = targets_property('_FirebaseScriptName') - cls.digest = targets_property('_FirebaseCrashlyticsScriptSha256') - cls._work = tempfile.TemporaryDirectory(prefix='crashlytics-download-') - work = Path(cls._work.name).resolve() - cls.project = work / 'fixture.csproj' - cls.project.write_text(PROJECT.format(version=xbd_version(), targets=TARGETS)) - # No global.json beside the fixture: its pinned workloadVersion would make the - # workload resolver fail wherever workloads are not installed, and this project - # needs none. Disabling the resolver keeps that true however the fixture is invoked. - cls.env = dict(os.environ, MSBuildEnableWorkloadResolver='false') - packages = work / 'packages' - restore = subprocess.run(['dotnet', 'restore', str(cls.project), '--packages', str(packages)], - cwd=work, env=cls.env, capture_output=True, text=True) - if restore.returncode != 0: - raise AssertionError(restore.stdout + restore.stderr) - # Build each starting state once and reuse it, so a run of this suite fetches the - # pinned source only for the cases that must observe a fresh download. - cls.baseline = work / 'baseline' - cls.baseline.mkdir() - code, log = cls.run_download(cls.baseline) - if code != 0: - raise AssertionError(log) - # The one state that leaves a download cache behind: the marker is gone while the - # versioned directory remains, so the download succeeds but cannot be moved in. - cls.failed = work / 'failed' - shutil.copytree(cls.baseline, cls.failed) - (cls.failed / (cls.folder + '.unpacked')).unlink() - code, cls.failed_log = cls.run_download(cls.failed) - if code == 0: - raise AssertionError('expected the interrupted download state to fail\n' + cls.failed_log) - leftover = cls.failed / (cls.folder + Path(cls.script).suffix) - if not leftover.exists(): - raise AssertionError('expected a leftover download cache\n' + cls.failed_log) + cls._work = tempfile.TemporaryDirectory(prefix='crashlytics-archive-') + cls.work = Path(cls._work.name).resolve() + cls.source = json.loads((ROOT/'source/Firebase/native-assets.json').read_text())['source'] + payload = io.BytesIO() + with zipfile.ZipFile(payload, 'w') as archive: + archive.writestr('Firebase/FirebaseCrashlytics/upload-symbols', TOOL) + cls.payload = payload.getvalue() + cls.requests = 0 + class Handler(BaseHTTPRequestHandler): + def do_GET(self): + cls.requests += 1 + self.send_response(200); self.end_headers(); self.wfile.write(cls.payload) + def log_message(self, *_): pass + cls.server = ThreadingHTTPServer(('127.0.0.1', 0), Handler) + cls.thread = threading.Thread(target=cls.server.serve_forever, daemon=True); cls.thread.start() + cls.project = cls.work/'fixture.csproj' + cls.project.write_text(f''' +net10.0 + + + +http://127.0.0.1:{cls.server.server_port}/Firebase.zip +{hashlib.sha256(cls.payload).hexdigest()} +$(FixtureDigest) + +''') + cls.env = dict(os.environ, MSBuildEnableWorkloadResolver='false', NO_PROXY='127.0.0.1', no_proxy='127.0.0.1') + result = subprocess.run(['dotnet','restore',str(cls.project)],cwd=cls.work,env=cls.env,capture_output=True,text=True) + if result.returncode: raise AssertionError(result.stdout+result.stderr) @classmethod def tearDownClass(cls): - cls._work.cleanup() - - @classmethod - def run_download(cls, cache): - result = subprocess.run( - ['dotnet', 'msbuild', str(cls.project), '-nologo', '-t:DownloadOnly', - '-p:OutputType=Exe', '-p:FirebaseCrashlyticsUploadSymbolsEnabled=True', - '-p:XamarinBuildDownloadDir=' + str(cache) + '/'], - cwd=cls.project.parent, env=cls.env, capture_output=True, text=True) - return result.returncode, result.stdout + result.stderr + cls.server.shutdown(); cls.server.server_close(); cls.thread.join(); cls._work.cleanup() def setUp(self): - parent = Path(tempfile.mkdtemp(prefix='crashlytics-cache-')).resolve() - self.addCleanup(shutil.rmtree, parent, ignore_errors=True) - self.cache = parent / 'cache' - shutil.copytree(self.baseline, self.cache) - self.directory = self.cache / self.folder - self.tool = self.directory / self.script - self.marker = self.cache / (self.folder + '.unpacked') - # Xamarin.Build.Download names its download cache after the item plus the - # ToFile extension. A successful download moves it into the versioned - # directory, so it is absent until an attempt fails partway. - self.download_cache = self.cache / (self.folder + Path(self.script).suffix) - - def download(self): - return self.run_download(self.cache) - - def assertPinnedToolPresent(self, log): - self.assertTrue(self.tool.exists(), log) - self.assertEqual(self.digest, hashlib.sha256(self.tool.read_bytes()).hexdigest(), log) - - def use_failed_attempt_state(self): - """Switch this test's cache to the state a failed attempt leaves behind.""" - shutil.rmtree(self.cache) - shutil.copytree(self.failed, self.cache) - self.assertTrue(self.download_cache.exists()) - self.assertFalse(self.marker.exists()) - - def test_pinned_source_download_matches_the_pinned_digest(self): - self.assertPinnedToolPresent('baseline download') - self.assertFalse(self.download_cache.exists(), - 'a successful download consumes the download cache') - - def test_documented_recovery_after_a_tampered_tool(self): - self.tool.write_bytes(POISON) - shutil.rmtree(self.directory) - self.marker.unlink() - code, log = self.download() - self.assertEqual(0, code, log) - self.assertPinnedToolPresent(log) - - def test_documented_recovery_after_a_failed_attempt(self): - self.use_failed_attempt_state() - shutil.rmtree(self.directory) - self.download_cache.unlink() - code, log = self.download() - self.assertEqual(0, code, log) - self.assertPinnedToolPresent(log) - - def test_deleting_only_the_versioned_directory_does_not_restore_the_tool(self): - shutil.rmtree(self.directory) - code, log = self.download() - self.assertEqual(0, code, log) - self.assertFalse(self.tool.exists(), 'the marker must still suppress the download') - - def test_leaving_the_download_cache_restores_the_rejected_bytes(self): - self.use_failed_attempt_state() - self.download_cache.write_bytes(POISON) + self.cache = self.work/self.id().split('.')[-1]; self.cache.mkdir() + self.directory = self.cache/self.source['id'] + self.tool = self.directory/'Firebase/FirebaseCrashlytics/upload-symbols' + + def acquire(self, digest=None): + args=['dotnet','msbuild',str(self.project),'-t:Acquire','-nologo', + '-p:OutputType=Exe','-p:TargetPlatformIdentifier=ios', + '-p:XamarinBuildDownloadAllowUnsecure=true', # Loopback fixture only; shipped URLs stay HTTPS. + '-p:XamarinBuildDownloadDir='+str(self.cache)+'/'] + if digest: args.append('-p:FixtureDigest='+digest) + result=subprocess.run(args,cwd=self.work,env=self.env,capture_output=True,text=True) + return result.returncode,result.stdout+result.stderr + + def test_zip_download_and_warm_cache_reuse(self): + code,log=self.acquire(); self.assertEqual(0,code,log); self.assertEqual(TOOL,self.tool.read_bytes()) + before=self.requests + code,log=self.acquire(); self.assertEqual(0,code,log); self.assertEqual(before,self.requests) + + def test_documented_archive_cache_cleanup_recovers_corrupted_tool(self): + code,log=self.acquire(); self.assertEqual(0,code,log) + self.tool.write_bytes(b'corrupt') + # Completed XBD caches intentionally do not rehash extracted files. + code,log=self.acquire(); self.assertEqual(0,code,log); self.assertEqual(b'corrupt',self.tool.read_bytes()) shutil.rmtree(self.directory) - code, log = self.download() - self.assertEqual(0, code, log) - self.assertEqual(POISON, self.tool.read_bytes(), - 'the download cache must be deleted too, or its bytes come back') + for suffix in ('.unpacked','.zip'): (self.cache/(self.source['id']+suffix)).unlink(missing_ok=True) + code,log=self.acquire(); self.assertEqual(0,code,log); self.assertEqual(TOOL,self.tool.read_bytes()) - def test_deleting_the_marker_while_the_directory_remains_fails_the_build(self): - # setUpClass already proved this fails and strands a download cache; assert the - # failure names the tool, rather than the runtime's localizable "already exists". - self.assertIn(self.script, self.failed_log) + def test_stock_xbd_cold_download_does_not_enforce_digest_metadata(self): + before=self.requests + code,log=self.acquire('0'*64); self.assertEqual(0,code,log); self.assertEqual(TOOL,self.tool.read_bytes()) + self.assertGreater(self.requests,before,log) + # 0.11.6 only checks an existing ZIP before download; it does not recheck + # freshly downloaded bytes. Producer validation, not XBD, enforces our pin. -if __name__ == '__main__': - unittest.main() +if __name__ == '__main__': unittest.main() diff --git a/tests/crashlytics/test_upload_integrity.py b/tests/crashlytics/test_upload_integrity.py index 7853c731..e9612261 100644 --- a/tests/crashlytics/test_upload_integrity.py +++ b/tests/crashlytics/test_upload_integrity.py @@ -47,11 +47,11 @@ class UploadIntegrityTests(unittest.TestCase): def assertRecoveryStepsNamed(self, log): """Guard the recovery steps themselves, which only live in the error text. - test_download_cache_recovery.py proves what the cache does; nothing but this - checks that the messages tell a consumer to do it. + The real XBD archive fixture checks cache recovery separately; this checks + that the error messages explain removal of the archive and completion marker. """ folder = targets_property('_FirebaseCrashlyticsItemsFolder') - suffix = Path(targets_property('_FirebaseScriptName')).suffix + suffix = '.zip' # The tool now comes from the shared official Firebase archive. # The marker is what makes deleting the directory alone a no-op. self.assertIn(folder + '.unpacked', log) # The download cache restores its bytes instead of re-downloading. @@ -64,12 +64,12 @@ def exercise(self, remote=False, content=TOOL, enabled=True, tamper=False, conti root = Path(tmp).resolve() (root / 'global.json').write_bytes((ROOT / 'global.json').read_bytes()) cache_name = targets_property('_FirebaseCrashlyticsItemsFolder') - cache = root / 'cache' / cache_name; cache.mkdir(parents=True) - script = cache / 'upload-symbols.sh' + cache = root / 'cache' / cache_name / 'Firebase/FirebaseCrashlytics'; cache.mkdir(parents=True) + script = cache / targets_property('_FirebaseScriptName') if content is not None: script.write_bytes(content) marker = root / 'executed' project = root / 'fixture.proj' - project.write_text('' + SHIMS + '') + project.write_text('' + SHIMS + '') env = dict(os.environ, TEST_UPLOAD_MARKER=str(marker), TEST_REMOTE_ROOT=str(root / 'remote'), TEST_TAMPER_REMOTE=str(tamper).lower()) name = '_FirebaseCrashlyticsUploadDSymToFirebaseOn' + ('Windows' if remote else 'Mac') command = ['dotnet', 'msbuild', str(project), '-nologo', '-t:' + name, diff --git a/tests/firebase-release/test_select_simulator.py b/tests/firebase-release/test_select_simulator.py index f0cc9f86..d5df2754 100644 --- a/tests/firebase-release/test_select_simulator.py +++ b/tests/firebase-release/test_select_simulator.py @@ -55,6 +55,11 @@ def test_name_selects_that_simulator(self): result = self.select(E2E_SIMULATOR_NAME='GoogleApisCI-iPhone') self.assertEqual((result.returncode, result.stdout), (0, DEDICATED + '\n')) + def test_dedicated_name_works_without_any_fallback_iphone(self): + result = self.select({'runtime': [{'name':'GoogleApisCI-iPhone','udid':DEDICATED}]}, + E2E_SIMULATOR_NAME='GoogleApisCI-iPhone') + self.assertEqual((result.returncode,result.stdout),(0,DEDICATED+'\n')) + def test_missing_name_fails_with_create_command(self): result = self.select(E2E_SIMULATOR_NAME='Missing-iPhone') self.assertEqual((result.returncode, result.stdout), (1, '')) diff --git a/tests/firebase-release/test_signin.py b/tests/firebase-release/test_signin.py index 72591e7d..822355bd 100644 --- a/tests/firebase-release/test_signin.py +++ b/tests/firebase-release/test_signin.py @@ -129,6 +129,19 @@ def run(*args): base='main', online=False, manual=True)) return release.read(output) + def test_shared_dependency_release_does_not_require_a_signin_binding_revision(self): + shared = ['AdamE.Google.iOS.AppCheckCore', 'AdamE.Google.iOS.GTMSessionFetcher'] + self.assertFalse(release.requires_new_channel_release(shared)) + self.assertFalse(release.requires_new_channel_release([])) + self.assertTrue(release.requires_new_channel_release(shared + ['AdamE.Google.iOS.SignIn'])) + # Unchanged root version still rejects any real root input/payload change. + root = packages()[-1] + with self.assertRaisesRegex(ValueError, 'without a version bump'): + release.check_versions([{**root, 'fingerprint':'changed'}], {'packages':[root]}) + release.configure_channel('firebase') + try: self.assertTrue(release.requires_new_channel_release(shared)) + finally: release.configure_channel('signin') + def test_manual_bootstrap_validation_is_not_release_eligible(self): manifest = self.plan_fixture() self.assertTrue(manifest['relevant']) diff --git a/tests/firebase-release/test_signin_review.py b/tests/firebase-release/test_signin_review.py index 43633859..93beed3e 100644 --- a/tests/firebase-release/test_signin_review.py +++ b/tests/firebase-release/test_signin_review.py @@ -71,6 +71,19 @@ def test_consumer_probe_matches_candidate_version_in_both_lanes(self): release.collect_validation(types.SimpleNamespace(results_dir=folder, package_dir=folder)) def test_shared_native_frameworks_have_one_owner_in_combined_consumers(self): + native_manifest = ROOT / 'source/Firebase/native-assets.json' + if native_manifest.exists(): + # Firebase 13 uses Google's prebuilt closure. Swift Promises is no longer + # a separate archive payload; RecaptchaInterop retains its AppCheckCore owner. + manifest = json.loads(native_manifest.read_text()) + frameworks = [(p['id'], Path(a['path']).name) for p in manifest['packages'] + for a in p['assets'] if a['kind'] == 'XCFramework'] + self.assertEqual([('Google.AppCheckCore', 'RecaptchaInterop.xcframework')], + [x for x in frameworks if x[1] == 'RecaptchaInterop.xcframework']) + self.assertFalse(any(n == 'Promises.xcframework' for _, n in frameworks)) + core = next(p for p in manifest['packages'] if p['id'] == 'Firebase.Core') + self.assertIn('AdamE.Google.iOS.AppCheckCore', core['dependencies']) + return projects = {name: ET.parse(ROOT / path) for name, path in { 'AppCheckCore': 'source/Google/AppCheckCore/AppCheckCore.csproj', 'Core': 'source/Firebase/Core/Core.csproj', diff --git a/tests/firebase13/test_native.py b/tests/firebase13/test_native.py new file mode 100644 index 00000000..b304d271 --- /dev/null +++ b/tests/firebase13/test_native.py @@ -0,0 +1,182 @@ +import copy +import importlib.util +import json +from pathlib import Path +import stat +import subprocess +import xml.etree.ElementTree as ET +import sys +import tempfile +import unittest +import zipfile + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT / 'tools/firebase13')) +import native +from archive_safety import preflight +from generate import generate + + +class NativeTests(unittest.TestCase): + def setUp(self): + self.manifest = json.loads(native.MANIFEST.read_text()) + + def test_committed_schema_and_generation(self): + self.assertEqual(len(native.validate_schema(self.manifest)), 23) + + def test_unverified_pack_fails_before_package_emission(self): + guard=ET.parse(ROOT/self.manifest['packages'][0]['project']).find("Target[@Name='_RequireVerifiedFirebase13Producer']") + with tempfile.TemporaryDirectory() as tmp: + work=Path(tmp);project=work/'fixture.proj';output=work/'packed' + project.write_text(''+ET.tostring(guard,encoding='unicode')+'') + command=['dotnet','msbuild',str(project),'-t:GenerateNuspec','-nologo'] + result=subprocess.run(command,capture_output=True,text=True) + self.assertNotEqual(0,result.returncode) + self.assertIn('firebase13.cake',result.stdout+result.stderr) + self.assertFalse(output.exists()) + result=subprocess.run(command+['-p:Firebase13BuildInfoPath=producer-info.cs'],capture_output=True,text=True) + self.assertEqual(0,result.returncode,result.stdout+result.stderr) + self.assertTrue(output.exists()) + + def test_conflicting_declarations_are_rejected(self): + for fault, message in [('url','source URL'),('hash','digest'),('id','asset ID'), + ('owner','owner'),('path','Unsafe asset'),('native-owner','framework ownership'), + ('dependency','outside Firebase')]: + m=copy.deepcopy(self.manifest) + with self.subTest(fault=fault): + if fault=='url':m['source']['url']='https://github.com/firebase/firebase-ios-sdk/releases/latest/download/Firebase.zip' + elif fault=='hash':m['source']['sha256']='bad' + elif fault=='id':m['packages'][1]['assets'][0]['id']=m['packages'][0]['assets'][0]['id'] + elif fault=='owner':m['packages'][0]['assets'][0]['owner']='Firebase.Auth' + elif fault=='path':m['packages'][0]['assets'][0]['path']='Firebase/../escape' + elif fault=='native-owner':m['packages'][1]['assets'][0]['path']=m['packages'][0]['assets'][0]['path'] + elif fault=='dependency':m['packages'][0]['dependencies'].append('AdamE.Google.iOS.SignIn') + with self.assertRaisesRegex(ValueError,message):native.validate_schema(m) + + def test_dependency_duplicates_and_cake_graph_drift_are_rejected(self): + m=copy.deepcopy(self.manifest) + m['packages'][0]['dependencies'].append(m['packages'][0]['dependencies'][0]) + with self.assertRaisesRegex(ValueError,'Duplicate manifest dependency'):native.validate_schema(m) + text=(ROOT/'components.cake').read_text() + wrong=text.replace('FIREBASE_CORE_ARTIFACT };','FIREBASE_CORE_ARTIFACT, FIREBASE_AUTH_ARTIFACT };',1) + with self.assertRaisesRegex(ValueError,'Cake dependency graph'):native.validate_cake_graph(self.manifest,wrong) + + def test_package_dependency_ranges_cannot_be_open_ended(self): + p=self.manifest['packages'][0] + versions={n['package']:n['version'].removesuffix('.0') for n in self.manifest['packages']} + assembly=ET.parse(ROOT/p['project']).findtext('PropertyGroup/AssemblyName') + with tempfile.TemporaryDirectory() as tmp: + for bounded in (True,False): + archive=Path(tmp)/'package.nupkg' + spec=ET.Element('package');meta=ET.SubElement(spec,'metadata') + ET.SubElement(meta,'id').text=p['package'];ET.SubElement(meta,'version').text=p['version'] + deps=ET.SubElement(meta,'dependencies') + with zipfile.ZipFile(archive,'w') as z: + for platform in ('ios','maccatalyst'): + group=ET.SubElement(deps,'group',targetFramework='net10.0-'+platform) + for dep in p['dependencies']: + ET.SubElement(group,'dependency',id=dep,version=('['+versions[dep]+']') if bounded else versions[dep]) + ET.SubElement(group,'dependency',id='Xamarin.Build.Download',version='[0.11.6]') + z.writestr('lib/net10.0-'+platform+'/'+assembly+'.dll',b'managed fixture') + z.writestr('package.nuspec',ET.tostring(spec)) + z.writestr('UPSTREAM-NOTICES.txt',(ROOT/'source/Firebase/native/UPSTREAM-NOTICES.txt').read_bytes()) + for folder in ('build','buildTransitive'): + for name in ('Firebase.Native.Common.targets',p['package']+'.targets'): + z.writestr(folder+'/'+name,generate(self.manifest)[name]) + if bounded:native.inspect_package(archive,p) + else: + with self.assertRaisesRegex(ValueError,'exact bounded version'):native.inspect_package(archive,p) + + def test_hostile_archive_paths_and_links(self): + for fault in ('traversal','absolute','escaping-link','cycle','write-through','case-collision','file-parent'): + with self.subTest(fault=fault), tempfile.TemporaryDirectory() as tmp: + path=Path(tmp)/'input.zip' + with zipfile.ZipFile(path,'w') as z: + def link(name,target): + item=zipfile.ZipInfo(name);item.external_attr=(stat.S_IFLNK | 0o777)<<16;z.writestr(item,target) + if fault=='traversal':z.writestr('Firebase/../escape','x') + elif fault=='absolute':z.writestr('/escape','x') + elif fault=='escaping-link':link('Firebase/link','../../escape') + elif fault=='cycle':link('Firebase/a','b');link('Firebase/b','a') + elif fault=='write-through':link('Firebase/link','other');z.writestr('Firebase/link/payload','x') + elif fault=='case-collision':z.writestr('Firebase/a','x');z.writestr('Firebase/A','y') + elif fault=='file-parent':z.writestr('Firebase/a','x');z.writestr('Firebase/a/payload','y') + with self.assertRaises(ValueError):preflight(path) + + def test_safe_internal_symlink_is_accepted(self): + with tempfile.TemporaryDirectory() as tmp: + path=Path(tmp)/'input.zip' + with zipfile.ZipFile(path,'w') as z: + z.writestr('Firebase/F.framework/Versions/A/payload','x') + item=zipfile.ZipInfo('Firebase/F.framework/Current');item.external_attr=(stat.S_IFLNK|0o777)<<16 + z.writestr(item,'Versions/A') + preflight(path) + + def test_checksum_mismatch_fails_before_archive_is_opened(self): + with tempfile.TemporaryDirectory() as tmp: + path=Path(tmp)/'bad.zip';path.write_bytes(b'not an archive') + with self.assertRaisesRegex(ValueError,'SHA-256 mismatch'):native.archive_validate(self.manifest,path) + + def test_msbuild_resource_metadata_survives_two_import_paths(self): + m=self.manifest + p=next(p for p in m['packages'] if p['id']=='Firebase.Core') + with tempfile.TemporaryDirectory() as tmp: + work=Path(tmp);cache=work/'cache';source=cache/m['source']['id'] + for a in p['assets']: + target=source/a['path'];target.mkdir(parents=True,exist_ok=True) + if a['kind']=='Bundle': + (target/'Info.plist').write_text('metadata') + (target/'PrivacyInfo.xcprivacy').write_text('privacy') + imports='' + for folder in ('build','buildTransitive'): + directory=work/folder;directory.mkdir() + targets=generate(m) + for name in ('Firebase.Native.Common.targets',p['package']+'.targets'): + (directory/name).write_text(targets[name]) + imports+='' + project=work/'probe.proj' + project.write_text(''+str(cache)+'/iosiossimulator-arm64Exe'+imports+'') + for label, properties, active, variant in ( + ('application', [], True, '-simulator'), + ('extension', ['-p:OutputType=Library','-p:IsAppExtension=True'], True, '-simulator'), + ('library', ['-p:OutputType=Library'], False, '-simulator'), + ('binding', ['-p:IsBindingProject=true'], False, '-simulator'), + ('design', ['-p:DesignTimeBuild=true'], False, '-simulator'), + ('outer', ['-p:IsCrossTargetingBuild=true'], False, '-simulator'), + ('catalyst', ['-p:TargetPlatformIdentifier=maccatalyst','-p:RuntimeIdentifier=maccatalyst-arm64'], True, '-catalyst')): + with self.subTest(shape=label): + for name in ('resources.txt','downloads.txt'):(work/name).unlink(missing_ok=True) + result=subprocess.run(['dotnet','msbuild',str(project),'-t:Test','-nologo']+properties,capture_output=True,text=True) + self.assertEqual(result.returncode,0,result.stdout+result.stderr) + resources=(work/'resources.txt').read_text().splitlines() if (work/'resources.txt').exists() else [] + expected={a['logical']+'/'+name for a in p['assets'] if a['kind']=='Bundle' and variant in a['id'] for name in ('Info.plist','PrivacyInfo.xcprivacy')} if active else set() + self.assertEqual(set(resources),expected) + self.assertEqual(len(resources),len(expected)) + downloads=(work/'downloads.txt').read_text().splitlines() if (work/'downloads.txt').exists() else [] + self.assertEqual(downloads,[m['source']['id']] if active else []) + + def test_missing_declared_payload_is_rejected(self): + m=copy.deepcopy(self.manifest) + with tempfile.TemporaryDirectory() as tmp: + path=Path(tmp)/'missing.zip' + with zipfile.ZipFile(path,'w') as z: + z.writestr('Firebase/NOTICES',(ROOT/'source/Firebase/native/UPSTREAM-NOTICES.txt').read_bytes()) + z.writestr('Firebase/METADATA.md',(ROOT/'tests/fixtures/firebase13/13.1.1/METADATA.md').read_bytes()) + m['source']['sha256']=native.digest(path) + with self.assertRaisesRegex(ValueError,'Missing payload'): + native.archive_validate(m,path) + + def test_both_import_paths_use_identical_shared_acquisition(self): + targets=generate(self.manifest) + self.assertEqual(sum('XamarinBuildDownload Include=' in t for t in targets.values()),1) + for p in self.manifest['packages']: + text=targets[p['package']+'.targets'] + self.assertIn('DependsOnTargets="_XamarinBuildDownload"',text) + self.assertIn('maccatalyst',text) + self.assertIn('DesignTimeBuild',text) + self.assertIn('IsAppExtension',text) + gam=targets['AdamE.Google.iOS.GoogleAppMeasurement.targets'] + self.assertIn('FirebaseWithoutAdIdSupport',gam) + + +if __name__=='__main__':unittest.main() diff --git a/tests/fixtures/firebase13/13.1.1/METADATA.md b/tests/fixtures/firebase13/13.1.1/METADATA.md new file mode 100644 index 00000000..a8c2d0f9 --- /dev/null +++ b/tests/fixtures/firebase13/13.1.1/METADATA.md @@ -0,0 +1,163 @@ +## Dependency Graph + +"(~> X)" below means that the SDK requires all of the xcframeworks from X. You +should make sure to include all of the xcframeworks from X when including the +SDK. + +## FirebaseAnalytics +- FBLPromises.xcframework +- FirebaseAnalytics.xcframework +- FirebaseCore.xcframework +- FirebaseCoreInternal.xcframework +- FirebaseInstallations.xcframework +- GoogleAdsOnDeviceConversion.xcframework +- GoogleAppMeasurement.xcframework +- GoogleAppMeasurementIdentitySupport.xcframework +- GoogleUtilities.xcframework +- nanopb.xcframework + +## FirebaseABTesting (~> FirebaseAnalytics) +- FirebaseABTesting.xcframework + +## FirebaseAILogic (~> FirebaseAnalytics) +- AppCheckCore.xcframework +- FirebaseAILogic.xcframework +- FirebaseAppCheck.xcframework +- FirebaseAppCheckInterop.xcframework +- FirebaseAuthInterop.xcframework +- FirebaseCoreExtension.xcframework +- RecaptchaInterop.xcframework + +## FirebaseAppCheck (~> FirebaseAnalytics) +- AppCheckCore.xcframework +- FirebaseAppCheck.xcframework +- FirebaseAppCheckInterop.xcframework +- RecaptchaInterop.xcframework + +## FirebaseAppDistribution (~> FirebaseAnalytics) +- FirebaseAppDistribution.xcframework + +## FirebaseAuth (~> FirebaseAnalytics) +- FirebaseAppCheckInterop.xcframework +- FirebaseAuth.xcframework +- FirebaseAuthInterop.xcframework +- FirebaseCoreExtension.xcframework +- GTMSessionFetcher.xcframework +- RecaptchaInterop.xcframework + +## FirebaseCrashlytics (~> FirebaseAnalytics) +- FirebaseCoreExtension.xcframework +- FirebaseCrashlytics.xcframework +- FirebaseRemoteConfigInterop.xcframework +- FirebaseSessions.xcframework +- GoogleDataTransport.xcframework + +## FirebaseDatabase (~> FirebaseAnalytics) +- FirebaseAppCheckInterop.xcframework +- FirebaseDatabase.xcframework +- FirebaseSharedSwift.xcframework +- leveldb.xcframework + +## FirebaseFirestore (~> FirebaseAnalytics) +- FirebaseAppCheckInterop.xcframework +- FirebaseCoreExtension.xcframework +- FirebaseFirestore.xcframework +- FirebaseFirestoreInternal.xcframework +- FirebaseSharedSwift.xcframework +- absl.xcframework +- grpc.xcframework +- grpcpp.xcframework +- leveldb.xcframework +- openssl_grpc.xcframework + +## FirebaseFunctions (~> FirebaseAnalytics) +- FirebaseAppCheckInterop.xcframework +- FirebaseAuthInterop.xcframework +- FirebaseCoreExtension.xcframework +- FirebaseFunctions.xcframework +- FirebaseMessagingInterop.xcframework +- FirebaseSharedSwift.xcframework +- GTMSessionFetcher.xcframework + +## FirebaseInAppMessaging (~> FirebaseAnalytics) +- FirebaseABTesting.xcframework +- FirebaseInAppMessaging.xcframework + +## FirebaseMessaging (~> FirebaseAnalytics) +- FirebaseMessaging.xcframework +- GoogleDataTransport.xcframework + +## FirebasePerformance (~> FirebaseAnalytics) +- FirebaseABTesting.xcframework +- FirebaseCoreExtension.xcframework +- FirebasePerformance.xcframework +- FirebaseRemoteConfig.xcframework +- FirebaseRemoteConfigInterop.xcframework +- FirebaseSessions.xcframework +- FirebaseSharedSwift.xcframework +- GoogleDataTransport.xcframework + +## FirebaseRemoteConfig (~> FirebaseAnalytics) +- FirebaseABTesting.xcframework +- FirebaseRemoteConfig.xcframework +- FirebaseRemoteConfigInterop.xcframework +- FirebaseSharedSwift.xcframework + +## FirebaseStorage (~> FirebaseAnalytics) +- FirebaseAppCheckInterop.xcframework +- FirebaseAuthInterop.xcframework +- FirebaseCoreExtension.xcframework +- FirebaseStorage.xcframework +- GTMSessionFetcher.xcframework + + + +## Versions + +The xcframeworks in this directory map to these versions of the Firebase SDKs in +CocoaPods. + + CocoaPod | Version +----------------------------|--------- +AppCheckCore | 12.0.0 +BoringSSL-GRPC | 0.0.42 +Firebase | 13.1.1 +FirebaseABTesting | 13.1.1 +FirebaseAILogic | 13.1.1 +FirebaseAnalytics | 13.1.1 +FirebaseAppCheck | 13.1.1 +FirebaseAppCheckInterop | 13.1.1 +FirebaseAppDistribution | 13.1.1-beta +FirebaseAuth | 13.1.1 +FirebaseAuthInterop | 13.1.1 +FirebaseCore | 13.1.1 +FirebaseCoreExtension | 13.1.1 +FirebaseCoreInternal | 13.1.1 +FirebaseCrashlytics | 13.1.1 +FirebaseDatabase | 13.1.1 +FirebaseFirestore | 13.1.1 +FirebaseFirestoreInternal | 13.1.1 +FirebaseFunctions | 13.1.1 +FirebaseInAppMessaging | 13.1.1-beta +FirebaseInstallations | 13.1.1 +FirebaseMessaging | 13.1.1 +FirebaseMessagingInterop | 13.1.1 +FirebasePerformance | 13.1.1 +FirebaseRemoteConfig | 13.1.1 +FirebaseRemoteConfigInterop | 13.1.1 +FirebaseSessions | 13.1.1 +FirebaseSharedSwift | 13.1.1 +FirebaseStorage | 13.1.1 +GTMSessionFetcher | 5.3.1 +GoogleAdsOnDeviceConversion | 3.7.0 +GoogleAppMeasurement | 13.1.1 +GoogleDataTransport | 10.1.1 +GoogleUtilities | 8.1.5 +PromisesObjC | 2.4.1 +RecaptchaInterop | 101.0.0 +abseil | 1.20250512.2 +gRPC-C++ | 1.83.1 +gRPC-Core | 1.83.1 +leveldb-library | 1.22.6 +nanopb | 3.30910.0 + diff --git a/tests/fixtures/firebase13/13.1.1/Package.swift b/tests/fixtures/firebase13/13.1.1/Package.swift new file mode 100644 index 00000000..113ab636 --- /dev/null +++ b/tests/fixtures/firebase13/13.1.1/Package.swift @@ -0,0 +1,1795 @@ +// 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.1.1" + +/// If you don't use Firestore in your app, you can disable the "Firestore" trait to reduce +/// the number of dependencies fetched by SwiftPM during package resolution. +let firestoreTrait = Trait( + name: "Firestore", + description: "Enables Firestore support and its underlying dependencies (gRPC, Abseil)." +) + +/// Package traits allow developers to opt out of features, including their dependencies. +/// +/// In a `Package.swift`: +/// ```swift +/// .package( +/// url: "https://github.com/firebase/firebase-ios-sdk.git", +/// from: "13.0.0", +/// traits: [ +/// // Leave empty (or list only non-Firestore traits) to opt out. +/// ] +/// ) +/// ``` +/// +/// In Xcode (26.4+): +/// - Select your project -> Package Dependencies -> in the Traits dropdown for Firebase, +/// uncheck any unwanted traits. +let packageTraits = Set([ + firestoreTrait, + // All traits are enabled by default. + .default(enabledTraits: [firestoreTrait.name]), +]) + +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.0.1/FirebaseAnalytics.zip", + checksum: "0122046d46caca4795e3c71b56c68ad5549d892853815c028854f02e9fe14ed7" + ), + .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: .when(traits: ["Firestore"])), + ], + 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", + ], + // TODO(ncooke3): Can this be upgraded to Swift 6? + swiftSettings: [ + .swiftLanguageMode(SwiftLanguageMode.v5), + ] + ), + .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", + exclude: [ + "FIRMessagingContextManagerServiceTest.m", // TODO: Adapt its NSBundle usage to SPM. + ], + 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: .when(traits: ["Firestore"])), + "FirebaseFunctionsCombineSwift", + "FirebaseStorageCombineSwift", + "FirebaseCrashlytics", + "FirebaseCore", + "FirebaseDatabase", + .target(name: "FirebaseFirestoreTarget", + condition: .when(traits: ["Firestore"])), + "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: .when(traits: ["Firestore"])), + "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", .when(traits: ["Firestore"]))] + ), + .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.0.1" ..< "13.1.0") +} + +func abseilDependency() -> Package.Dependency { + let packageInfo: (url: String, range: Range) + + // 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) + + // 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: .when( + platforms: [.iOS, .tvOS, .macOS, .visionOS, .macCatalyst], + traits: ["Firestore"] + ) + ), + ], + path: "SwiftPM-PlatformExclude/FirebaseFirestoreWrap", + cSettings: [.define("FIRESTORE_TRAIT_ENABLED", .when(traits: ["Firestore"]))] + ) + } + + return .target( + name: "FirebaseFirestoreTarget", + dependencies: [.target(name: "FirebaseFirestore", + condition: .when(platforms: [.iOS, .tvOS, .macOS, .macCatalyst], + traits: ["Firestore"]))], + path: "SwiftPM-PlatformExclude/FirebaseFirestoreWrap", + cSettings: [ + .define("FIREBASE_BINARY_FIRESTORE", to: "1"), + .define("FIRESTORE_TRAIT_ENABLED", .when(traits: ["Firestore"])), + ] + ) +} + +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: .when(traits: ["Firestore"])), + .product(name: "gRPC-cpp", package: "grpc-ios", + condition: .when(traits: ["Firestore"])), + ], + 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.1.1/rc0/FirebaseFirestoreInternal.zip", + checksum: "2d6be52d2f387b34a60e92ed8b14b4a9bb06c7b147014e6ed560dc92ca4b09af" + ) + } + }() + + return [ + .target( + name: "FirebaseFirestore", + dependencies: [ + .target( + name: "FirebaseFirestoreInternalWrapper", + condition: .when(platforms: [.iOS, .macCatalyst, .tvOS, .macOS], + traits: ["Firestore"]) + ), + .product( + name: "abseil", + package: "abseil-cpp-binary", + condition: .when(platforms: [.iOS, .macCatalyst, .tvOS, .macOS], + traits: ["Firestore"]) + ), + .product( + name: "gRPC-C++", + package: "grpc-binary", + condition: .when(platforms: [.iOS, .macCatalyst, .tvOS, .macOS], + traits: ["Firestore"]) + ), + .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: .when(platforms: [.iOS, .macCatalyst, .tvOS, .macOS], + traits: ["Firestore"]) + )], + path: "FirebaseFirestoreInternal", + publicHeadersPath: "." + ), + firestoreInternalTarget, + ] +} + +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"] { + return .package(path: localPath) + } + + if let branch = Context.environment["FIREBASE_APP_CHECK_BRANCH"] { + return .package(url: appCheckURL, branch: branch) + } + + return .package(url: appCheckURL, "12.0.0" ..< "13.0.0") +} diff --git a/tests/fixtures/legacy-producer/signin-10.1.0.json b/tests/fixtures/legacy-producer/signin-10.1.0.json new file mode 100644 index 00000000..d97db036 --- /dev/null +++ b/tests/fixtures/legacy-producer/signin-10.1.0.json @@ -0,0 +1,337 @@ +{ + "releaseVersion": "10.1.0", + "sourceCommit": "993ecb4485404d3aaba66d0431c54cfa86e14300", + "metadata": [ + { + "key": "Google.GTMSessionFetcher", + "id": "AdamE.Google.iOS.GTMSessionFetcher", + "version": "3.5.0.8", + "project": "source/Google/GTMSessionFetcher/GTMSessionFetcher.csproj", + "firebase": false, + "minimumOS": "15.0", + "dependencies": [], + "pods": [ + { + "Name": "GTMSessionFetcher", + "Version": "3.5.0", + "LocalPath": null, + "Repository": null, + "TargetName": "GTMSessionFetcher", + "FrameworkName": "GTMSessionFetcher", + "SubSpecs": [ + "Full" + ], + "UseDefaultSubspecs": false, + "FrameworkSource": 1, + "CanBeBuild": true, + "Source": 0 + } + ], + "extraPodfileLines": [ + "=begin", + "This override the static_framework flag to false,", + "in order to be able to build dynamic frameworks.", + "=end", + "pre_install do |installer|", + "\tinstaller.pod_targets.each do |pod|", + "\tputs \"Forcing a static_framework to false for #{pod.name}\"", + "\t\tif Pod::VERSION >= \"1.7.0\"", + "\t\t\tif pod.build_as_static?", + "\t\t\t\tdef pod.build_as_static?; false end", + "\t\t\t\tdef pod.build_as_static_framework?; false end", + "\t\t\t\tdef pod.build_as_dynamic?; true end", + "\t\t\t\tdef pod.build_as_dynamic_framework?; true end", + "\t\t\tend", + "\t\telse", + "\t\t\tdef pod.static_framework?; false end", + "\t\tend", + "\tend", + "end", + "=begin", + "It seems that there is an issue with bundles and Xcode 14, it asks for your Team ID to sign them when building.", + "Here's a workaround for this: https://github.com/CocoaPods/CocoaPods/issues/8891#issuecomment-1201465446", + "=end", + "post_install do |installer|", + "\tinstaller.pods_project.targets.each do |target|", + "\t\tif target.respond_to?(:product_type) and target.product_type == \"com.apple.product-type.bundle\"", + "\t\t\ttarget.build_configurations.each do |config|", + "\t\t\t\tputs \"Setting 'CODE_SIGNING_ALLOWED' to 'NO' for #{target.name}\"", + "\t\t\t\tconfig.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'", + "\t\t\tend", + "\t\tend", + "\tend", + "end" + ], + "downloads": {} + }, + { + "key": "Google.PromisesObjC", + "id": "AdamE.Google.iOS.PromisesObjC", + "version": "2.4.0.8", + "project": "source/Google/PromisesObjC/PromisesObjC.csproj", + "firebase": false, + "minimumOS": "15.0", + "dependencies": [], + "pods": [ + { + "Name": "PromisesObjC", + "Version": "2.4.0", + "LocalPath": null, + "Repository": null, + "TargetName": "PromisesObjC", + "FrameworkName": "FBLPromises", + "SubSpecs": null, + "UseDefaultSubspecs": false, + "FrameworkSource": 1, + "CanBeBuild": true, + "Source": 0 + } + ], + "extraPodfileLines": [ + "=begin", + "This override the static_framework flag to false,", + "in order to be able to build dynamic frameworks.", + "=end", + "pre_install do |installer|", + "\tinstaller.pod_targets.each do |pod|", + "\tputs \"Forcing a static_framework to false for #{pod.name}\"", + "\t\tif Pod::VERSION >= \"1.7.0\"", + "\t\t\tif pod.build_as_static?", + "\t\t\t\tdef pod.build_as_static?; false end", + "\t\t\t\tdef pod.build_as_static_framework?; false end", + "\t\t\t\tdef pod.build_as_dynamic?; true end", + "\t\t\t\tdef pod.build_as_dynamic_framework?; true end", + "\t\t\tend", + "\t\telse", + "\t\t\tdef pod.static_framework?; false end", + "\t\tend", + "\tend", + "end", + "=begin", + "It seems that there is an issue with bundles and Xcode 14, it asks for your Team ID to sign them when building.", + "Here's a workaround for this: https://github.com/CocoaPods/CocoaPods/issues/8891#issuecomment-1201465446", + "=end", + "post_install do |installer|", + "\tinstaller.pods_project.targets.each do |target|", + "\t\tif target.respond_to?(:product_type) and target.product_type == \"com.apple.product-type.bundle\"", + "\t\t\ttarget.build_configurations.each do |config|", + "\t\t\t\tputs \"Setting 'CODE_SIGNING_ALLOWED' to 'NO' for #{target.name}\"", + "\t\t\t\tconfig.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'", + "\t\t\tend", + "\t\tend", + "\tend", + "end" + ], + "downloads": {} + }, + { + "key": "Google.GoogleUtilities", + "id": "AdamE.Google.iOS.GoogleUtilities", + "version": "8.1.5", + "project": "source/Google/GoogleUtilities/GoogleUtilities.csproj", + "firebase": false, + "minimumOS": "15.0", + "dependencies": [], + "pods": [ + { + "Name": "GoogleUtilities", + "Version": "8.1.5", + "LocalPath": null, + "Repository": null, + "TargetName": "GoogleUtilities", + "FrameworkName": "GoogleUtilities", + "SubSpecs": [ + "AppDelegateSwizzler", + "Environment", + "Logger", + "MethodSwizzler", + "Network", + "NSData+zlib", + "Privacy", + "Reachability", + "UserDefaults" + ], + "UseDefaultSubspecs": false, + "FrameworkSource": 1, + "CanBeBuild": true, + "Source": 0 + } + ], + "extraPodfileLines": [ + "=begin", + "This override the static_framework flag to false,", + "in order to be able to build dynamic frameworks.", + "=end", + "pre_install do |installer|", + "\tinstaller.pod_targets.each do |pod|", + "\tputs \"Forcing a static_framework to false for #{pod.name}\"", + "\t\tif Pod::VERSION >= \"1.7.0\"", + "\t\t\tif pod.build_as_static?", + "\t\t\t\tdef pod.build_as_static?; false end", + "\t\t\t\tdef pod.build_as_static_framework?; false end", + "\t\t\t\tdef pod.build_as_dynamic?; true end", + "\t\t\t\tdef pod.build_as_dynamic_framework?; true end", + "\t\t\tend", + "\t\telse", + "\t\t\tdef pod.static_framework?; false end", + "\t\tend", + "\tend", + "end", + "=begin", + "It seems that there is an issue with bundles and Xcode 14, it asks for your Team ID to sign them when building.", + "Here's a workaround for this: https://github.com/CocoaPods/CocoaPods/issues/8891#issuecomment-1201465446", + "=end", + "post_install do |installer|", + "\tinstaller.pods_project.targets.each do |target|", + "\t\tif target.respond_to?(:product_type) and target.product_type == \"com.apple.product-type.bundle\"", + "\t\t\ttarget.build_configurations.each do |config|", + "\t\t\t\tputs \"Setting 'CODE_SIGNING_ALLOWED' to 'NO' for #{target.name}\"", + "\t\t\t\tconfig.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'", + "\t\t\tend", + "\t\tend", + "\tend", + "end" + ], + "downloads": {} + }, + { + "key": "Google.AppCheckCore", + "id": "AdamE.Google.iOS.AppCheckCore", + "version": "11.3.2", + "project": "source/Google/AppCheckCore/AppCheckCore.csproj", + "firebase": false, + "minimumOS": "15.0", + "dependencies": [ + "AdamE.Google.iOS.PromisesObjC", + "AdamE.Google.iOS.GoogleUtilities" + ], + "pods": [ + { + "Name": "AppCheckCore", + "Version": "11.3.2", + "LocalPath": null, + "Repository": null, + "TargetName": "AppCheckCore", + "FrameworkName": "AppCheckCore", + "SubSpecs": null, + "UseDefaultSubspecs": false, + "FrameworkSource": 1, + "CanBeBuild": true, + "Source": 0 + }, + { + "Name": "PromisesSwift", + "Version": "2.4.0", + "LocalPath": null, + "Repository": null, + "TargetName": "PromisesSwift", + "FrameworkName": "Promises", + "SubSpecs": null, + "UseDefaultSubspecs": false, + "FrameworkSource": 1, + "CanBeBuild": true, + "Source": 0 + }, + { + "Name": "RecaptchaInterop", + "Version": "101.0.0", + "LocalPath": null, + "Repository": null, + "TargetName": "RecaptchaInterop", + "FrameworkName": "RecaptchaInterop", + "SubSpecs": null, + "UseDefaultSubspecs": false, + "FrameworkSource": 1, + "CanBeBuild": true, + "Source": 0 + } + ], + "extraPodfileLines": null, + "downloads": {} + }, + { + "key": "Google.SignIn", + "id": "AdamE.Google.iOS.SignIn", + "version": "10.1.0.0", + "project": "source/Google/SignIn/SignIn.csproj", + "firebase": false, + "minimumOS": "15.0", + "dependencies": [ + "AdamE.Google.iOS.GTMSessionFetcher", + "AdamE.Google.iOS.PromisesObjC", + "AdamE.Google.iOS.GoogleUtilities", + "AdamE.Google.iOS.AppCheckCore" + ], + "pods": [ + { + "Name": "GoogleSignIn", + "Version": "10.1.0", + "LocalPath": null, + "Repository": null, + "TargetName": "GoogleSignIn", + "FrameworkName": "GoogleSignIn", + "SubSpecs": null, + "UseDefaultSubspecs": false, + "FrameworkSource": 1, + "CanBeBuild": true, + "Source": 0 + }, + { + "Name": "AppAuth", + "Version": "3.0.0", + "LocalPath": null, + "Repository": null, + "TargetName": "AppAuth", + "FrameworkName": "AppAuth", + "SubSpecs": null, + "UseDefaultSubspecs": false, + "FrameworkSource": 1, + "CanBeBuild": true, + "Source": 0 + }, + { + "Name": "GTMAppAuth", + "Version": "6.0.0", + "LocalPath": null, + "Repository": null, + "TargetName": "GTMAppAuth", + "FrameworkName": "GTMAppAuth", + "SubSpecs": null, + "UseDefaultSubspecs": false, + "FrameworkSource": 1, + "CanBeBuild": true, + "Source": 0 + } + ], + "extraPodfileLines": null, + "downloads": {} + } + ], + "expected": [ + { + "id": "AdamE.Google.iOS.GTMSessionFetcher", + "version": "3.5.0.8", + "fingerprint": "25115d8d920b761497cd6aa9b3c7012f3be9e58de0f9d1c4d86eddc5db292439" + }, + { + "id": "AdamE.Google.iOS.PromisesObjC", + "version": "2.4.0.8", + "fingerprint": "ac5ba1504344939c636bc30b1b63ce206680db52eeb8168581446aca4eb3d72e" + }, + { + "id": "AdamE.Google.iOS.GoogleUtilities", + "version": "8.1.5", + "fingerprint": "ffddb83f904a886014adf691977624c97bdf4e7d9214c2b8a839caa6c0872d1d" + }, + { + "id": "AdamE.Google.iOS.AppCheckCore", + "version": "11.3.2", + "fingerprint": "149e7cd543d38625256ec3ef39965e7ebd4bfb82ccb8e012d70518f16b7212fb" + }, + { + "id": "AdamE.Google.iOS.SignIn", + "version": "10.1.0.0", + "fingerprint": "43897f64400ad905755601175d44b49de47c3c88725a3532409ac3b78654ea8e" + } + ] +} diff --git a/tests/legacy-producer/test_producer.py b/tests/legacy-producer/test_producer.py new file mode 100644 index 00000000..8d54b6d2 --- /dev/null +++ b/tests/legacy-producer/test_producer.py @@ -0,0 +1,138 @@ +import copy +import importlib.util +import json +from pathlib import Path +import subprocess +import tempfile +import unittest +import zipfile + +ROOT=Path(__file__).resolve().parents[2] +def load(name,path): + spec=importlib.util.spec_from_file_location(name,ROOT/path) + module=importlib.util.module_from_spec(spec);spec.loader.exec_module(module);return module +producer=load('legacy_producer_tests','tools/legacy/producer.py') +release=load('legacy_release_tests','scripts/firebase-release/release.py') + + +class LegacyProducerTests(unittest.TestCase): + def setUp(self): + self.data=producer.lock() + self.manifest=json.loads((ROOT/'source/Firebase/native-assets.json').read_text()) + + def test_signin_uses_unchanged_five_package_baseline(self): + plan=producer.plan(self.data,self.manifest,'Google.SignIn') + self.assertEqual(plan['firebase13'],[]) + self.assertEqual(plan['legacy'],['Google.SignIn']) + records={p['key']:p for p in plan['legacyPackages']} + self.assertEqual(len(records),5) + self.assertEqual(records['Google.SignIn']['version'],'10.1.0.0') + self.assertTrue(records['Google.AppCheckCore']['version'].startswith('11.')) + self.assertTrue(records['Google.GTMSessionFetcher']['version'].startswith('3.')) + + def test_deferred_products_keep_their_historical_closures(self): + for key in ('Google.Cast','Google.TagManager','Google.UserMessagingPlatform','MLKit.Core','MLKit.BarcodeScanning','Google.Maps','Google.Places'): + with self.subTest(key=key): + plan=producer.plan(self.data,self.manifest,key) + self.assertFalse(plan['firebase13']) + self.assertIn(key,[p['key'] for p in plan['legacyPackages']]) + for p in plan['legacyPackages']: + if p['id'].startswith('AdamE.Firebase.'): + self.assertTrue(p['version'].startswith('12.')) + + def test_default_and_mixed_selections_partition_without_mutating_the_manifest(self): + default=producer.plan(self.data,self.manifest,'') + self.assertEqual(len(default['firebase13']),23) + self.assertEqual(set(default['legacy'])|set(default['firebase13']),{p['key'] for p in self.data['artifacts']}) + self.assertFalse(set(default['legacy'])&set(default['firebase13'])) + mixed=producer.plan(self.data,self.manifest,'Google.SignIn,Firebase.Auth') + self.assertEqual(mixed['legacy'],['Google.SignIn']);self.assertEqual(mixed['firebase13'],['Firebase.Auth']) + modern=producer.plan(self.data,self.manifest,'Google.GoogleAppMeasurement') + self.assertEqual(modern['firebase13'],['Google.GoogleAppMeasurement']) + self.assertEqual(self.manifest,json.loads((ROOT/'source/Firebase/native-assets.json').read_text())) + + def test_explicit_legacy_fixture_selection_remains_firebase12(self): + plan=producer.plan(self.data,self.manifest,'Firebase.Auth,Firebase.Analytics,Firebase.CloudFirestore','legacy') + self.assertFalse(plan['firebase13']) + self.assertTrue(all(not p['id'].startswith('AdamE.Firebase.') or p['version'].startswith('12.') for p in plan['legacyPackages'])) + with self.assertRaisesRegex(ValueError,'Unknown component'):producer.plan(self.data,self.manifest,'MLKit.NotRegistered') + with self.assertRaisesRegex(ValueError,'cycle'): + data=copy.deepcopy(self.data);data['artifacts'][0]['dependencies']=[data['artifacts'][0]['key']] + producer.closure(data,[data['artifacts'][0]['key']]) + + def test_no_publication_command_exists(self): + result=subprocess.run(['python3',str(ROOT/'tools/legacy/producer.py'),'publish'],capture_output=True,text=True) + self.assertNotEqual(0,result.returncode);self.assertIn('invalid choice',result.stderr) + + def test_materialization_is_pinned_and_never_copies_untracked_secrets(self): + with tempfile.TemporaryDirectory() as tmp: + root=Path(tmp);self.git_fixture(root) + (root/'tracked.txt').write_text('current checkout') + (root/'secret').write_text('fixture must never be archived') + with producer.source_tree(root) as stage: + self.assertEqual((stage/'tracked.txt').read_text(),'baseline') + self.assertFalse((stage/'secret').exists()) + location=stage + self.assertFalse(location.exists()) + self.assertEqual((root/'tracked.txt').read_text(),'current checkout') + + def git_fixture(self,root): + subprocess.run(['git','init','--quiet',str(root)],check=True) + (root/'tracked.txt').write_text('baseline') + (root/'.gitignore').write_text('secret\noutput\n') + path=root/'source/Google/SignIn/SignIn.csproj';path.parent.mkdir(parents=True) + path.write_text('') + (root/'README.md').write_text('baseline notice') + for name in ('Directory.Build.props','global.json','.config/dotnet-tools.json','source/AssemblyInfo.cs','common.cake','poco.cake','custom_externals_download.cake'): + target=root/name;target.parent.mkdir(parents=True,exist_ok=True);target.write_text('fixture input') + subprocess.run(['git','add','.'],cwd=root,check=True) + subprocess.run(['git','-c','user.name=Fixture','-c','user.email=fixture@example.invalid','commit','--quiet','-m','fixture'],cwd=root,check=True) + commit=subprocess.check_output(['git','rev-parse','HEAD'],cwd=root,text=True).strip() + tree=subprocess.check_output(['git','rev-parse','HEAD^{tree}'],cwd=root,text=True).strip() + data={'schema':1,'commit':commit,'tree':tree,'artifacts':[dict(key='Google.SignIn',artifactId='Google.SignIn',id='AdamE.Google.iOS.SignIn',version='10.1.0.0',project=str(path.relative_to(root)),dependencies=[])]} + (root/'eng').mkdir();(root/producer.LOCK).write_text(json.dumps(data));return data + + def test_future_product_edits_fail_instead_of_silently_using_stale_source(self): + with tempfile.TemporaryDirectory() as tmp: + root=Path(tmp);data=self.git_fixture(root) + with producer.source_tree(root) as stage: + (root/data['artifacts'][0]['project']).write_text('changed binding') + with self.assertRaisesRegex(ValueError,'Non-Firebase product changed'): + producer.verify_nonfirebase_inputs(root,stage,data,{'packages':[]}) + data['tree']='0'*40;(root/producer.LOCK).write_text(json.dumps(data)) + with self.assertRaisesRegex(ValueError,'tree differs'): + with producer.source_tree(root):pass + + def test_packed_readme_edits_are_not_silently_ignored(self): + with tempfile.TemporaryDirectory() as tmp: + root=Path(tmp);data=self.git_fixture(root) + with producer.source_tree(root) as stage: + (root/'README.md').write_text('changed package documentation') + with self.assertRaisesRegex(ValueError,'Legacy producer input changed.*README.md'): + producer.verify_nonfirebase_inputs(root,stage,data,{'packages':[]}) + + def test_wrong_missing_or_extra_package_outputs_are_rejected(self): + with tempfile.TemporaryDirectory() as tmp: + root=Path(tmp);stage=root/'stage';(stage/'output').mkdir(parents=True) + item=next(p for p in self.data['artifacts'] if p['key']=='Google.SignIn') + with self.assertRaisesRegex(ValueError,'Missing legacy output'):producer.copy_outputs(root,stage,[item],True) + file=stage/'output/fixture.nupkg' + def package(id,version): + with zipfile.ZipFile(file,'w') as z:z.writestr('fixture.nuspec',f'{id}{version}') + package(item['id'],'10.1.0.1') + with self.assertRaisesRegex(ValueError,'version changed'):producer.copy_outputs(root,stage,[item],True) + package('AdamE.Unrelated','10.1.0') + with self.assertRaisesRegex(ValueError,'Unexpected legacy output'):producer.copy_outputs(root,stage,[item],True) + package(item['id'],'10.1.0');producer.copy_outputs(root,stage,[item],True) + self.assertEqual((root/'output/fixture.nupkg').read_bytes(),file.read_bytes()) + + def test_effective_inputs_match_the_published_1010_fingerprints(self): + fixture=json.loads((ROOT/'tests/fixtures/legacy-producer/signin-10.1.0.json').read_text()) + release.configure_channel('signin') + try: + actual=release.snapshot(fixture['metadata']) + self.assertEqual([{k:p[k] for k in ('id','version','fingerprint')} for p in actual],fixture['expected']) + finally:release.configure_channel('firebase') + + +if __name__=='__main__':unittest.main() diff --git a/tools/firebase13/acquire.proj b/tools/firebase13/acquire.proj new file mode 100644 index 00000000..6747b49e --- /dev/null +++ b/tools/firebase13/acquire.proj @@ -0,0 +1,16 @@ + + + net10.0 + false + + + + + https://github.com/firebase/firebase-ios-sdk/releases/download/13.1.1/Firebase.zip + Zip + eab04111b6b6ebd2bbd9264b452b2eec5be13703207f32f7cf10d9040e246b70 + 1800 + + + + diff --git a/tools/firebase13/archive_safety.py b/tools/firebase13/archive_safety.py new file mode 100644 index 00000000..9d408707 --- /dev/null +++ b/tools/firebase13/archive_safety.py @@ -0,0 +1,48 @@ +"""Producer archive preflight; consumer extraction remains stock XBD.""" +import posixpath +import stat +import zipfile +from pathlib import PurePosixPath + +def preflight(archive): + names = set() + files = set() + links = {} + with zipfile.ZipFile(archive) as source: + for item in source.infolist(): + name = item.filename.rstrip('/') + path = PurePosixPath(name) + if (not name or path.is_absolute() or '\\' in name or ':' in name + or any(part in ('', '.', '..') for part in name.split('/'))): + raise ValueError(f'Unsafe archive path: {item.filename}') + if name.casefold() in names: + raise ValueError(f'Archive destination collision: {name}') + names.add(name.casefold()) + mode = stat.S_IFMT(item.external_attr >> 16) + if mode not in (0, stat.S_IFREG, stat.S_IFDIR, stat.S_IFLNK): + raise ValueError(f'Unsupported archive file type: {name}') + if not item.is_dir(): + files.add(name.casefold()) + if stat.S_ISLNK(item.external_attr >> 16): + target = source.read(item).decode('utf-8') + if not target or target.startswith('/') or '\\' in target or ':' in target: + raise ValueError(f'Unsafe link target: {name} -> {target}') + resolved = posixpath.normpath(posixpath.join(posixpath.dirname(name), target)) + if not resolved.startswith('Firebase/'): + raise ValueError(f'Escaping archive link: {name} -> {target}') + links[name] = resolved + for name in names: + parents = PurePosixPath(name).parents + if any(str(parent) in files for parent in parents): + raise ValueError(f'Archive file/directory destination collision: {name}') + for name in links: + current = links[name] + visited = {name} + while current in links: + if current in visited: + raise ValueError(f'Cyclic archive link: {name}') + visited.add(current) + current = links[current] + # Never extract actual entries through a link declared by the archive. + if any(other != name and other.startswith(name + '/') for other in source.namelist()): + raise ValueError(f'Archive writes through a link: {name}') diff --git a/tools/firebase13/audit.py b/tools/firebase13/audit.py new file mode 100644 index 00000000..cce9efb5 --- /dev/null +++ b/tools/firebase13/audit.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +"""Run the existing binding audit against the pinned, prebuilt Firebase closure only.""" +import argparse +import json +from pathlib import Path +import subprocess +from generate import ROOT, MANIFEST +from native import archive_validate, validate_schema + + +def main(): + parser=argparse.ArgumentParser(description=__doc__) + parser.add_argument('--cache',type=Path,required=True) + parser.add_argument('--archive',type=Path) + parser.add_argument('--sharpie-path',required=True) + args=parser.parse_args() + m=json.loads(MANIFEST.read_text());validate_schema(m) + archive_validate(m,args.archive or args.cache/(m['source']['id']+'.zip')) + directory=ROOT/'externals';directory.mkdir(exist_ok=True) + for package in m['packages']: + for asset in package['assets']: + if asset['kind']!='XCFramework':continue + source=(args.cache/m['source']['id']/asset['path']).resolve() + if not source.exists():raise ValueError('Acquire the pinned archive before auditing: '+str(source)) + destination=directory/source.name + if destination.is_symlink() and destination.resolve()==source:continue + if destination.exists() or destination.is_symlink(): + raise ValueError('Existing native input would be overwritten; use a clean feature worktree: '+str(destination)) + destination.symlink_to(source,target_is_directory=True) + targets=','.join(p['id'].split('.',1)[1] for p in m['packages'] if p['id'].startswith('Firebase.')) + subprocess.run(['scripts/compare-firebase-bindings.sh','--targets',targets,'--sharpie-path',args.sharpie_path, + '--output-dir','output/firebase13-api-audit'],cwd=ROOT,check=True) + + +if __name__=='__main__':main() diff --git a/tools/firebase13/check_symbols.py b/tools/firebase13/check_symbols.py new file mode 100644 index 00000000..d4cc2643 --- /dev/null +++ b/tools/firebase13/check_symbols.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python3 +"""Check every explicitly named Firebase Objective-C binding class against native exports. + +This catches class renames that package layout checks cannot detect. It does not establish +selector coverage, authentication behavior, or service correctness. +""" +import json +from pathlib import Path +import re +import subprocess + +ROOT = Path(__file__).resolve().parents[2] + + +def main(): + manifest = json.loads((ROOT / 'source/Firebase/native-assets.json').read_text()) + import argparse + parser = argparse.ArgumentParser() + parser.add_argument('--cache', type=Path, required=True) + args = parser.parse_args() + import plistlib + exports = set() + binaries = [] + architecture_checks = 0 + for package in manifest['packages']: + for asset in package['assets']: + if asset['kind'] != 'XCFramework': + continue + framework = args.cache / manifest['source']['id'] / asset['path'] + info = plistlib.loads((framework / 'Info.plist').read_bytes()) + for lib in info['AvailableLibraries']: + if lib['SupportedPlatform'] != 'ios': + continue + binary = framework / lib['LibraryIdentifier'] / lib['LibraryPath'] / framework.stem + architectures = subprocess.check_output(['xcrun', 'lipo', '-archs', str(binary)]).decode().split() + if set(architectures) != set(lib['SupportedArchitectures']): + raise ValueError('Mach-O architectures differ from XCFramework metadata: ' + str(binary)) + architecture_checks += 1 + if lib.get('SupportedPlatformVariant', '') == '': + binaries.append(binary) + if len(binaries) < 35: + raise ValueError('Acquire the verified Firebase archive before native-symbol validation') + for binary in binaries: + result = subprocess.run(['xcrun', 'nm', '-arch', 'arm64', '-gU', str(binary)], check=True, + stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + exports.update(re.findall(r'_OBJC_CLASS_\$_(\w+)', result.stdout)) + projects = [ROOT / p['project'] for p in manifest['packages']] + failures = [] + checked = 0 + for project in projects: + for source in project.parent.glob('*.cs'): + text = source.read_text(encoding='utf-8-sig') + for match in re.finditer(r'((?:\s*\[[^\]]*\])+\s*)interface\s+(\w+)', text): + attributes, managed_name = match.groups() + if '[Protocol' in attributes: + continue + base_type = re.search(r'\[BaseType\s*\([^\]]*Name\s*=\s*"([^"]+)"', attributes) + if base_type: + native_name = base_type.group(1) + checked += 1 + if native_name not in exports: + failures.append(f'{source.relative_to(ROOT)}: {managed_name} maps to missing {native_name}') + if failures: + raise ValueError('\n'.join(failures)) + print(f'Validated {checked} explicit Objective-C binding class names against {len(binaries)} native iOS libraries and {architecture_checks} actual Mach-O slices.') + + +if __name__ == '__main__': + main() diff --git a/tools/firebase13/consumers.py b/tools/firebase13/consumers.py new file mode 100644 index 00000000..e38d49fa --- /dev/null +++ b/tools/firebase13/consumers.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python3 +"""Exercise direct/transitive Firebase native acquisition and warm-cache offline builds.""" +import argparse +import json +import os +from pathlib import Path +import shutil +import subprocess +import tempfile +import time +from generate import ROOT, MANIFEST +from native import digest + +PROBE = '''using System; using System.IO; using System.Runtime.InteropServices; using Foundation; using UIKit; +class Program { static void Main(string[] args) => UIApplication.Main(args, null, typeof(AppDelegate)); } +[Register("AppDelegate")] public class AppDelegate : UIApplicationDelegate { public override bool FinishedLaunching(UIApplication app, NSDictionary options) => true; } +[Register("SceneDelegate")] public class SceneDelegate : UIWindowSceneDelegate { + public override UIWindow Window {get;set;} + [DllImport("/usr/lib/libobjc.dylib")] static extern IntPtr objc_getClass(string name); + public override void WillConnect(UIScene scene, UISceneSession session, UISceneConnectionOptions connectionOptions) { + Window=new UIWindow((UIWindowScene)scene) { RootViewController=new UIViewController() }; Window.MakeKeyAndVisible(); + string result; + try { + if (!Firebase.Core.App.FirebaseVersion.Equals("EXPECTED_FIREBASE_VERSION")) throw new Exception("Wrong Firebase runtime"); + foreach (var name in new[] { CLASS_NAMES }) if(objc_getClass(name)==IntPtr.Zero) throw new Exception("Missing class "+name); + EXTRA_PROBE + result="PASS Firebase " + Firebase.Core.App.FirebaseVersion; + } catch(Exception e) {result=e.ToString();} + File.WriteAllText(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments),"firebase13-result.txt"),result); + } +}''' + + +def snapshot(path): + return {str(p.relative_to(path)): digest(p) for p in path.rglob('*') if p.is_file() and not p.name.endswith('.locked')} + + +def main(): + parser=argparse.ArgumentParser(description=__doc__) + parser.add_argument('--resume',type=Path) + parser.add_argument('--platform',choices=['ios','maccatalyst']) + parser.add_argument('--scope',choices=['core','combined','all'],default='combined') + parser.add_argument('--without-ad-id',action='store_true') + parser.add_argument('--quick',action='store_true',help='Direct iOS simulator only; the default includes device/Catalyst/transitive shapes') + parser.add_argument('--cache',type=Path,help='Reuse an existing XBD cache instead of testing a fresh acquisition') + args=parser.parse_args() + m=json.loads(MANIFEST.read_text());feed=ROOT/'output/firebase13' + label=args.scope+('-without-ad-id' if args.without_ad_id else '') + roots={'core':['Core'],'combined':['Analytics','Auth','CloudFirestore'],'all':[p['id'].split('.',1)[1] for p in m['packages'] if p['id'].startswith('Firebase.')]}[args.scope] + work=(args.resume or Path(tempfile.mkdtemp(prefix='firebase13-consumer-'))).resolve();print('WORKSPACE',work,flush=True) + results=ROOT/'output/firebase13-results';results.mkdir(parents=True,exist_ok=True) + (results/(label+'-workspace.txt')).write_text(str(work)) + shutil.copy2(ROOT/'global.json',work/'global.json') + cache=(args.cache or work/'xbd').resolve() + env=dict(os.environ,NUGET_PACKAGES=str(work/'nuget'),NUGET_HTTP_CACHE_PATH=str(work/'http'),XamarinBuildDownloadDir=str(cache)) + tools=work/'tools';tools.mkdir(exist_ok=True);pod=tools/'pod';pod.write_text('#!/bin/sh\ntouch "'+str(work/'pod-invoked')+'"\nexit 97\n');pod.chmod(0o755);env['PATH']=str(tools)+os.pathsep+env['PATH'] + offline=dict(env,NO_PROXY='localhost,127.0.0.1',no_proxy='localhost,127.0.0.1',NUGET_CERT_REVOCATION_MODE='offline') + for k in ('HTTP_PROXY','HTTPS_PROXY','ALL_PROXY','http_proxy','https_proxy','all_proxy'):offline[k]='http://127.0.0.1:9' + (work/'NuGet.config').write_text(f'') + def run(name,cmd,blocked=False): + print(name,flush=True) + with (results/(label+'-'+name+'.log')).open('w') as output: + p=subprocess.run(cmd,cwd=work,env=offline if blocked else env,stdout=output,stderr=subprocess.STDOUT) + if p.returncode:raise RuntimeError((results/(label+'-'+name+'.log')).read_text()[-10000:]) + projects=[] + for platform in ([args.platform] if args.platform else ['ios'] if args.quick else ['ios','maccatalyst']): + for transitive in ([False] if args.quick else [False,True]): + project=work/(platform+('-transitive' if transitive else '-direct'));project.mkdir(exist_ok=True) + versions={p['id'].split('.',1)[1]:p['version'] for p in m['packages'] if p['id'].startswith('Firebase.')} + refs=''.join(f'' for name in roots) + if transitive: + lib=project/'Library';lib.mkdir(exist_ok=True) + (lib/'Library.csproj').write_text(f'net10.0-{platform}{refs}') + (lib/'Class.cs').write_text('public class BindingConsumer { public static string Version => Firebase.Core.App.FirebaseVersion; }') + refs='' + minimum_os='17.0' if platform=='maccatalyst' else '15.0' + (project/'Probe.csproj').write_text(f'net10.0-{platform}{"iossimulator-arm64;ios-arm64" if platform=="ios" else "maccatalyst-arm64"}Exe{minimum_os}falsefalseNone{refs}') + classes=['FIRApp']+([] if args.scope=='core' else ['FIRAnalytics','FIRAuth','FIRFirestore','__FIRExprBridge','__FIRSortStageBridge']) + extra='' + if args.scope!='core': + extra='''var sortType=typeof(Firebase.CloudFirestore.SortStageBridge); + if(sortType==null) throw new Exception("Missing managed Firestore bridge"); + using var field=new Firebase.CloudFirestore.FieldBridge("field"); if(field.FieldName!="field") throw new Exception("Firestore bridge roundtrip failed"); + using var objectId=new Firebase.CloudFirestore.BsonObjectId("507f1f77bcf86cd799439011"); + using var sameId=new Firebase.CloudFirestore.BsonObjectId("507f1f77bcf86cd799439011"); if(!objectId.IsEqual(sameId)) throw new Exception("Inherited NSObject equality failed"); + using var timestamp=new Firebase.CloudFirestore.BsonTimestamp(7,2); + using var integer=new Firebase.CloudFirestore.Int32Value(42); + using var number=new Firebase.CloudFirestore.Decimal128Value("1.25"); + using var regex=new Firebase.CloudFirestore.RegexValue("a","i"); + using var bytes=NSData.FromArray(new byte[]{1,2}); + using var blob=Firebase.CloudFirestore.Blob.FromBsonBinary(bytes,128); + using var expression=new Firebase.CloudFirestore.ConstantBridge(new NSString("value")); + using var fields=NSDictionary.FromObjectsAndKeys(new Firebase.CloudFirestore.ExprBridge[]{expression},new NSString[]{new NSString("field")}); + using var updateStage=new Firebase.CloudFirestore.UpdateStageBridge(fields); + using var upsertStage=new Firebase.CloudFirestore.UpsertStageBridge(fields,null,null); + using var literalsStage=new Firebase.CloudFirestore.LiteralsSourceStageBridge(new[]{fields}); + if(typeof(Firebase.CloudFirestore.UpdateStageBridge).GetConstructor(new[]{typeof(NSDictionary)})!=null || + typeof(Firebase.CloudFirestore.UpsertStageBridge).GetConstructor(new[]{typeof(NSDictionary),typeof(string),typeof(Firebase.CloudFirestore.ExprBridge)})!=null || + typeof(Firebase.CloudFirestore.LiteralsSourceStageBridge).GetConstructor(new[]{typeof(NSDictionary[])})!=null) + throw new Exception("Untyped stage initializer must remain internal"); + using var databaseStage=new Firebase.CloudFirestore.DatabaseSourceStageBridge(); + using var deleteStage=new Firebase.CloudFirestore.DeleteStageBridge(); + if(objectId.Value!="507f1f77bcf86cd799439011" || timestamp.Seconds!=7 || timestamp.Increment!=2 || integer.Value!=42 || number.Value!="1.25" || regex.Pattern!="a" || regex.Options!="i" || blob.Subtype!=128 || blob.Bytes.Length!=2 || Firebase.CloudFirestore.MinKey.SharedInstance is null || Firebase.CloudFirestore.MaxKey.SharedInstance is null) + throw new Exception("Firebase13 BSON value roundtrip failed");''' + if args.scope=='all': + extra += """using(var metadata=new Firebase.Storage.StorageMetadata()) { + using var copy=metadata.Copy(); if(!metadata.IsEqual(copy) || metadata.Description==null) throw new Exception("Inherited Storage API failed"); + } + Action downloadApi=task=>{task.Enqueue();task.Pause();task.Cancel();task.Resume();}; + Action uploadApi=task=>{task.Enqueue();task.Pause();task.Cancel();task.Resume();}; + GC.KeepAlive(downloadApi); GC.KeepAlive(uploadApi); + """ + (project/'Main.cs').write_text(PROBE.replace('EXPECTED_FIREBASE_VERSION',m['releaseVersion']).replace('CLASS_NAMES',','.join('"'+n+'"' for n in classes)).replace('EXTRA_PROBE',extra)) + bundle='com.googleapisforioscomponents.firebase13.'+work.name.split('-')[-1]+'.'+platform+('.transitive' if transitive else '.direct') + (project/'Info.plist').write_text(f'CFBundleIdentifier{bundle}CFBundleShortVersionString1.0CFBundleVersion1UIApplicationSceneManifestUIApplicationSupportsMultipleScenesUISceneConfigurationsUIWindowSceneSessionRoleApplicationUISceneConfigurationNameDefault ConfigurationUISceneDelegateClassNameSceneDelegate') + projects.append((project,platform,bundle)) + before=snapshot(cache) + for project,platform,bundle in projects:run('restore-'+project.name,['dotnet','restore',str(project/'Probe.csproj'),'--force','--configfile',str(work/'NuGet.config')]) + assert snapshot(cache)==before,'Restore acquired native SDK files' + for p in m['packages']: + version=p['version'].removesuffix('.0') + restored=work/'nuget'/p['package'].lower()/version/(p['package'].lower()+'.'+version+'.nupkg') + if restored.exists(): + assert digest(restored)==digest(feed/(p['package']+'.'+version+'.nupkg')), 'Restored package differs from current candidate; rerun in a fresh workspace: '+p['package'] + restored_packages=snapshot(work/'nuget') + first=True;simulator=None + for project,platform,bundle in projects: + for rid in (['iossimulator-arm64'] if args.quick else (['iossimulator-arm64','ios-arm64'] if platform=='ios' else ['maccatalyst-arm64'])): + cmd=['dotnet','build',str(project/'Probe.csproj'),'-c','Debug','--no-restore','-p:RuntimeIdentifier='+rid,'-p:UseSharedCompilation=false','-p:BuildInParallel=false'] + if args.without_ad_id:cmd+=['-p:FirebaseWithoutAdIdSupport=True'] + if platform=='ios':cmd+=['-p:Platform='+('iPhoneSimulator' if 'simulator' in rid else 'iPhone'),'-p:SdkIsSimulator='+('true' if 'simulator' in rid else 'false')] + run(project.name+'-'+rid,cmd,blocked=not first) + warm=snapshot(cache) + run(project.name+'-'+rid+'-offline-rebuild',cmd+(['-t:Rebuild'] if first and not args.resume else []),blocked=True) + assert snapshot(cache)==warm,'Offline build modified the native cache' + assets=(project/'native-assets.txt').read_text().splitlines() + assert assets and len(assets)==len(set(assets)),'Missing/duplicate native references' + app=next(project.glob('bin/**/'+rid+'/Probe.app')) + for row in (project/'bundle-assets.txt').read_text().splitlines(): + source, logical = row.split('|',1) + if source.endswith('PrivacyInfo.xcprivacy'): + candidates=[app/logical,app/'Contents/Resources'/logical] + assert any(p.exists() and digest(p)==digest(Path(source)) for p in candidates), 'Missing/altered privacy resource: '+logical + bundles=[p.name for p in app.rglob('*.bundle')] + assert len(bundles)==len(set(bundles)),'Duplicate logical bundles' + if args.scope!='core':assert ('GoogleAdsOnDeviceConversion.xcframework' in '\n'.join(assets)) == (platform=='ios' and not args.without_ad_id) + if args.without_ad_id:assert 'GoogleAppMeasurementIdentitySupport.xcframework' not in '\n'.join(assets) + if first:simulator=(app,bundle) + first=False + assert snapshot(work/'nuget')==restored_packages,'Consumer modified restored package bytes' + assert not (work/'pod-invoked').exists(),'Consumer invoked CocoaPods' + if args.platform=='maccatalyst': + (results/(label+'-catalyst-result.json')).write_text(json.dumps({'success':True,'workspace':str(work),'platform':'maccatalyst'},indent=2)) + print('PASS Mac Catalyst direct/transitive offline builds',flush=True) + return + app,bundle=simulator + for lib in sorted(app.rglob('*.dylib')):subprocess.run(['codesign','--force','--sign','-',str(lib)],check=True,capture_output=True) + subprocess.run(['codesign','--force','--deep','--sign','-',str(app)],check=True,capture_output=True) + device=subprocess.check_output([str(ROOT/'tools/e2e/select-simulator.sh')],text=True).strip() + subprocess.run(['xcrun','simctl','boot',device],capture_output=True) + subprocess.run(['xcrun','simctl','bootstatus',device,'-b'],check=True,stdout=subprocess.DEVNULL) + subprocess.run(['xcrun','simctl','install',device,str(app)],check=True) + subprocess.run(['xcrun','simctl','launch',device,bundle],check=True) + container=Path(subprocess.check_output(['xcrun','simctl','get_app_container',device,bundle,'data']).decode().strip()) + result=container/'Documents/firebase13-result.txt' + for _ in range(30): + if result.exists():break + time.sleep(1) + text=result.read_text() if result.exists() else 'timeout' + assert text.startswith('PASS Firebase 13.'),text + (results/(label+'-result.json')).write_text(json.dumps({'success':True,'runtime':text,'workspace':str(work),'sourceCommit':subprocess.check_output(['git','rev-parse','HEAD'],cwd=ROOT).decode().strip(),'scope':args.scope,'quick':args.quick},indent=2)) + print(text,flush=True) + + +if __name__=='__main__':main() diff --git a/tools/firebase13/generate.py b/tools/firebase13/generate.py new file mode 100644 index 00000000..2e7edee5 --- /dev/null +++ b/tools/firebase13/generate.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +"""Generate deterministic MSBuild delivery targets from the Firebase ownership manifest.""" +import json +from pathlib import Path +import xml.etree.ElementTree as ET + +ROOT = Path(__file__).resolve().parents[2] +MANIFEST = ROOT / 'source/Firebase/native-assets.json' +ACTIVE = "'$(IsBindingProject)' != 'true' And '$(DesignTimeBuild)' != 'true' And '$(IsCrossTargetingBuild)' != 'true' And ('$(TargetPlatformIdentifier)' == 'ios' Or '$(TargetPlatformIdentifier)' == 'maccatalyst') And ('$(OutputType)' != 'Library' Or '$(IsAppExtension)' == 'True')" + + +def xml(root): + ET.indent(root, space=' ') + return ET.tostring(root, encoding='unicode') + '\n' + + +def generate(manifest): + source = manifest['source'] + common = ET.Element('Project') + props = ET.SubElement(common, 'PropertyGroup') + ET.SubElement(props, '_FirebaseNativeSourceId', Condition="'$(_FirebaseNativeSourceId)' == ''").text = source['id'] + ET.SubElement(props, '_FirebaseNativeRoot').text = '$(XamarinBuildDownloadDir)' + source['id'] + '/' + ET.SubElement(props, '_FirebaseNativeCleanup').text = ('Remove ' + source['id'] + ', ' + source['id'] + '.unpacked, and any ' + source['id'] + '.zip from $(XamarinBuildDownloadDir), then rebuild online.') + group = ET.SubElement(common, 'ItemGroup', Condition=ACTIVE) + item = ET.SubElement(group, 'XamarinBuildDownload', Include=source['id'], Exclude='@(XamarinBuildDownload)') + for key, value in [('Url', source['url']), ('Kind', source['kind']), ('Sha256', source['sha256']), ('ExclusiveLockTimeout', str(source['lockTimeout']))]: + ET.SubElement(item, key).text = value + check = ET.SubElement(common, 'Target', Name='_FirebaseNativeSourceCheck_' + source['id'].replace('.', '_').replace('-', '_'), + BeforeTargets='_XamarinBuildDownload;_BeforeCoreCompileInterfaceDefinitions', Condition=ACTIVE) + ET.SubElement(check, 'Error', Condition="'$(_FirebaseNativeSourceId)' != '" + source['id'] + "'", + Text='Conflicting Firebase binary archive versions. Align Firebase and shared dependency package versions.') + outputs = {'Firebase.Native.Common.targets': xml(common)} + for package in manifest['packages']: + key = package['package'].replace('.', '_') + root = ET.Element('Project') + ET.SubElement(root, 'Import', Project='$(MSBuildThisFileDirectory)Firebase.Native.Common.targets') + target = ET.SubElement(root, 'Target', Name='_FirebaseNative_' + key, + BeforeTargets='_BeforeCoreCompileInterfaceDefinitions', + DependsOnTargets='_XamarinBuildDownload', Condition=ACTIVE) + for asset in package['assets']: + ET.SubElement(target, 'Error', Condition=(asset.get('condition') + ' And ' if asset.get('condition') else '') + "!Exists('$(_FirebaseNativeRoot)" + asset['path'] + "')", + Text='Missing Firebase native asset ' + asset['id'] + '. $(_FirebaseNativeCleanup)') + group = ET.SubElement(target, 'ItemGroup') + for asset in package['assets']: + kwargs = {'Include': '$(_FirebaseNativeRoot)' + asset['path']} + if asset.get('condition'): + kwargs['Condition'] = asset['condition'] + if asset['kind'] == 'XCFramework': + item = ET.SubElement(group, 'NativeReference', **kwargs) + for name, value in asset['metadata'].items(): + ET.SubElement(item, name).text = value + elif asset['kind'] == 'Bundle': + kwargs['Include'] += '/**/*' + item_name = '_FirebaseBundle_' + ''.join(c if c.isalnum() else '_' for c in asset['id']) + ET.SubElement(group, item_name, **kwargs) + resources = ET.SubElement(target, 'ItemGroup') + item = ET.SubElement(resources, 'BundleResource', Include='@(' + item_name + ')') + ET.SubElement(item, 'LogicalName').text = asset['logical'] + '/%(' + item_name + '.RecursiveDir)%(' + item_name + '.Filename)%(' + item_name + '.Extension)' + if package['id'] == 'Firebase.Crashlytics': + ET.SubElement(root, 'Import', Project='$(MSBuildThisFileDirectory)Firebase.Crashlytics.Upload.targets') + outputs[package['package'] + '.targets'] = xml(root) + return outputs + + +if __name__ == '__main__': + import argparse + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--check', action='store_true') + args = parser.parse_args() + for name, content in generate(json.loads(MANIFEST.read_text())).items(): + path = ROOT / 'source/Firebase/native' / name + if args.check: + if not path.exists() or path.read_text() != content: + raise SystemExit('Stale generated target: ' + str(path)) + else: + path.write_text(content) diff --git a/tools/firebase13/native.py b/tools/firebase13/native.py new file mode 100644 index 00000000..b6c745e4 --- /dev/null +++ b/tools/firebase13/native.py @@ -0,0 +1,262 @@ +#!/usr/bin/env python3 +"""Validate Firebase official archives and build managed-only, XBD-delivered packages. + +No consumer downloader is implemented here. Acquisition uses stock Xamarin.Build.Download. +""" +import argparse +from datetime import datetime, timezone +import hashlib +import json +import os +from pathlib import Path, PurePosixPath +import plistlib +import re +import subprocess +import zipfile +import xml.etree.ElementTree as ET +from generate import ROOT, MANIFEST, generate + + +def require(ok, message): + if not ok: + raise ValueError(message) + + +def digest(path): + h = hashlib.sha256() + with open(path, 'rb') as f: + for block in iter(lambda: f.read(1024 * 1024), b''): + h.update(block) + return h.hexdigest() + + +def validate_cake_graph(m, text): + symbols={symbol:identity for symbol,identity in re.findall(r'Artifact\s+(\w+)\s*=\s*new Artifact\s*\("([^"]+)"',text)} + declared={} + for symbol,expression in re.findall(r'(\w+)\.Dependencies\s*=\s*([^;]+);',text): + if symbol not in symbols: continue + refs=[] if expression.strip()=='null' else re.findall(r'\b\w+_ARTIFACT\b',expression) + require(expression.strip()=='null' or expression.strip().startswith('new [] {'), 'Unrecognized Cake dependency declaration') + require(len(refs)==len(set(refs)), 'Duplicate Cake dependency') + declared[symbols[symbol]]={symbols[r] for r in refs} + bypackage={p['package']:p['id'] for p in m['packages']} + for package in m['packages']: + require(package['id'] in declared and declared[package['id']]=={bypackage[d] for d in package['dependencies']}, 'Cake dependency graph differs from ownership manifest: '+package['id']) + + +def validate_schema(m): + require(m['schema'] == 1 and m['publicationEnabled'] is False, 'Experimental publication must remain disabled') + s = m['source'] + require(re.fullmatch(r'13\.\d+\.\d+', s['version']) and m['releaseVersion']==s['version'], 'Only pinned Firebase13 release versions are accepted') + require(s['url'] == f"https://github.com/firebase/firebase-ios-sdk/releases/download/{s['version']}/Firebase.zip", 'Unapproved/mutable source URL') + require(re.fullmatch(r'[a-f0-9]{64}', s['sha256']) and s['kind'] == 'Zip', 'Invalid source digest/kind') + require(s['id'] == 'FirebaseiOSSDK-' + s['version'] and s['extractionRoot'] == 'Firebase' and s['lockTimeout'] > 0, 'Invalid shared cache declaration') + ids, ownership, destinations = set(), set(), set() + packages = {p['package']: p for p in m['packages']} + require(len(packages) == len(m['packages']) == 23, 'Unexpected Firebase package closure') + for p in m['packages']: + require(len(p['dependencies']) == len(set(p['dependencies'])), 'Duplicate manifest dependency') + require(all(n in packages for n in p['dependencies']), 'Dependency outside Firebase closure') + project = ET.parse(ROOT / p['project']).getroot() + require(project.findtext('PropertyGroup/PackageId') == p['package'], 'Package owner/project mismatch') + require(project.findtext('PropertyGroup/PackageVersion') == p['version'], 'Package version mismatch') + guard=project.find("Target[@Name='_RequireVerifiedFirebase13Producer']") + require(guard is not None and guard.get('BeforeTargets') == 'GenerateNuspec' and guard.get('Condition') == "'$(Firebase13BuildInfoPath)' == ''" and guard.find('Error') is not None, 'Verified producer pack guard required') + require(not list(project.iter('NativeReference')) and not list(project.iter('BundleResource')), 'Producer project embeds native payloads') + xbd = [n for n in project.iter('PackageReference') if n.get('Include') == 'Xamarin.Build.Download'] + require(len(xbd) == 1 and xbd[0].get('Version') == '[0.11.6]' and xbd[0].get('PrivateAssets') == 'None', 'Exact public XBD dependency required') + references=list(project.iter('ProjectReference')) + require(len(references)==len({n.get('Include') for n in references}), 'Duplicate project reference') + require(any(n.get('Project','').endswith('Firebase.Native.Pack.targets') for n in project.iter('Import')), 'Exact dependency pack targets required') + refs = {str((ROOT / p['project']).parent.joinpath(n.get('Include').replace('\\', '/')).resolve()) for n in project.iter('ProjectReference')} + require(len(refs)==len(references), 'Duplicate resolved project reference') + require(refs == {str((ROOT / packages[n]['project']).resolve()) for n in p['dependencies']}, 'Dependency consumption differs from ownership manifest') + for a in p['assets']: + require(a['id'] not in ids, 'Duplicate asset ID'); ids.add(a['id']) + path = PurePosixPath(a['path']) + require(not path.is_absolute() and a['path'].startswith('Firebase/') and not any(x in ('', '.', '..') for x in a['path'].split('/')) and '\\' not in a['path'] and ':' not in a['path'], 'Unsafe asset path') + require(a['owner'] == p['id'] and a['kind'] in ('XCFramework', 'Bundle', 'Tool'), 'Invalid asset owner/kind') + if a['kind'] == 'XCFramework': + require(path.name not in ownership, 'Duplicate framework ownership'); ownership.add(path.name) + if a['kind'] == 'Bundle': + key = (a['logical'], a.get('condition')) + require(key not in destinations, 'Duplicate logical bundle'); destinations.add(key) + validate_cake_graph(m,(ROOT/'components.cake').read_text()) + for name, content in generate(m).items(): + require((ROOT / 'source/Firebase/native' / name).read_text() == content, 'Stale generated target: ' + name) + acquisition=ET.parse(ROOT/'tools/firebase13/acquire.proj').find('.//XamarinBuildDownload') + require(acquisition.get('Include') == s['id'] and acquisition.findtext('Url') == s['url'] and acquisition.findtext('Kind') == s['kind'] and acquisition.findtext('Sha256') == s['sha256'] and acquisition.findtext('ExclusiveLockTimeout') == str(s['lockTimeout']), 'Producer/consumer XBD declarations differ') + return packages + + +def archive_validate(m, archive): + require(digest(archive) == m['source']['sha256'], 'Archive SHA-256 mismatch') + # Reuse the reviewed archive preflight, never consumer-time custom extraction. + from archive_safety import preflight + preflight(archive) + with zipfile.ZipFile(archive) as z: + names = z.namelist() + require(z.read('Firebase/NOTICES') == (ROOT/'source/Firebase/native/UPSTREAM-NOTICES.txt').read_bytes(), 'Upstream notices differ from archive') + tagged=(ROOT/'tests/fixtures/firebase13'/m['releaseVersion']/'Package.swift').read_text() + require('let firebaseVersion = "'+m['releaseVersion']+'"' in tagged, 'Tagged Package.swift version mismatch') + require(z.read('Firebase/METADATA.md') == (ROOT / 'tests/fixtures/firebase13' / m['releaseVersion'] / 'METADATA.md').read_bytes(), 'METADATA differs from committed fixture') + for p in m['packages']: + for a in p['assets']: + require(a['path'] in names or any(n.startswith(a['path'] + '/') for n in names), 'Missing payload: ' + a['id']) + if a['kind'] == 'Tool': + require(hashlib.sha256(z.read(a['path'])).hexdigest() == a['sha256'], 'Tool digest mismatch') + if a['kind'] == 'Bundle': + prefix = a['path'].split('.xcframework/')[0] + '.xcframework/' + copies = sorted({n[:n.index('.bundle/')+7] for n in names if n.startswith(prefix) and '/' + a['logical'] + '/' in n}) + def resources(bundle): + start = bundle + '/' + result={} + for n in names: + if not n.startswith(start) or n.endswith('/'): + continue + relative=n[len(start):] + if relative in ('Info.plist','Contents/Info.plist'): + continue + relative=relative.removeprefix('Contents/Resources/') + result[relative]=hashlib.sha256(z.read(n)).hexdigest() + return result + # Bundle Info.plist contains SDK-specific build metadata; use each actual slice. + for copy in copies: + if any(slice in copy for slice in ('/ios-arm64/', '/ios-arm64_x86_64-simulator/', '/ios-arm64_x86_64-maccatalyst/')): + require(a['logical'] == 'InAppMessagingDisplayResources.bundle' or resources(copy) == resources(a['path']), 'Resource payload differs across supported slices: ' + copy) + if a['kind'] != 'XCFramework': + continue + info = plistlib.loads(z.read(a['path'] + '/Info.plist')) + libs = info['AvailableLibraries'] + slices = {(x['SupportedPlatform'], x.get('SupportedPlatformVariant', '')):set(x['SupportedArchitectures']) for x in libs} + expected = {('ios',''):{'arm64'}, ('ios','simulator'):{'arm64','x86_64'}, ('ios','maccatalyst'):{'arm64','x86_64'}} + if p['id'] == 'Google.AppMeasurement' and a['path'].endswith('GoogleAdsOnDeviceConversion.xcframework'): + expected.pop(('ios','maccatalyst')) + require(all(slices.get(k) == v for k,v in expected.items()), 'Missing/unexpected supported slices: ' + a['id']) + for lib in libs: + if (lib['SupportedPlatform'], lib.get('SupportedPlatformVariant','')) not in expected: + continue + prefix=a['path']+'/'+lib['LibraryIdentifier']+'/'+lib['LibraryPath'] + paths=[prefix+'/Info.plist',prefix+'/Versions/A/Resources/Info.plist'] + actual=None + for path in paths: + if path in names: + try: actual=plistlib.loads(z.read(path)).get('CFBundleShortVersionString') + except plistlib.InvalidFileException: continue + if actual: break + require(actual == a['binaryVersion'], 'Unexpected binary version: '+prefix) + # Compare complete product copies except their detached XCFramework signatures. + # Google signs identical payloads separately; the full archive digest pins signatures too. + basename = PurePosixPath(a['path']).name + copies = sorted({n.split(basename + '/',1)[0] + basename for n in names if '/' + basename + '/' in n}) + def fingerprints(prefix): + start = prefix + '/' + return {n[len(start):]: hashlib.sha256(z.read(n)).hexdigest() for n in names if n.startswith(start) and not n.endswith('/') and not n[len(start):].startswith('_CodeSignature/')} + canonical = fingerprints(a['path']) + for copy in copies: + require(fingerprints(copy) == canonical, 'Conflicting framework product copies: ' + copy) + supported = {PurePosixPath(a['path']).name for p in m['packages'] for a in p['assets'] if a['kind'] == 'XCFramework'} + metadata = z.read('Firebase/METADATA.md').decode() + sections = re.split(r'^## ', metadata, flags=re.M) + for section in sections: + product = section.splitlines()[0] if section.splitlines() else '' + if product.split(' ')[0] not in {PurePosixPath(a['path']).stem for p in m['packages'] for a in p['assets'] if a['kind']=='XCFramework' and a['path'].split('/')[1].startswith('Firebase')}: + continue + require(set(re.findall(r'^- (\S+\.xcframework)$', section, re.M)) <= supported, 'Unowned framework in supported product: ' + product) + print('PASS official archive: digest, paths/links, metadata, slices, ownership, duplicate frameworks and tools') + + +def inspect_package(path, p): + with zipfile.ZipFile(path) as z: + names = z.namelist() + require(not any('.xcframework' in n or '.framework' in n or '.bundle' in n or n.endswith(('.resources.zip','.a','.dylib')) or '.resources/' in n or PurePosixPath(n).name in ('run','upload-symbols','Podfile') or '.podspec' in n for n in names), 'Native/CocoaPods payload in NuGet: ' + p['package']) + nuspec = ET.fromstring(z.read(next(n for n in names if n.endswith('.nuspec')))) + def value(tag): + return next(n.text for n in nuspec.iter() if n.tag.split('}')[-1] == tag) + def version(v): + parts=v.split('.') + while len(parts)>3 and parts[-1]=='0':parts.pop() + return '.'.join(parts) + require(value('id') == p['package'] and version(value('version')) == version(p['version']), 'NuGet identity/version mismatch') + assembly=ET.parse(ROOT/p['project']).findtext('PropertyGroup/AssemblyName')+'.dll' + for platform in ('ios','maccatalyst'): + require(any(n.startswith('lib/net10.0-'+platform) and n.endswith('/'+assembly) for n in names), 'Missing managed platform assembly') + deps = [n for n in nuspec.iter() if n.tag.split('}')[-1]=='dependency'] + require({n.get('id') for n in deps} == set(p['dependencies']) | {'Xamarin.Build.Download'}, 'Unexpected package dependency closure') + versions={n['package']:version(n['version']) for n in json.loads(MANIFEST.read_text())['packages']} + require(all(n.get('version')=='['+versions[n.get('id')]+']' for n in deps if n.get('id')!='Xamarin.Build.Download'), 'Native dependency must have an exact bounded version') + for group in (n for n in nuspec.iter() if n.tag.split('}')[-1]=='group'): + declared=[n.get('id') for n in group if n.tag.split('}')[-1]=='dependency'] + require(len(declared)==len(set(declared)) and set(declared)==set(p['dependencies'])|{'Xamarin.Build.Download'}, 'Missing/duplicate dependency in target framework group') + require(z.read('UPSTREAM-NOTICES.txt') == (ROOT/'source/Firebase/native/UPSTREAM-NOTICES.txt').read_bytes(), 'Missing/upstream notices differ') + xbd = [n for n in deps if n.get('id')=='Xamarin.Build.Download'] + require(xbd and all(n.get('version')=='[0.11.6]' for n in xbd), 'Missing exact XBD dependency in NuGet') + for folder in ('build','buildTransitive'): + require(z.read(folder+'/Firebase.Native.Common.targets').decode() == generate(json.loads(MANIFEST.read_text()))['Firebase.Native.Common.targets'], 'Inconsistent common XBD declaration') + name=folder+'/'+p['package']+'.targets' + require(z.read(name).decode()==generate(json.loads(MANIFEST.read_text()))[p['package']+'.targets'], 'Missing/stale delivery target') + require(z.read('build/'+p['package']+'.targets')==z.read('buildTransitive/'+p['package']+'.targets'), 'Inconsistent transitive targets') + print('PASS managed-only package:', path.name) + + +def order(packages, names): + byid={p['id']:p for p in packages.values()} + selected=list(byid) if not names else names.replace('Google.GoogleAppMeasurement','Google.AppMeasurement').split(',') + require(all(n in byid for n in selected), 'Only Firebase and its declared native dependencies are supported here') + done, visiting, result=set(),set(),[] + def visit(key): + if key in done:return + require(key not in visiting, 'Dependency cycle');visiting.add(key) + p=byid[key] + for dep in p['dependencies']:visit(packages[dep]['id']) + visiting.remove(key);done.add(key);result.append(p) + for key in selected:visit(key) + return result + + +def main(): + parser=argparse.ArgumentParser(description=__doc__) + parser.add_argument('command', choices=['native-assets-validate','archive-validate','release-check','externals','nuget','libs','packages-validate']) + parser.add_argument('--names', default='') + parser.add_argument('--archive', type=Path) + parser.add_argument('--cache', type=Path) + args=parser.parse_args() + m=json.loads(MANIFEST.read_text());packages=validate_schema(m) + selected=order(packages,args.names) + cache=(args.cache or Path(os.environ.get('XamarinBuildDownloadDir',str(Path.home()/'Library/Caches/XamarinBuildDownload')))).resolve() + if args.command in ('externals','nuget','libs','release-check'): + subprocess.run(['dotnet','restore','tools/firebase13/acquire.proj'],cwd=ROOT,check=True) + subprocess.run(['dotnet','msbuild','tools/firebase13/acquire.proj','-t:Acquire','-p:XamarinBuildDownloadDir='+str(cache)],cwd=ROOT,check=True) + if args.archive:archive_validate(m,args.archive) + if args.command=='archive-validate':require(args.archive is not None,'--archive is required') + if args.command=='release-check': + archive=args.archive or cache/(m['source']['id']+'.zip') + require(archive.exists(),'Release validation requires --archive when XBD no longer retains the pinned ZIP') + if not args.archive:archive_validate(m,archive) + if args.command in ('nuget','libs'): + # Strict producer verification uses the complete official archive before packing. + archive=args.archive or cache/(m['source']['id']+'.zip') + require(archive.exists(),'Producer validation requires --archive with the pinned official ZIP; warm XBD caches may discard it') + if not args.archive:archive_validate(m,archive) + output=ROOT/'output/firebase13';output.mkdir(parents=True,exist_ok=True) + commit=subprocess.check_output(['git','rev-parse','HEAD'],cwd=ROOT).decode().strip() + info=ROOT/'output/firebase13-build-info.cs' + info.write_text((ROOT/'source/AssemblyInfo.cs').read_text().replace('{BUILD_COMMIT}',commit).replace('{BUILD_NUMBER}',os.environ.get('GITHUB_RUN_NUMBER','LOCAL')).replace('{BUILD_TIMESTAMP}',datetime.now(timezone.utc).isoformat())) + for p in selected: + command=['dotnet',('pack' if args.command=='nuget' else 'build'),str(ROOT/p['project']),'-c','Release'] + if args.command=='nuget':command+=['-o',str(output)] + command+=['-p:UseSharedCompilation=false','-p:RepositoryCommit='+commit,'-p:Firebase13BuildInfoPath='+str(info)] + subprocess.run(command,cwd=ROOT,check=True) + path=output/(p['package']+'.'+p['version'].removesuffix('.0')+'.nupkg') + if args.command=='nuget':inspect_package(path,p) + elif args.command=='packages-validate': + if not args.names: + expected={p['package']+'.'+p['version'].removesuffix('.0')+'.nupkg' for p in selected} + require({p.name for p in (ROOT/'output/firebase13').glob('*.nupkg')} == expected, 'Missing/extra packages in Firebase output') + for p in selected: + inspect_package(ROOT/'output/firebase13'/(p['package']+'.'+p['version'].removesuffix('.0')+'.nupkg'),p) + print('PASS',args.command,':',len(selected),'packages; publishing disabled') + + +if __name__=='__main__': + main() diff --git a/tools/legacy/producer.py b/tools/legacy/producer.py new file mode 100644 index 00000000..d8a875e9 --- /dev/null +++ b/tools/legacy/producer.py @@ -0,0 +1,240 @@ +#!/usr/bin/env python3 +"""Produce non-Firebase packages with the pinned, isolated pre-migration inputs. + +This obtains this repository's historical source, not native SDK binaries. Existing +CocoaPods production runs only in the legacy workspace; Firebase 13 never falls back. +""" +import argparse +from contextlib import contextmanager +import json +import os +import re +from pathlib import Path, PurePosixPath +import shutil +import subprocess +import tarfile +import tempfile +import xml.etree.ElementTree as ET + +ROOT=Path(__file__).resolve().parents[2] +LOCK='eng/legacy-producer.json' +PRODUCTION={'externals','libs','nuget','build','ci'} + + +def run(args, root=ROOT, **kwargs): + return subprocess.run(args,cwd=root,check=True,**kwargs) + + +def lock(root=ROOT): + data=json.loads((root/LOCK).read_text()) + if data['schema']!=1 or not re.fullmatch('[a-f0-9]{40}',data['commit']) or not re.fullmatch('[a-f0-9]{40}',data['tree']): + raise ValueError('Invalid legacy producer lock') + keys=[p['key'] for p in data['artifacts']] + for field in ('key','artifactId','id','project'): + values=[p[field] for p in data['artifacts']] + if len(values)!=len(set(values)):raise ValueError('Duplicate locked legacy artifact '+field) + if any(not set(p['dependencies'])<=set(keys) for p in data['artifacts']):raise ValueError('Unknown locked legacy dependency') + return data + + +def ensure_commit(root, data): + check=subprocess.run(['git','cat-file','-e',data['commit']+'^{commit}'],cwd=root,capture_output=True) + if check.returncode: + # Shallow CI checkouts may omit this reviewed ancestor. Fetch only its pinned object. + run(['git','fetch','--no-tags','origin',data['commit']],root) + tree=subprocess.check_output(['git','rev-parse',data['commit']+'^{tree}'],cwd=root,text=True).strip() + if tree!=data['tree']:raise ValueError('Legacy baseline tree differs from its lock') + + +def closure(data, names): + bykey={p['key']:p for p in data['artifacts']};result=[];visiting=set();done=set() + def visit(key): + if key not in bykey:raise ValueError('Unknown legacy artifact: '+key) + if key in visiting:raise ValueError('Legacy dependency cycle: '+key) + if key in done:return + visiting.add(key) + for dep in bykey[key]['dependencies']:visit(dep) + visiting.remove(key);done.add(key);result.append(bykey[key]) + for name in names:visit(name) + return result + + +def plan(data, manifest, names, mode='auto'): + registered={p['key'] for p in data['artifacts']} + selected=names.split(',') if names else [p['key'] for p in data['artifacts']] + if not set(selected)<=registered:raise ValueError('Unknown component selection') + migrated_ids={p['id'] for p in manifest['packages']} + migrated={p['key'] for p in data['artifacts'] if p['artifactId'] in migrated_ids} + legacy=selected if mode=='legacy' else [n for n in selected if n not in migrated] + modern=[] if mode=='legacy' else [n for n in selected if n in migrated] + return {'legacy':legacy,'firebase13':modern,'legacyPackages':closure(data,legacy)} + + +@contextmanager +def source_tree(root=ROOT): + """Fresh immutable inputs for fingerprints; build workspaces are separate copies.""" + root=root.resolve() + data=lock(root);ensure_commit(root,data) + directory=root/'output/legacy-sources';directory.mkdir(parents=True,exist_ok=True) + with tempfile.TemporaryDirectory(prefix='source-',dir=directory) as tmp: + stage=Path(tmp).resolve() + archive=stage/'source.tar' + run(['git','archive','--format=tar','--output='+str(archive),data['commit']],root) + with tarfile.open(archive) as tar: + for item in tar: + path=PurePosixPath(item.name) + if path.is_absolute() or '..' in path.parts or item.isdev() or item.islnk(): + raise ValueError('Unsafe path in legacy source archive') + if item.issym(): + target=PurePosixPath(item.linkname) + resolved=os.path.normpath(str(path.parent/target)) + if target.is_absolute() or resolved.startswith('../'):raise ValueError('Escaping legacy source link') + tar.extractall(stage) + archive.unlink() + yield stage + + +def matches_metadata(metadata, root=ROOT): + if not (root/LOCK).exists() or not metadata:return False + versions={p['id']:p['version'] for p in lock(root)['artifacts']} + def norm(v):return tuple(int(n) for n in v.split('.'))+(0,)*(4-len(v.split('.'))) + return all(p['id'] in versions and norm(p['version'])==norm(versions[p['id']]) for p in metadata) + + +def verify_nonfirebase_inputs(root, stage, data, manifest): + """Never silently ignore a later product edit while using a frozen baseline.""" + root=root.resolve();stage=stage.resolve() + migrated_ids={p['id'] for p in manifest['packages']} + migrated={p['key'] for p in data['artifacts'] if p['artifactId'] in migrated_ids} + tracked=set(subprocess.check_output(['git','ls-files'],cwd=root,text=True).splitlines()) + for p in data['artifacts']: + if p['key'] in migrated:continue + prefix=str(Path(p['project']).parent)+'/' + for name in tracked: + if name.startswith(prefix): + if not (stage/name).is_file() or (root/name).read_bytes()!=(stage/name).read_bytes(): + raise ValueError('Non-Firebase product changed; review/update its legacy baseline before production: '+name) + # Include packed readmes/icons and global build inputs, not just files beside the project. + shared=['Directory.Build.props','global.json','.config/dotnet-tools.json','source/AssemblyInfo.cs','common.cake','poco.cake','custom_externals_download.cake'] + for artifact in data['artifacts']: + if artifact['key'] in migrated:continue + project=stage/artifact['project'] + for node in ET.parse(project).iter(): + include=(node.get('Include') or '').replace('\\','/') + if node.get('Pack','').lower()=='true' and '$(' not in include and '*' not in include: + source=(project.parent/include).resolve() + if source.is_relative_to(stage) and source.is_file():shared.append(str(source.relative_to(stage))) + for name in set(shared): + if not (root/name).is_file() or (root/name).read_bytes()!=(stage/name).read_bytes(): + raise ValueError('Legacy producer input changed; review/update its baseline: '+name) + prefixes=[str(Path(p['project']).parent)+'/' for p in data['artifacts'] if p['key'] not in migrated] + untracked=subprocess.check_output(['git','ls-files','--others','--exclude-standard'],cwd=root,text=True).splitlines() + if any(any(name.startswith(prefix) for prefix in prefixes) for name in untracked): + raise ValueError('Untracked non-Firebase source would be ignored by the legacy baseline; review it before production') + # Metadata-only identities, pins and graph are also compared by the existing AST normalizer. + selected=root/'output/legacy-selected.json';output=root/'output/legacy-components.json' + selected.write_text(json.dumps([p['artifactId'] for p in data['artifacts'] if p['key'] not in migrated])) + results=[] + for source in (root,stage): + run(['dotnet','run','--project',str(root/'scripts/FirebaseReleaseFingerprint'),'--',str(source),str(selected),str(output),'--components-only'],root, + env={**os.environ,'MSBuildEnableWorkloadResolver':'false'}) + results.append(output.read_bytes()) + if results[0]!=results[1]:raise ValueError('Non-Firebase Cake declarations changed; review/update the locked producer baseline') + + +def cake(stage, target, names='', output=None, channel=None): + args=['dotnet','tool','run','dotnet-cake','--'] + if channel=='signin':args+=['signin_publish.cake'] + else:args+=['--target='+('firebase-publish-metadata' if channel=='firebase' else ('nuget' if target=='build' else target))] + if names:args+=['--names='+names] + if output:args+=['--metadata-output='+str(output)] + run(args,stage) + + +def copy_outputs(root, stage, selected, require_packages=False): + allowed={p['id']:p['version'] for p in selected} + output=root/'output';output.mkdir(exist_ok=True) + import zipfile + seen=set() + for package in (stage/'output').glob('*.nupkg'): + with zipfile.ZipFile(package) as z: + spec=ET.fromstring(z.read(next(n for n in z.namelist() if n.endswith('.nuspec')))) + values={n.tag.split('}')[-1]:n.text for n in spec.iter()} + if values['id'] not in allowed:raise ValueError('Unexpected legacy output: '+values['id']) + if values['id'] in seen:raise ValueError('Duplicate legacy output identity') + seen.add(values['id']) + expected=allowed[values['id']].split('.') + while len(expected)>3 and expected[-1]=='0':expected.pop() + actual=values['version'].split('.') + while len(actual)>3 and actual[-1]=='0':actual.pop() + if actual!=expected:raise ValueError('Legacy package version changed: '+values['id']) + shutil.copy2(package,output/package.name) + if require_packages and seen!=set(allowed):raise ValueError('Missing legacy output packages') + # Keep the established resolution-evidence path used by Sign-In validation. + for artifact in selected: + source=stage/'externals/build'/artifact['key'] + for name in ('Podfile','Podfile.lock'): + if (source/name).exists(): + destination=root/'externals/build'/artifact['key'];destination.mkdir(parents=True,exist_ok=True) + shutil.copy2(source/name,destination/name) + + +def copy_product_externals(root, stage, selected, manifest): + migrated={p['id'] for p in manifest['packages']} + assets=set() + for artifact in selected: + if artifact['artifactId'] in migrated:continue + for node in ET.parse(stage/artifact['project']).iter(): + include=(node.get('Include') or '').replace('\\','/') + if '/externals/' in include: + name=include.split('/externals/',1)[1].split('/',1)[0] + if name and '*' not in name and name not in ('.','..'):assets.add(name) + for name in assets: + source=stage/'externals'/name;target=root/'externals'/name + if not source.exists():continue + if target.is_symlink():target.unlink() + elif target.is_dir():shutil.rmtree(target) + elif target.exists():target.unlink() + target.parent.mkdir(parents=True,exist_ok=True) + if source.is_dir():shutil.copytree(source,target,symlinks=True) + else:shutil.copy2(source,target) + + +def main(): + parser=argparse.ArgumentParser(description=__doc__) + parser.add_argument('command',choices=['build','metadata','plan']) + parser.add_argument('--target',choices=sorted(PRODUCTION),default='nuget') + parser.add_argument('--names',default='') + parser.add_argument('--mode',choices=['auto','legacy'],default='auto') + parser.add_argument('--channel',choices=['signin','firebase'],default='signin') + parser.add_argument('--output',type=Path) + parser.add_argument('--archive');parser.add_argument('--cache') + args=parser.parse_args();data=lock();manifest=json.loads((ROOT/'source/Firebase/native-assets.json').read_text()) + selection=plan(data,manifest,args.names,args.mode) + if args.command=='plan':print(json.dumps(selection,indent=2));return + if args.command=='metadata' or selection['legacy']: + with source_tree() as source: + verify_nonfirebase_inputs(ROOT,source,data,manifest) + if args.command=='metadata': + destination=(args.output or ROOT/('output/'+args.channel+'-metadata.json')).resolve();destination.parent.mkdir(parents=True,exist_ok=True) + cake(source,'',output=destination,channel=args.channel);return + # Build mutations, Pods and externals stay inside this private workspace. + stage=Path(tempfile.mkdtemp(prefix='build-',dir=ROOT/'output/legacy-sources')) + shutil.copytree(source,stage,dirs_exist_ok=True,symlinks=True) + if 'Google.SignIn' in selection['legacy']: + expected=json.loads((stage/'eng/signin-release.json').read_text())['nativeBuild']['cocoapods'] + actual=subprocess.check_output(['pod','--version'],text=True).strip() + if actual!=expected:raise ValueError('Sign-In legacy production requires CocoaPods '+expected+'; found '+actual) + cake(stage,args.target,','.join(selection['legacy'])) + copy_outputs(ROOT,stage,selection['legacyPackages'],args.target in ('nuget','build','ci')) + copy_product_externals(ROOT,stage,selection['legacyPackages'],manifest) + print('Legacy production workspace:',stage) + if selection['firebase13']: + command='externals' if args.target=='externals' else ('libs' if args.target=='libs' else 'nuget') + cmd=['python3','tools/firebase13/native.py',command,'--names',','.join(selection['firebase13'])] + for key in ('archive','cache'): + if getattr(args,key):cmd+=['--'+key,getattr(args,key)] + run(cmd) + + +if __name__=='__main__':main()