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, )