diff --git a/.bazelrc b/.bazelrc
index 14da857d8..e8640da8f 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -1,7 +1,7 @@
# To update these lines, execute
# `bazel run @rules_bazel_integration_test//tools:update_deleted_packages`
-build --deleted_packages=bzlmod/workspace,bzlmod/workspace/Sources/MyExecutable,bzlmod/workspace/Sources/MyLibrary,bzlmod/workspace/Tests/MyLibraryTests,examples/firebase_example,examples/firebase_example/abtesting,examples/firebase_example/abtesting/SharedApp,examples/firebase_example/analytics/AnalyticsExample,examples/firebase_example/appdistribution,examples/firebase_example/appdistribution/AppDistributionExample,examples/firebase_example/appdistribution/AppDistributionTests,examples/http_archive_ext_deps,examples/http_archive_ext_deps/Sources/MyDequeModule,examples/http_archive_ext_deps/Sources/PrintStuff,examples/http_archive_ext_deps/Tests/MyDequeModuleTests,examples/http_archive_ext_deps/third_party,examples/interesting_deps,examples/ios_sim,examples/ios_sim/Sources/Foo,examples/ios_sim/Tests/FooTests,examples/ios_sim/third-party/swift-cmark,examples/nimble_example,examples/nimble_example/Sources/NimbleExample,examples/objc_code,examples/phone_number_kit,examples/phone_number_kit/Tests/PhoneNumberKitTests,examples/pkg_manifest_minimal,examples/pkg_manifest_minimal/Sources/MyExecutable,examples/pkg_manifest_minimal/Sources/MyLibrary,examples/pkg_manifest_minimal/Tests/MyLibraryTests,examples/pkg_manifest_minimal/third_party,examples/resources_example,examples/resources_example/Sources/MyApp,examples/resources_example/Tests/MyAppTests,examples/resources_example/third_party,examples/soto_example,examples/soto_example/Tests/SotoTests,examples/tca_example,examples/tca_example/SwiftUICaseStudies,examples/tca_example/SwiftUICaseStudiesTests,examples/vapor_example,examples/vapor_example/Sources/App,examples/vapor_example/Sources/Run,examples/vapor_example/Tests/AppTests,examples/vapor_example/swift,examples/xcmetrics_example
-query --deleted_packages=bzlmod/workspace,bzlmod/workspace/Sources/MyExecutable,bzlmod/workspace/Sources/MyLibrary,bzlmod/workspace/Tests/MyLibraryTests,examples/firebase_example,examples/firebase_example/abtesting,examples/firebase_example/abtesting/SharedApp,examples/firebase_example/analytics/AnalyticsExample,examples/firebase_example/appdistribution,examples/firebase_example/appdistribution/AppDistributionExample,examples/firebase_example/appdistribution/AppDistributionTests,examples/http_archive_ext_deps,examples/http_archive_ext_deps/Sources/MyDequeModule,examples/http_archive_ext_deps/Sources/PrintStuff,examples/http_archive_ext_deps/Tests/MyDequeModuleTests,examples/http_archive_ext_deps/third_party,examples/interesting_deps,examples/ios_sim,examples/ios_sim/Sources/Foo,examples/ios_sim/Tests/FooTests,examples/ios_sim/third-party/swift-cmark,examples/nimble_example,examples/nimble_example/Sources/NimbleExample,examples/objc_code,examples/phone_number_kit,examples/phone_number_kit/Tests/PhoneNumberKitTests,examples/pkg_manifest_minimal,examples/pkg_manifest_minimal/Sources/MyExecutable,examples/pkg_manifest_minimal/Sources/MyLibrary,examples/pkg_manifest_minimal/Tests/MyLibraryTests,examples/pkg_manifest_minimal/third_party,examples/resources_example,examples/resources_example/Sources/MyApp,examples/resources_example/Tests/MyAppTests,examples/resources_example/third_party,examples/soto_example,examples/soto_example/Tests/SotoTests,examples/tca_example,examples/tca_example/SwiftUICaseStudies,examples/tca_example/SwiftUICaseStudiesTests,examples/vapor_example,examples/vapor_example/Sources/App,examples/vapor_example/Sources/Run,examples/vapor_example/Tests/AppTests,examples/vapor_example/swift,examples/xcmetrics_example
+build --deleted_packages=bzlmod/workspace,bzlmod/workspace/Sources/MyExecutable,bzlmod/workspace/Sources/MyLibrary,bzlmod/workspace/Tests/MyLibraryTests,examples/firebase_example,examples/firebase_example/abtesting,examples/firebase_example/abtesting/SharedApp,examples/firebase_example/analytics/AnalyticsExample,examples/firebase_example/appdistribution,examples/firebase_example/appdistribution/AppDistributionExample,examples/firebase_example/appdistribution/AppDistributionTests,examples/firebase_example/crashlytics,examples/http_archive_ext_deps,examples/http_archive_ext_deps/Sources/MyDequeModule,examples/http_archive_ext_deps/Sources/PrintStuff,examples/http_archive_ext_deps/Tests/MyDequeModuleTests,examples/http_archive_ext_deps/third_party,examples/interesting_deps,examples/ios_sim,examples/ios_sim/Sources/Foo,examples/ios_sim/Tests/FooTests,examples/ios_sim/third-party/swift-cmark,examples/nimble_example,examples/nimble_example/Sources/NimbleExample,examples/objc_code,examples/phone_number_kit,examples/phone_number_kit/Tests/PhoneNumberKitTests,examples/pkg_manifest_minimal,examples/pkg_manifest_minimal/Sources/MyExecutable,examples/pkg_manifest_minimal/Sources/MyLibrary,examples/pkg_manifest_minimal/Tests/MyLibraryTests,examples/pkg_manifest_minimal/third_party,examples/resources_example,examples/resources_example/Sources/MyApp,examples/resources_example/Tests/MyAppTests,examples/resources_example/third_party,examples/soto_example,examples/soto_example/Tests/SotoTests,examples/tca_example,examples/tca_example/SwiftUICaseStudies,examples/tca_example/SwiftUICaseStudiesTests,examples/vapor_example,examples/vapor_example/Sources/App,examples/vapor_example/Sources/Run,examples/vapor_example/Tests/AppTests,examples/vapor_example/swift,examples/xcmetrics_example
+query --deleted_packages=bzlmod/workspace,bzlmod/workspace/Sources/MyExecutable,bzlmod/workspace/Sources/MyLibrary,bzlmod/workspace/Tests/MyLibraryTests,examples/firebase_example,examples/firebase_example/abtesting,examples/firebase_example/abtesting/SharedApp,examples/firebase_example/analytics/AnalyticsExample,examples/firebase_example/appdistribution,examples/firebase_example/appdistribution/AppDistributionExample,examples/firebase_example/appdistribution/AppDistributionTests,examples/firebase_example/crashlytics,examples/http_archive_ext_deps,examples/http_archive_ext_deps/Sources/MyDequeModule,examples/http_archive_ext_deps/Sources/PrintStuff,examples/http_archive_ext_deps/Tests/MyDequeModuleTests,examples/http_archive_ext_deps/third_party,examples/interesting_deps,examples/ios_sim,examples/ios_sim/Sources/Foo,examples/ios_sim/Tests/FooTests,examples/ios_sim/third-party/swift-cmark,examples/nimble_example,examples/nimble_example/Sources/NimbleExample,examples/objc_code,examples/phone_number_kit,examples/phone_number_kit/Tests/PhoneNumberKitTests,examples/pkg_manifest_minimal,examples/pkg_manifest_minimal/Sources/MyExecutable,examples/pkg_manifest_minimal/Sources/MyLibrary,examples/pkg_manifest_minimal/Tests/MyLibraryTests,examples/pkg_manifest_minimal/third_party,examples/resources_example,examples/resources_example/Sources/MyApp,examples/resources_example/Tests/MyAppTests,examples/resources_example/third_party,examples/soto_example,examples/soto_example/Tests/SotoTests,examples/tca_example,examples/tca_example/SwiftUICaseStudies,examples/tca_example/SwiftUICaseStudiesTests,examples/vapor_example,examples/vapor_example/Sources/App,examples/vapor_example/Sources/Run,examples/vapor_example/Tests/AppTests,examples/vapor_example/swift,examples/xcmetrics_example
# Import Shared settings
import %workspace%/shared.bazelrc
diff --git a/.github/actions/set_up_macos/action.yml b/.github/actions/set_up_macos/action.yml
index 29a7fac2f..1a2811a76 100644
--- a/.github/actions/set_up_macos/action.yml
+++ b/.github/actions/set_up_macos/action.yml
@@ -7,7 +7,7 @@ inputs:
required: true
xcode_version:
description: The version of Xcode to use.
- default: '14.0.1'
+ default: '14.3.1'
runs:
using: composite
diff --git a/config_settings/spm/platform/platforms.bzl b/config_settings/spm/platform/platforms.bzl
index 51f9768b3..05f6bd8d4 100644
--- a/config_settings/spm/platform/platforms.bzl
+++ b/config_settings/spm/platform/platforms.bzl
@@ -62,8 +62,11 @@ def _label(name):
Returns:
The condition label as a `string`.
"""
+
+ # There is currently no support Mac Catalyst in Bazel. These are Mac apps
+ # that use iOS frameworks. Treat it like iOS for now.
if name == "maccatalyst":
- name = "macos"
+ name = "ios"
return "@rules_swift_package_manager//config_settings/spm/platform:{}".format(name)
platforms = struct(
diff --git a/examples/firebase_example/.bazelrc b/examples/firebase_example/.bazelrc
index 958cc1926..34dd1e78a 100644
--- a/examples/firebase_example/.bazelrc
+++ b/examples/firebase_example/.bazelrc
@@ -7,10 +7,12 @@ import %workspace%/../../ci.bazelrc
# Try to import a local.rc file; typically, written by CI
try-import %workspace%/../../local.bazelrc
-# The CNIOBoringSSL uses C++14 features like 'enable_if_t' macro support.
-# For more details on how to enable this in Bazel:
+# Per https://github.com/firebase/firebase-ios-sdk/blob/master/Package.swift#L1322-L1323
+# NOTE: Puposefully not specifying --copt='-std=c99' as it is applied to
+# objc_library targets that contain Objective-C++ files. Tried using
+# --per_file_copt to exclude .mm files, but did not have success.
# https://stackoverflow.com/questions/40260242/how-to-set-c-standard-version-when-build-with-bazel/43388168#43388168
-build --cxxopt='-std=c++14'
+build --cxxopt='-std=gnu++14'
# Firebase SPM support requires `-ObjC` linker option.
# https://github.com/firebase/firebase-ios-sdk/blob/master/SwiftPackageManager.md#requirements
diff --git a/examples/firebase_example/MODULE.bazel b/examples/firebase_example/MODULE.bazel
index 1d6d27ba4..bebc90b7d 100644
--- a/examples/firebase_example/MODULE.bazel
+++ b/examples/firebase_example/MODULE.bazel
@@ -43,5 +43,6 @@ swift_deps.from_file(
use_repo(
swift_deps,
"swiftpkg_firebase_ios_sdk",
+ "swiftpkg_reachability.swift",
)
# swift_deps END
diff --git a/examples/firebase_example/Package.resolved b/examples/firebase_example/Package.resolved
index 1c10147b7..951b0be0d 100644
--- a/examples/firebase_example/Package.resolved
+++ b/examples/firebase_example/Package.resolved
@@ -1,21 +1,12 @@
{
"pins" : [
{
- "identity" : "abseil-cpp-swiftpm",
+ "identity" : "abseil-cpp-binary",
"kind" : "remoteSourceControl",
- "location" : "https://github.com/firebase/abseil-cpp-SwiftPM.git",
+ "location" : "https://github.com/google/abseil-cpp-binary.git",
"state" : {
- "revision" : "583de9bd60f66b40e78d08599cc92036c2e7e4e1",
- "version" : "0.20220203.2"
- }
- },
- {
- "identity" : "boringssl-swiftpm",
- "kind" : "remoteSourceControl",
- "location" : "https://github.com/firebase/boringssl-SwiftPM.git",
- "state" : {
- "revision" : "dd3eda2b05a3f459fc3073695ad1b28659066eab",
- "version" : "0.9.1"
+ "revision" : "bfc0b6f81adc06ce5121eb23f628473638d67c5c",
+ "version" : "1.2022062300.0"
}
},
{
@@ -23,8 +14,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/firebase/firebase-ios-sdk",
"state" : {
- "revision" : "f567ed9a2b30e29159df258049a9c662c517688e",
- "version" : "10.5.0"
+ "revision" : "e700a8f40c87c31cab7984875fcc1225d96b25bf",
+ "version" : "10.11.0"
}
},
{
@@ -32,8 +23,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/GoogleAppMeasurement.git",
"state" : {
- "revision" : "9a09ece724128e8d1e14c5133b87c0e236844ac0",
- "version" : "10.4.0"
+ "revision" : "62e3a0c09a75e2637f5300d46f05a59313f1c286",
+ "version" : "10.11.0"
}
},
{
@@ -55,12 +46,12 @@
}
},
{
- "identity" : "grpc-ios",
+ "identity" : "grpc-binary",
"kind" : "remoteSourceControl",
- "location" : "https://github.com/grpc/grpc-ios.git",
+ "location" : "https://github.com/google/grpc-binary.git",
"state" : {
- "revision" : "8440b914756e0d26d4f4d054a1c1581daedfc5b6",
- "version" : "1.44.3-grpc"
+ "revision" : "f1b366129d1125be7db83247e003fc333104b569",
+ "version" : "1.50.2"
}
},
{
@@ -68,8 +59,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/google/gtm-session-fetcher.git",
"state" : {
- "revision" : "96d7cc73a71ce950723aa3c50ce4fb275ae180b8",
- "version" : "3.1.0"
+ "revision" : "5ccda3981422a84186387dbb763ba739178b529c",
+ "version" : "2.3.0"
}
},
{
@@ -99,6 +90,15 @@
"version" : "2.1.1"
}
},
+ {
+ "identity" : "reachability.swift",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/ashleymills/Reachability.swift.git",
+ "state" : {
+ "revision" : "c01bbdf2d633cf049ae1ed1a68a2020a8bda32e2",
+ "version" : "5.1.0"
+ }
+ },
{
"identity" : "swift-protobuf",
"kind" : "remoteSourceControl",
diff --git a/examples/firebase_example/Package.swift b/examples/firebase_example/Package.swift
index 21895d17a..d7da49e97 100644
--- a/examples/firebase_example/Package.swift
+++ b/examples/firebase_example/Package.swift
@@ -6,5 +6,7 @@ let package = Package(
name: "firebase_example",
dependencies: [
.package(url: "https://github.com/firebase/firebase-ios-sdk", .upToNextMajor(from: "10.0.0")),
+ // Used by crashlytics example
+ .package(url: "https://github.com/ashleymills/Reachability.swift.git", .upToNextMajor(from: "5.1.0")),
]
)
diff --git a/examples/firebase_example/crashlytics/BUILD.bazel b/examples/firebase_example/crashlytics/BUILD.bazel
new file mode 100644
index 000000000..00159fdaa
--- /dev/null
+++ b/examples/firebase_example/crashlytics/BUILD.bazel
@@ -0,0 +1,62 @@
+load("@bazel_skylib//rules:build_test.bzl", "build_test")
+load("@build_bazel_rules_apple//apple:ios.bzl", "ios_application")
+load("@build_bazel_rules_apple//apple:macos.bzl", "macos_application")
+load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library")
+
+# Exclude this entire directory from having anything generated by Gazelle. That
+# way the test cases won't be fixed by `bazel run //:update_build_files` when
+# run in this repository.
+# gazelle:exclude **
+
+swift_library(
+ name = "CrashlyticsSwiftUIExample",
+ srcs = [
+ "Shared/ContentView.swift",
+ "Shared/CrashlyticsSwiftUIExampleApp.swift",
+ "Shared/ReachabililtyHelper.swift",
+ ],
+ module_name = "CrashlyticsSwiftUIExample",
+ tags = ["manual"],
+ visibility = ["//visibility:public"],
+ deps = [
+ "@swiftpkg_firebase_ios_sdk//:Crashlytics_FirebaseCrashlytics",
+ "@swiftpkg_reachability.swift//:Sources_Reachability",
+ ],
+)
+
+ios_application(
+ name = "iosapp",
+ bundle_id = "com.google.firebase.quickstart.CrashlyticsExample",
+ families = [
+ "iphone",
+ "ipad",
+ ],
+ infoplists = [":iOS/Info.plist"],
+ minimum_os_version = "15.0",
+ resources = glob(
+ ["CrashlyticsSwiftUIExample/Assets.xcassets/**"],
+ exclude = ["CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/**"],
+ ),
+ deps = [":CrashlyticsSwiftUIExample"],
+)
+
+macos_application(
+ name = "macosapp",
+ bundle_id = "com.google.firebase.quickstart.CrashlyticsExample",
+ entitlements = ":macOS/macOS.entitlements",
+ infoplists = [":macOS/Info.plist"],
+ minimum_os_version = "11.0",
+ resources = glob(
+ ["CrashlyticsSwiftUIExample/Assets.xcassets/**"],
+ exclude = ["CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/**"],
+ ),
+ deps = [":CrashlyticsSwiftUIExample"],
+)
+
+build_test(
+ name = "iosapp_build_test",
+ targets = [
+ ":iosapp",
+ ":macosapp",
+ ],
+)
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AccentColor.colorset/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AccentColor.colorset/Contents.json
new file mode 100644
index 000000000..eb8789700
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AccentColor.colorset/Contents.json
@@ -0,0 +1,11 @@
+{
+ "colors" : [
+ {
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
new file mode 100644
index 000000000..795cce172
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
@@ -0,0 +1,16 @@
+{
+ "images" : [
+ {
+ "idiom" : "tv",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "tv",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Back.imagestacklayer/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Back.imagestacklayer/Contents.json
new file mode 100644
index 000000000..73c00596a
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Back.imagestacklayer/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Contents.json
new file mode 100644
index 000000000..de59d885a
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Contents.json
@@ -0,0 +1,17 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "layers" : [
+ {
+ "filename" : "Front.imagestacklayer"
+ },
+ {
+ "filename" : "Middle.imagestacklayer"
+ },
+ {
+ "filename" : "Back.imagestacklayer"
+ }
+ ]
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
new file mode 100644
index 000000000..795cce172
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
@@ -0,0 +1,16 @@
+{
+ "images" : [
+ {
+ "idiom" : "tv",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "tv",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Front.imagestacklayer/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Front.imagestacklayer/Contents.json
new file mode 100644
index 000000000..73c00596a
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Front.imagestacklayer/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
new file mode 100644
index 000000000..795cce172
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
@@ -0,0 +1,16 @@
+{
+ "images" : [
+ {
+ "idiom" : "tv",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "tv",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Middle.imagestacklayer/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Middle.imagestacklayer/Contents.json
new file mode 100644
index 000000000..73c00596a
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIcon.imagestack/Middle.imagestacklayer/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
new file mode 100644
index 000000000..2e003356c
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Back.imagestacklayer/Content.imageset/Contents.json
@@ -0,0 +1,11 @@
+{
+ "images" : [
+ {
+ "idiom" : "tv"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Back.imagestacklayer/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Back.imagestacklayer/Contents.json
new file mode 100644
index 000000000..73c00596a
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Back.imagestacklayer/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Contents.json
new file mode 100644
index 000000000..de59d885a
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Contents.json
@@ -0,0 +1,17 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ },
+ "layers" : [
+ {
+ "filename" : "Front.imagestacklayer"
+ },
+ {
+ "filename" : "Middle.imagestacklayer"
+ },
+ {
+ "filename" : "Back.imagestacklayer"
+ }
+ ]
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
new file mode 100644
index 000000000..2e003356c
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Front.imagestacklayer/Content.imageset/Contents.json
@@ -0,0 +1,11 @@
+{
+ "images" : [
+ {
+ "idiom" : "tv"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Front.imagestacklayer/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Front.imagestacklayer/Contents.json
new file mode 100644
index 000000000..73c00596a
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Front.imagestacklayer/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
new file mode 100644
index 000000000..2e003356c
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json
@@ -0,0 +1,11 @@
+{
+ "images" : [
+ {
+ "idiom" : "tv"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Middle.imagestacklayer/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Middle.imagestacklayer/Contents.json
new file mode 100644
index 000000000..73c00596a
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/AppIconAppStore.imagestack/Middle.imagestacklayer/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/Contents.json
new file mode 100644
index 000000000..cda257258
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/Contents.json
@@ -0,0 +1,32 @@
+{
+ "assets" : [
+ {
+ "filename" : "AppIconAppStore.imagestack",
+ "idiom" : "tv",
+ "role" : "primary-app-icon",
+ "size" : "1280x768"
+ },
+ {
+ "filename" : "AppIcon.imagestack",
+ "idiom" : "tv",
+ "role" : "primary-app-icon",
+ "size" : "400x240"
+ },
+ {
+ "filename" : "TopShelfImageWide.imageset",
+ "idiom" : "tv",
+ "role" : "top-shelf-image-wide",
+ "size" : "2320x720"
+ },
+ {
+ "filename" : "TopShelfImage.imageset",
+ "idiom" : "tv",
+ "role" : "top-shelf-image",
+ "size" : "1920x720"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/TopShelfImage.imageset/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/TopShelfImage.imageset/Contents.json
new file mode 100644
index 000000000..b65f0cddc
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/TopShelfImage.imageset/Contents.json
@@ -0,0 +1,24 @@
+{
+ "images" : [
+ {
+ "idiom" : "tv",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "tv",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "tv-marketing",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "tv-marketing",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/TopShelfImageWide.imageset/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/TopShelfImageWide.imageset/Contents.json
new file mode 100644
index 000000000..b65f0cddc
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/AppIconTopShelfImage.brandassets/TopShelfImageWide.imageset/Contents.json
@@ -0,0 +1,24 @@
+{
+ "images" : [
+ {
+ "idiom" : "tv",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "tv",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "tv-marketing",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "tv-marketing",
+ "scale" : "2x"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/Contents.json
new file mode 100644
index 000000000..73c00596a
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Info.plist b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Info.plist
new file mode 100644
index 000000000..16d307cc9
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/Info.plist
@@ -0,0 +1,32 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UILaunchScreen
+
+ UIRequiredDeviceCapabilities
+
+ arm64
+
+ UIUserInterfaceStyle
+ Automatic
+
+
diff --git a/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/PreviewContent/PreviewAssets.xcassets/Contents.json b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/PreviewContent/PreviewAssets.xcassets/Contents.json
new file mode 100644
index 000000000..73c00596a
--- /dev/null
+++ b/examples/firebase_example/crashlytics/CrashlyticsSwiftUIExample/PreviewContent/PreviewAssets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/Shared/Assets.xcassets/AccentColor.colorset/Contents.json b/examples/firebase_example/crashlytics/Shared/Assets.xcassets/AccentColor.colorset/Contents.json
new file mode 100644
index 000000000..eb8789700
--- /dev/null
+++ b/examples/firebase_example/crashlytics/Shared/Assets.xcassets/AccentColor.colorset/Contents.json
@@ -0,0 +1,11 @@
+{
+ "colors" : [
+ {
+ "idiom" : "universal"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/Shared/Assets.xcassets/AppIcon.appiconset/Contents.json b/examples/firebase_example/crashlytics/Shared/Assets.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 000000000..c136eaff7
--- /dev/null
+++ b/examples/firebase_example/crashlytics/Shared/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,148 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "2x",
+ "size" : "60x60"
+ },
+ {
+ "idiom" : "iphone",
+ "scale" : "3x",
+ "size" : "60x60"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "20x20"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "29x29"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "40x40"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "1x",
+ "size" : "76x76"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "76x76"
+ },
+ {
+ "idiom" : "ipad",
+ "scale" : "2x",
+ "size" : "83.5x83.5"
+ },
+ {
+ "idiom" : "ios-marketing",
+ "scale" : "1x",
+ "size" : "1024x1024"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "1x",
+ "size" : "16x16"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "2x",
+ "size" : "16x16"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "1x",
+ "size" : "32x32"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "2x",
+ "size" : "32x32"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "1x",
+ "size" : "128x128"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "2x",
+ "size" : "128x128"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "1x",
+ "size" : "256x256"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "2x",
+ "size" : "256x256"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "1x",
+ "size" : "512x512"
+ },
+ {
+ "idiom" : "mac",
+ "scale" : "2x",
+ "size" : "512x512"
+ }
+ ],
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/Shared/Assets.xcassets/Contents.json b/examples/firebase_example/crashlytics/Shared/Assets.xcassets/Contents.json
new file mode 100644
index 000000000..73c00596a
--- /dev/null
+++ b/examples/firebase_example/crashlytics/Shared/Assets.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "author" : "xcode",
+ "version" : 1
+ }
+}
diff --git a/examples/firebase_example/crashlytics/Shared/ContentView.swift b/examples/firebase_example/crashlytics/Shared/ContentView.swift
new file mode 100644
index 000000000..588528fc5
--- /dev/null
+++ b/examples/firebase_example/crashlytics/Shared/ContentView.swift
@@ -0,0 +1,79 @@
+//
+// Copyright 2021 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.
+//
+
+import SwiftUI
+import FirebaseCrashlytics
+
+struct CrashButtonView: View {
+ var body: some View {
+ NavigationView {
+ Button(action: {
+ fatalError()
+ }) {
+ Text("Crash")
+ }
+ .navigationTitle("Crashlytics Example")
+ }
+ }
+}
+
+struct ContentView: View {
+ private var crashlyticsReference = Crashlytics.crashlytics()
+
+ #if compiler(>=5.5) && canImport(_Concurrency)
+ @available(iOS 15, tvOS 15, macOS 12, watchOS 8, *) func checkForUnsentReportsAsync() async {
+ let reportFound = await crashlyticsReference.checkForUnsentReports()
+ if reportFound {
+ crashlyticsReference.sendUnsentReports()
+ }
+ }
+ #endif
+
+ func checkForUnsentReports() {
+ crashlyticsReference.checkForUnsentReports { reportFound in
+ if reportFound {
+ Crashlytics.crashlytics().sendUnsentReports()
+ }
+ }
+ }
+
+ var body: some View {
+ if #available(iOS 15, tvOS 15, macOS 12, watchOS 8, *) {
+ #if compiler(>=5.5) && canImport(_Concurrency)
+ CrashButtonView()
+ .task {
+ await self.checkForUnsentReportsAsync()
+ }
+ #else
+ CrashButtonView()
+ .onAppear {
+ self.checkForUnsentReports()
+ }
+ #endif
+ } else {
+ CrashButtonView()
+ .onAppear {
+ self.checkForUnsentReports()
+ }
+ }
+ }
+}
+
+struct ContentView_Previews: PreviewProvider {
+ static var previews: some View {
+ ContentView()
+ }
+}
diff --git a/examples/firebase_example/crashlytics/Shared/CrashlyticsSwiftUIExampleApp.swift b/examples/firebase_example/crashlytics/Shared/CrashlyticsSwiftUIExampleApp.swift
new file mode 100644
index 000000000..8bee05d41
--- /dev/null
+++ b/examples/firebase_example/crashlytics/Shared/CrashlyticsSwiftUIExampleApp.swift
@@ -0,0 +1,73 @@
+//
+// Copyright 2021 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.
+//
+
+import SwiftUI
+import FirebaseCore
+import FirebaseCrashlytics
+
+@main
+struct CrashlyticsSwiftUIExampleApp: App {
+ private var crashlyticsReference = Crashlytics.crashlytics()
+ #if !os(watchOS)
+ let reachabilityHelper = ReachabililtyHelper()
+ #endif
+
+ func setUserInfo() {
+ let userInfo = [
+ NSLocalizedDescriptionKey: NSLocalizedString("The request failed.", comment: ""),
+ NSLocalizedFailureReasonErrorKey: NSLocalizedString(
+ "The response returned a 404.",
+ comment: ""
+ ),
+ NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(
+ "Does this page exist?",
+ comment: ""
+ ),
+ "ProductID": "123456",
+ "UserID": "Jane Smith",
+ ]
+ let error = NSError(domain: NSURLErrorDomain, code: -1001, userInfo: userInfo)
+ Crashlytics.crashlytics().record(error: error)
+ }
+
+ func setCustomValues() {
+ crashlyticsReference.setCustomValue(42, forKey: "MeaningOfLife")
+ crashlyticsReference.setCustomValue("Test value", forKey: "last_UI_action")
+ // Reachability is not compatible with watchOS
+ #if !os(watchOS)
+ let customKeysObject = [
+ "locale": reachabilityHelper.getLocale(),
+ "network_connection": reachabilityHelper.getNetworkStatus(),
+ ] as [String: Any]
+ crashlyticsReference.setCustomKeysAndValues(customKeysObject)
+ reachabilityHelper.updateAndTrackNetworkStatus()
+ #endif
+ Crashlytics.crashlytics().setUserID("123456789")
+ }
+
+ init() {
+ FirebaseApp.configure()
+ Crashlytics.crashlytics().log("App loaded")
+ setCustomValues()
+ setUserInfo()
+ }
+
+ var body: some Scene {
+ WindowGroup {
+ ContentView()
+ }
+ }
+}
diff --git a/examples/firebase_example/crashlytics/Shared/ReachabililtyHelper.swift b/examples/firebase_example/crashlytics/Shared/ReachabililtyHelper.swift
new file mode 100644
index 000000000..f2bdee330
--- /dev/null
+++ b/examples/firebase_example/crashlytics/Shared/ReachabililtyHelper.swift
@@ -0,0 +1,68 @@
+//
+// Copyright 2021 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.
+//
+
+import Foundation
+import FirebaseCrashlytics
+import Reachability
+
+class ReachabililtyHelper: NSObject {
+ /**
+ * Retrieve the locale information for the app.
+ */
+ func getLocale() -> String {
+ return Locale.preferredLanguages[0]
+ }
+
+ /**
+ * Retrieve the network status for the app.
+ */
+ func getNetworkStatus() -> String {
+ guard let reachability = try? Reachability() else {
+ return "unknown"
+ }
+ switch reachability.connection {
+ case .wifi:
+ return "wifi"
+ case .cellular:
+ return "cellular"
+ case .unavailable:
+ return "unavailable"
+ case .none:
+ // Duplicate of unavailable.
+ return "unavailable"
+ }
+ }
+
+ /**
+ * Add a hook to update network status going forward.
+ */
+ func updateAndTrackNetworkStatus() {
+ NotificationCenter.default.addObserver(self,
+ selector: #selector(reachabilityChanged(note:)),
+ name: .reachabilityChanged,
+ object: nil)
+ do {
+ let reachability = try Reachability()
+ try reachability.startNotifier()
+ } catch {
+ print("Could not start reachability notifier: \(error)")
+ }
+ }
+
+ @objc func reachabilityChanged(note: Notification) {
+ Crashlytics.crashlytics().setCustomValue(getNetworkStatus(), forKey: "network_connection")
+ }
+}
diff --git a/examples/firebase_example/crashlytics/Shared/UITests.swift b/examples/firebase_example/crashlytics/Shared/UITests.swift
new file mode 100644
index 000000000..e980172a5
--- /dev/null
+++ b/examples/firebase_example/crashlytics/Shared/UITests.swift
@@ -0,0 +1,46 @@
+//
+// Copyright 2021 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.
+//
+
+import XCTest
+
+class UITests: XCTestCase {
+ override func setUpWithError() throws {
+ continueAfterFailure = false
+ }
+
+ func testStaticUI() throws {
+ let app = XCUIApplication()
+ app.launch()
+ #if !os(macOS)
+ XCTAssertTrue(
+ app.navigationBars["Crashlytics Example"].exists,
+ "Crashlytics Example is missing from the navigation bar"
+ )
+ #endif
+ XCTAssertTrue(app.buttons["Crash"].exists, "Crash button does not exist.")
+ XCTAssertTrue(app.buttons["Crash"].isEnabled, "Crash button is not enabled.")
+ XCTAssertTrue(app.buttons["Crash"].isHittable, "Crash button is missing from the view.")
+ }
+
+ func testLaunchPerformance() throws {
+ if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) {
+ // This measures how long it takes to launch your application.
+ measure(metrics: [XCTApplicationLaunchMetric()]) {
+ XCUIApplication().launch()
+ }
+ }
+ }
+}
diff --git a/examples/firebase_example/crashlytics/iOS/Info.plist b/examples/firebase_example/crashlytics/iOS/Info.plist
new file mode 100644
index 000000000..efc211a0c
--- /dev/null
+++ b/examples/firebase_example/crashlytics/iOS/Info.plist
@@ -0,0 +1,50 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ UIApplicationSceneManifest
+
+ UIApplicationSupportsMultipleScenes
+
+
+ UIApplicationSupportsIndirectInputEvents
+
+ UILaunchScreen
+
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
diff --git a/examples/firebase_example/crashlytics/macOS/Info.plist b/examples/firebase_example/crashlytics/macOS/Info.plist
new file mode 100644
index 000000000..6b2abe4a8
--- /dev/null
+++ b/examples/firebase_example/crashlytics/macOS/Info.plist
@@ -0,0 +1,28 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIconFile
+
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1
+ LSMinimumSystemVersion
+ $(MACOSX_DEPLOYMENT_TARGET)
+ NSHumanReadableCopyright
+ Copyright © 2021 Google Inc. All rights reserved.
+
+
diff --git a/examples/firebase_example/crashlytics/macOS/macOS.entitlements b/examples/firebase_example/crashlytics/macOS/macOS.entitlements
new file mode 100644
index 000000000..625af03d9
--- /dev/null
+++ b/examples/firebase_example/crashlytics/macOS/macOS.entitlements
@@ -0,0 +1,12 @@
+
+
+
+
+ com.apple.security.app-sandbox
+
+ com.apple.security.files.user-selected.read-only
+
+ com.apple.security.network.client
+
+
+
diff --git a/examples/firebase_example/swift_deps_index.json b/examples/firebase_example/swift_deps_index.json
index fb12eb621..f5c282af6 100644
--- a/examples/firebase_example/swift_deps_index.json
+++ b/examples/firebase_example/swift_deps_index.json
@@ -1,28 +1,19 @@
{
"direct_dep_identities": [
- "firebase-ios-sdk"
+ "firebase-ios-sdk",
+ "reachability.swift"
],
"modules": [
{
"name": "abseil",
"c99name": "abseil",
- "src_type": "clang",
- "label": "@swiftpkg_abseil_cpp_swiftpm//:abseil",
- "package_identity": "abseil-cpp-swiftpm",
+ "src_type": "binary",
+ "label": "@swiftpkg_abseil_cpp_binary//:remote_archive_abseil.zip_abseil",
+ "package_identity": "abseil-cpp-binary",
"product_memberships": [
"abseil"
]
},
- {
- "name": "openssl_grpc",
- "c99name": "openssl_grpc",
- "src_type": "clang",
- "label": "@swiftpkg_boringssl_swiftpm//:openssl_grpc",
- "package_identity": "boringssl-swiftpm",
- "product_memberships": [
- "openssl_grpc"
- ]
- },
{
"name": "Firebase",
"c99name": "Firebase",
@@ -234,8 +225,10 @@
"FirebaseFirestoreCombine-Community",
"FirebaseFunctionsCombine-Community",
"FirebaseStorageCombine-Community",
+ "FirebaseCrashlytics",
"FirebaseFirestoreSwift",
"FirebaseFunctions",
+ "FirebasePerformance",
"FirebaseStorage"
]
},
@@ -472,6 +465,29 @@
"FirebaseRemoteConfigSwift"
]
},
+ {
+ "name": "FirebaseSessionsObjC",
+ "c99name": "FirebaseSessionsObjC",
+ "src_type": "objc",
+ "label": "@swiftpkg_firebase_ios_sdk//:FirebaseSessions_FirebaseSessionsObjC",
+ "package_identity": "firebase-ios-sdk",
+ "product_memberships": [
+ "FirebaseCrashlytics",
+ "FirebasePerformance"
+ ]
+ },
+ {
+ "name": "FirebaseSessions",
+ "c99name": "FirebaseSessions",
+ "src_type": "swift",
+ "label": "@swiftpkg_firebase_ios_sdk//:FirebaseSessions_Sources_FirebaseSessions",
+ "modulemap_label": "@swiftpkg_firebase_ios_sdk//:FirebaseSessions_Sources_FirebaseSessions_modulemap",
+ "package_identity": "firebase-ios-sdk",
+ "product_memberships": [
+ "FirebaseCrashlytics",
+ "FirebasePerformance"
+ ]
+ },
{
"name": "FirebaseSharedSwift",
"c99name": "FirebaseSharedSwift",
@@ -499,18 +515,6 @@
"FirebaseStorage"
]
},
- {
- "name": "FirebaseFirestore",
- "c99name": "FirebaseFirestore",
- "src_type": "objc",
- "label": "@swiftpkg_firebase_ios_sdk//:Firestore_FirebaseFirestore",
- "package_identity": "firebase-ios-sdk",
- "product_memberships": [
- "FirebaseFirestoreCombine-Community",
- "FirebaseFirestore",
- "FirebaseFirestoreSwift"
- ]
- },
{
"name": "FirebaseFirestoreSwift",
"c99name": "FirebaseFirestoreSwift",
@@ -589,7 +593,9 @@
"label": "@swiftpkg_firebase_ios_sdk//:SwiftPM-PlatformExclude_FirebaseFirestoreWrap_FirebaseFirestoreTarget",
"package_identity": "firebase-ios-sdk",
"product_memberships": [
- "FirebaseFirestore"
+ "FirebaseFirestoreCombine-Community",
+ "FirebaseFirestore",
+ "FirebaseFirestoreSwift"
]
},
{
@@ -624,6 +630,18 @@
"FirebaseAnalyticsSwift"
]
},
+ {
+ "name": "FirebaseFirestore",
+ "c99name": "FirebaseFirestore",
+ "src_type": "binary",
+ "label": "@swiftpkg_firebase_ios_sdk//:remote_archive_FirebaseFirestore.zip_FirebaseFirestore",
+ "package_identity": "firebase-ios-sdk",
+ "product_memberships": [
+ "FirebaseFirestoreCombine-Community",
+ "FirebaseFirestore",
+ "FirebaseFirestoreSwift"
+ ]
+ },
{
"name": "GoogleAppMeasurementOnDeviceConversionTarget",
"c99name": "GoogleAppMeasurementOnDeviceConversionTarget",
@@ -817,24 +835,54 @@
]
},
{
- "name": "gRPC-Core",
- "c99name": "gRPC_Core",
- "src_type": "clang",
- "label": "@swiftpkg_grpc_ios//:native_src_gRPC-Core",
- "package_identity": "grpc-ios",
+ "name": "gRPC-CXX-Target",
+ "c99name": "gRPC_CXX_Target",
+ "src_type": "objc",
+ "label": "@swiftpkg_grpc_binary//:SwiftPM-PlatformExclude_gRPC-CXX-Target",
+ "package_identity": "grpc-binary",
"product_memberships": [
- "gRPC-Core",
- "gRPC-cpp"
+ "gRPC-C++"
]
},
{
- "name": "gRPC-cpp",
- "c99name": "gRPC_cpp",
- "src_type": "clang",
- "label": "@swiftpkg_grpc_ios//:native_src_gRPC-cpp",
- "package_identity": "grpc-ios",
+ "name": "gRPC-CXX-Wrapper",
+ "c99name": "gRPC_CXX_Wrapper",
+ "src_type": "objc",
+ "label": "@swiftpkg_grpc_binary//:gRPC-CXX-Wrapper_gRPC-CXX-Wrapper",
+ "package_identity": "grpc-binary",
"product_memberships": [
- "gRPC-cpp"
+ "gRPC-C++"
+ ]
+ },
+ {
+ "name": "BoringSSL-GRPC",
+ "c99name": "BoringSSL_GRPC",
+ "src_type": "binary",
+ "label": "@swiftpkg_grpc_binary//:remote_archive_BoringSSL-GRPC.zip_BoringSSL-GRPC",
+ "package_identity": "grpc-binary",
+ "product_memberships": [
+ "gRPC-C++"
+ ]
+ },
+ {
+ "name": "gRPC-C++",
+ "c99name": "gRPC_C__",
+ "src_type": "binary",
+ "label": "@swiftpkg_grpc_binary//:remote_archive_gRPC-C++.zip_gRPC-C++",
+ "package_identity": "grpc-binary",
+ "product_memberships": [
+ "gRPC-C++"
+ ]
+ },
+ {
+ "name": "gRPC-Core",
+ "c99name": "gRPC_Core",
+ "src_type": "binary",
+ "label": "@swiftpkg_grpc_binary//:remote_archive_gRPC-Core.zip_gRPC-Core",
+ "package_identity": "grpc-binary",
+ "product_memberships": [
+ "gRPC-Core",
+ "gRPC-C++"
]
},
{
@@ -936,6 +984,16 @@
"PromisesTestHelpers"
]
},
+ {
+ "name": "Reachability",
+ "c99name": "Reachability",
+ "src_type": "swift",
+ "label": "@swiftpkg_reachability.swift//:Sources_Reachability",
+ "package_identity": "reachability.swift",
+ "product_memberships": [
+ "Reachability"
+ ]
+ },
{
"name": "SwiftProtobufPlugin",
"c99name": "SwiftProtobufPlugin",
@@ -985,19 +1043,11 @@
],
"products": [
{
- "identity": "abseil-cpp-swiftpm",
+ "identity": "abseil-cpp-binary",
"name": "abseil",
"type": "library",
"target_labels": [
- "@swiftpkg_abseil_cpp_swiftpm//:abseil"
- ]
- },
- {
- "identity": "boringssl-swiftpm",
- "name": "openssl_grpc",
- "type": "library",
- "target_labels": [
- "@swiftpkg_boringssl_swiftpm//:openssl_grpc"
+ "@swiftpkg_abseil_cpp_binary//:remote_archive_abseil.zip_abseil"
]
},
{
@@ -1329,19 +1379,19 @@
]
},
{
- "identity": "grpc-ios",
- "name": "gRPC-Core",
+ "identity": "grpc-binary",
+ "name": "gRPC-C++",
"type": "library",
"target_labels": [
- "@swiftpkg_grpc_ios//:native_src_gRPC-Core"
+ "@swiftpkg_grpc_binary//:SwiftPM-PlatformExclude_gRPC-CXX-Target"
]
},
{
- "identity": "grpc-ios",
- "name": "gRPC-cpp",
+ "identity": "grpc-binary",
+ "name": "gRPC-Core",
"type": "library",
"target_labels": [
- "@swiftpkg_grpc_ios//:native_src_gRPC-cpp"
+ "@swiftpkg_grpc_binary//:remote_archive_gRPC-Core.zip_gRPC-Core"
]
},
{
@@ -1425,6 +1475,14 @@
"@swiftpkg_promises//:Sources_PromisesTestHelpers"
]
},
+ {
+ "identity": "reachability.swift",
+ "name": "Reachability",
+ "type": "library",
+ "target_labels": [
+ "@swiftpkg_reachability.swift//:Sources_Reachability"
+ ]
+ },
{
"identity": "swift-protobuf",
"name": "SwiftProtobuf",
@@ -1460,39 +1518,30 @@
],
"packages": [
{
- "name": "swiftpkg_abseil_cpp_swiftpm",
- "identity": "abseil-cpp-swiftpm",
- "remote": {
- "commit": "583de9bd60f66b40e78d08599cc92036c2e7e4e1",
- "remote": "https://github.com/firebase/abseil-cpp-SwiftPM.git",
- "version": "0.20220203.2"
- }
- },
- {
- "name": "swiftpkg_boringssl_swiftpm",
- "identity": "boringssl-swiftpm",
+ "name": "swiftpkg_abseil_cpp_binary",
+ "identity": "abseil-cpp-binary",
"remote": {
- "commit": "dd3eda2b05a3f459fc3073695ad1b28659066eab",
- "remote": "https://github.com/firebase/boringssl-SwiftPM.git",
- "version": "0.9.1"
+ "commit": "bfc0b6f81adc06ce5121eb23f628473638d67c5c",
+ "remote": "https://github.com/google/abseil-cpp-binary.git",
+ "version": "1.2022062300.0"
}
},
{
"name": "swiftpkg_firebase_ios_sdk",
"identity": "firebase-ios-sdk",
"remote": {
- "commit": "f567ed9a2b30e29159df258049a9c662c517688e",
+ "commit": "e700a8f40c87c31cab7984875fcc1225d96b25bf",
"remote": "https://github.com/firebase/firebase-ios-sdk",
- "version": "10.5.0"
+ "version": "10.11.0"
}
},
{
"name": "swiftpkg_googleappmeasurement",
"identity": "googleappmeasurement",
"remote": {
- "commit": "9a09ece724128e8d1e14c5133b87c0e236844ac0",
+ "commit": "62e3a0c09a75e2637f5300d46f05a59313f1c286",
"remote": "https://github.com/google/GoogleAppMeasurement.git",
- "version": "10.4.0"
+ "version": "10.11.0"
}
},
{
@@ -1514,21 +1563,21 @@
}
},
{
- "name": "swiftpkg_grpc_ios",
- "identity": "grpc-ios",
+ "name": "swiftpkg_grpc_binary",
+ "identity": "grpc-binary",
"remote": {
- "commit": "8440b914756e0d26d4f4d054a1c1581daedfc5b6",
- "remote": "https://github.com/grpc/grpc-ios.git",
- "version": "1.44.3-grpc"
+ "commit": "f1b366129d1125be7db83247e003fc333104b569",
+ "remote": "https://github.com/google/grpc-binary.git",
+ "version": "1.50.2"
}
},
{
"name": "swiftpkg_gtm_session_fetcher",
"identity": "gtm-session-fetcher",
"remote": {
- "commit": "96d7cc73a71ce950723aa3c50ce4fb275ae180b8",
+ "commit": "5ccda3981422a84186387dbb763ba739178b529c",
"remote": "https://github.com/google/gtm-session-fetcher.git",
- "version": "3.1.0"
+ "version": "2.3.0"
}
},
{
@@ -1558,6 +1607,15 @@
"version": "2.1.1"
}
},
+ {
+ "name": "swiftpkg_reachability.swift",
+ "identity": "reachability.swift",
+ "remote": {
+ "commit": "c01bbdf2d633cf049ae1ed1a68a2020a8bda32e2",
+ "remote": "https://github.com/ashleymills/Reachability.swift.git",
+ "version": "5.1.0"
+ }
+ },
{
"name": "swiftpkg_swift_protobuf",
"identity": "swift-protobuf",
diff --git a/swiftpkg/internal/bzl_selects.bzl b/swiftpkg/internal/bzl_selects.bzl
index d949f983d..4732ece0a 100644
--- a/swiftpkg/internal/bzl_selects.bzl
+++ b/swiftpkg/internal/bzl_selects.bzl
@@ -39,20 +39,27 @@ def _new(value, kind = None, condition = None):
value = value,
)
-def _new_from_build_setting(build_setting):
+def _new_from_build_setting(build_setting, values_map_fn = None):
"""Create conditions from an SPM build setting.
Args:
build_setting: A `struct` as returned by `pkginfos.new_build_setting`.
+ values_map_fn: Optional. A `function` that is applied to each value
+ before being added to condition struct.
Returns:
A `list` of condition `struct` values (`bzl_selects.new`).
"""
+ if values_map_fn == None:
+ values = build_setting.values
+ else:
+ values = lists.map(build_setting.values, values_map_fn)
+
bsc = build_setting.condition
if bsc == None:
return [
_new(kind = build_setting.kind, value = v)
- for v in build_setting.values
+ for v in values
]
platforms_len = len(bsc.platforms)
@@ -72,7 +79,7 @@ Found a build setting condition that had no platforms or a configuration. {}\
return [
_new(kind = build_setting.kind, value = v, condition = c)
- for v in build_setting.values
+ for v in values
for c in conditions
]
diff --git a/swiftpkg/internal/clang_files.bzl b/swiftpkg/internal/clang_files.bzl
index e825b319c..61b0d72b0 100644
--- a/swiftpkg/internal/clang_files.bzl
+++ b/swiftpkg/internal/clang_files.bzl
@@ -18,7 +18,7 @@ _HEADER_EXTS = [".h", ".hh", ".hpp", ".hxx", ".inl", ".H"]
# https://bazel.build/reference/be/objective-c#objc_library.srcs
# NOTE: From examples found so far, .inc files tend to include source, not
# header declarations.
-_SRC_EXTS = [".c", ".cc", ".S", ".so", ".o", ".m", ".inc"]
+_SRC_EXTS = [".c", ".cc", ".S", ".so", ".o", ".m", ".mm", ".inc"]
def _is_hdr(path):
_root, ext = paths.split_extension(path)
diff --git a/swiftpkg/internal/module_maps.bzl b/swiftpkg/internal/module_maps.bzl
index eed789b6d..fe7088fca 100644
--- a/swiftpkg/internal/module_maps.bzl
+++ b/swiftpkg/internal/module_maps.bzl
@@ -118,6 +118,13 @@ def write_module_map(
# Write a `use` declaration for each of the module's dependencies.
content.add_all(dependent_module_names, format_each = ' use "%s"')
+
+ # Export all of the modules referenced by the headers
+ # This was needed to allow the firebase Crashlytics example to build.
+ content.add("")
+ content.add(" export *")
+
+ # Close out the module
content.add("}")
actions.write(
diff --git a/swiftpkg/internal/objc_files.bzl b/swiftpkg/internal/objc_files.bzl
index b55b02224..daba5ec52 100644
--- a/swiftpkg/internal/objc_files.bzl
+++ b/swiftpkg/internal/objc_files.bzl
@@ -135,7 +135,7 @@ def _has_objc_srcs(srcs):
A `bool` indicating whether any of the source files are Objective-C
files.
"""
- return lists.contains(srcs, lambda x: x.endswith(".m"))
+ return lists.contains(srcs, lambda x: x.endswith(".m") or x.endswith(".mm"))
objc_files = struct(
collect_builtin_frameworks = _collect_builtin_frameworks,
diff --git a/swiftpkg/internal/pkginfos.bzl b/swiftpkg/internal/pkginfos.bzl
index 701c11227..14c2e2298 100644
--- a/swiftpkg/internal/pkginfos.bzl
+++ b/swiftpkg/internal/pkginfos.bzl
@@ -875,6 +875,9 @@ def _new_clang_src_info_from_sources(
extra_hdr_dirs.append(normalized_pi)
for ehd in extra_hdr_dirs:
abs_ehd = paths.normalize(paths.join(pkg_path, ehd))
+ if not repository_files.path_exists(repository_ctx, abs_ehd):
+ # Do not fail if the path does not exist.
+ continue
hdr_paths = repository_files.list_files_under(repository_ctx, abs_ehd)
hdr_paths = [
clang_files.relativize(hp, pkg_path)
diff --git a/swiftpkg/internal/repository_files.bzl b/swiftpkg/internal/repository_files.bzl
index 4b2ee7865..94fba2bd7 100644
--- a/swiftpkg/internal/repository_files.bzl
+++ b/swiftpkg/internal/repository_files.bzl
@@ -2,6 +2,22 @@
load("@cgrindel_bazel_starlib//bzllib:defs.bzl", "lists")
+def _path_exists(repository_ctx, path):
+ """Determines if the specified path exists.
+
+ Args:
+ repository_ctx: A `repository_ctx` instance.
+ path: A path `string` value.
+
+ Returns:
+ A `bool` indicating whether the path exists.
+ """
+ exec_result = repository_ctx.execute(
+ ["test", "-e", path],
+ quiet = True,
+ )
+ return exec_result.return_code == 0
+
def _list_files_under(repository_ctx, path, exclude = []):
"""Retrieves the list of files under the specified path.
@@ -155,4 +171,5 @@ repository_files = struct(
is_directory = _is_directory,
list_directories_under = _list_directories_under,
list_files_under = _list_files_under,
+ path_exists = _path_exists,
)
diff --git a/swiftpkg/internal/starlark_codegen.bzl b/swiftpkg/internal/starlark_codegen.bzl
index 7a4873da0..5cce3bf72 100644
--- a/swiftpkg/internal/starlark_codegen.bzl
+++ b/swiftpkg/internal/starlark_codegen.bzl
@@ -289,6 +289,20 @@ def _expr_to_starlark_parts(expr, indent):
parts.append(" ")
return parts
+# MARK: - Escape String
+
+def _normalize_define_value(value):
+ """Ensures that the specified value is properly formatted as a `defines` \
+ value.
+
+ Args:
+ value: The `string` to normalize.
+
+ Returns:
+ A `string` that is formatted properly to be a `defines` value.
+ """
+ return value.replace(" ", "\\ ")
+
# MARK: - API Definition
starlark_codegen = struct(
@@ -300,4 +314,5 @@ starlark_codegen = struct(
normalize = _normalize,
to_starlark = _to_starlark,
with_indent = _with_indent,
+ normalize_define_value = _normalize_define_value,
)
diff --git a/swiftpkg/internal/swiftpkg_build_files.bzl b/swiftpkg/internal/swiftpkg_build_files.bzl
index 858d9b776..282d468fd 100644
--- a/swiftpkg/internal/swiftpkg_build_files.bzl
+++ b/swiftpkg/internal/swiftpkg_build_files.bzl
@@ -196,7 +196,12 @@ def _clang_target_build_file(repository_ctx, pkg_ctx, target):
if target.clang_settings != None:
defines.extend(lists.flatten([
- bzl_selects.new_from_build_setting(bs)
+ bzl_selects.new_from_build_setting(
+ bs,
+ # Define values can contain spaces. Bazel requires that they
+ # are already escaped.
+ values_map_fn = scg.normalize_define_value,
+ )
for bs in target.clang_settings.defines
]))
diff --git a/swiftpkg/tests/bzl_selects_tests.bzl b/swiftpkg/tests/bzl_selects_tests.bzl
index 87d2c555a..c04c99233 100644
--- a/swiftpkg/tests/bzl_selects_tests.bzl
+++ b/swiftpkg/tests/bzl_selects_tests.bzl
@@ -127,9 +127,24 @@ def _new_from_build_setting_test(ctx):
),
],
),
+ struct(
+ msg = "with values_map_fn",
+ bs = pkginfos.new_build_setting(
+ kind = "define",
+ values = ["CHICKEN=Foo"],
+ ),
+ values_map_fn = lambda x: x + "Bar",
+ exp = [
+ bzl_selects.new(value = "CHICKEN=FooBar", kind = "define"),
+ ],
+ ),
]
for t in tests:
- actual = bzl_selects.new_from_build_setting(t.bs)
+ values_map_fn = getattr(t, "values_map_fn", None)
+ actual = bzl_selects.new_from_build_setting(
+ t.bs,
+ values_map_fn = values_map_fn,
+ )
asserts.equals(env, t.exp, actual, t.msg)
return unittest.end(env)
diff --git a/swiftpkg/tests/objc_files_tests.bzl b/swiftpkg/tests/objc_files_tests.bzl
index b14643ecc..b3ce1e791 100644
--- a/swiftpkg/tests/objc_files_tests.bzl
+++ b/swiftpkg/tests/objc_files_tests.bzl
@@ -137,9 +137,43 @@ def _collect_builtin_frameworks_test(ctx):
collect_builtin_frameworks_test = unittest.make(_collect_builtin_frameworks_test)
+def _has_objc_srcs_test(ctx):
+ env = unittest.begin(ctx)
+
+ tests = [
+ struct(
+ msg = "has entries",
+ srcs = [],
+ exp = False,
+ ),
+ struct(
+ msg = "has .m file",
+ srcs = ["foo.h", "foo.m"],
+ exp = True,
+ ),
+ struct(
+ msg = "has .mm file",
+ srcs = ["foo.h", "foo.mm"],
+ exp = True,
+ ),
+ struct(
+ msg = "has no objc srcs",
+ srcs = ["foo.h", "foo.c"],
+ exp = False,
+ ),
+ ]
+ for t in tests:
+ actual = objc_files.has_objc_srcs(t.srcs)
+ asserts.equals(env, t.exp, actual, t.msg)
+
+ return unittest.end(env)
+
+has_objc_srcs_test = unittest.make(_has_objc_srcs_test)
+
def objc_files_test_suite():
return unittest.suite(
"objc_files_tests",
parse_for_imported_framework_test,
collect_builtin_frameworks_test,
+ has_objc_srcs_test,
)
diff --git a/swiftpkg/tests/starlark_codegen_tests.bzl b/swiftpkg/tests/starlark_codegen_tests.bzl
index 65350b6c7..278c958ad 100644
--- a/swiftpkg/tests/starlark_codegen_tests.bzl
+++ b/swiftpkg/tests/starlark_codegen_tests.bzl
@@ -332,6 +332,29 @@ foo(
expr_to_starlark_parts_test = unittest.make(_expr_to_starlark_parts_test)
+def _normalize_define_value_test(ctx):
+ env = unittest.begin(ctx)
+
+ tests = [
+ struct(
+ msg = "no spaces",
+ val = "CHICKEN=foo",
+ exp = "CHICKEN=foo",
+ ),
+ struct(
+ msg = "with spaces",
+ val = "CHICKEN=Foo iOS SDK",
+ exp = "CHICKEN=Foo\\ iOS\\ SDK",
+ ),
+ ]
+ for t in tests:
+ actual = scg.normalize_define_value(t.val)
+ asserts.equals(env, t.exp, actual, t.msg)
+
+ return unittest.end(env)
+
+normalize_define_value_test = unittest.make(_normalize_define_value_test)
+
def starlark_codegen_test_suite():
return unittest.suite(
"starlark_codegen_tests",
@@ -342,4 +365,5 @@ def starlark_codegen_test_suite():
op_to_starlark_parts_test,
new_expr_test,
expr_to_starlark_parts_test,
+ normalize_define_value_test,
)