diff --git a/.github/workflows/all_plugins.yaml b/.github/workflows/all_plugins.yaml index 8c0e545f645f..6d7e63d87271 100644 --- a/.github/workflows/all_plugins.yaml +++ b/.github/workflows/all_plugins.yaml @@ -124,7 +124,7 @@ jobs: "flutter build web" swift-integration: runs-on: macos-latest - timeout-minutes: 30 + timeout-minutes: 40 steps: - uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938 - uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225 diff --git a/.github/workflows/scripts/swift-integration.dart b/.github/workflows/scripts/swift-integration.dart index fe3d50e5e3ca..8640dbfaebf2 100644 --- a/.github/workflows/scripts/swift-integration.dart +++ b/.github/workflows/scripts/swift-integration.dart @@ -10,6 +10,8 @@ void main() async { await buildSwiftExampleApp('ios', 'cloud_firestore'); await buildSwiftExampleApp('macos', 'firebase_core'); await buildSwiftExampleApp('macos', 'cloud_firestore'); + await buildSwiftExampleApp('ios', 'cloud_functions'); + await buildSwiftExampleApp('macos', 'cloud_functions'); } Future deleteFirstLine(String filePath) async { diff --git a/packages/cloud_functions/cloud_functions/example/.gitignore b/packages/cloud_functions/cloud_functions/example/.gitignore index 29a3a5017f04..79c113f9b501 100644 --- a/packages/cloud_functions/cloud_functions/example/.gitignore +++ b/packages/cloud_functions/cloud_functions/example/.gitignore @@ -5,9 +5,11 @@ *.swp .DS_Store .atom/ +.build/ .buildlog/ .history .svn/ +.swiftpm/ migrate_working_dir/ # IntelliJ related diff --git a/packages/cloud_functions/cloud_functions/example/ios/Flutter/Debug.xcconfig b/packages/cloud_functions/cloud_functions/example/ios/Flutter/Debug.xcconfig index e8efba114687..ec97fc6f3021 100644 --- a/packages/cloud_functions/cloud_functions/example/ios/Flutter/Debug.xcconfig +++ b/packages/cloud_functions/cloud_functions/example/ios/Flutter/Debug.xcconfig @@ -1,2 +1,2 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "Generated.xcconfig" diff --git a/packages/cloud_functions/cloud_functions/example/ios/Flutter/Release.xcconfig b/packages/cloud_functions/cloud_functions/example/ios/Flutter/Release.xcconfig index 399e9340e6f6..c4855bfe2000 100644 --- a/packages/cloud_functions/cloud_functions/example/ios/Flutter/Release.xcconfig +++ b/packages/cloud_functions/cloud_functions/example/ios/Flutter/Release.xcconfig @@ -1,2 +1,2 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "Generated.xcconfig" diff --git a/packages/cloud_functions/cloud_functions/example/macos/Flutter/Flutter-Debug.xcconfig b/packages/cloud_functions/cloud_functions/example/macos/Flutter/Flutter-Debug.xcconfig index 785633d3a86b..4b81f9b2d200 100644 --- a/packages/cloud_functions/cloud_functions/example/macos/Flutter/Flutter-Debug.xcconfig +++ b/packages/cloud_functions/cloud_functions/example/macos/Flutter/Flutter-Debug.xcconfig @@ -1,2 +1,2 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/cloud_functions/cloud_functions/example/macos/Flutter/Flutter-Release.xcconfig b/packages/cloud_functions/cloud_functions/example/macos/Flutter/Flutter-Release.xcconfig index 5fba960c3af2..5caa9d1579e4 100644 --- a/packages/cloud_functions/cloud_functions/example/macos/Flutter/Flutter-Release.xcconfig +++ b/packages/cloud_functions/cloud_functions/example/macos/Flutter/Flutter-Release.xcconfig @@ -1,2 +1,2 @@ -#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" +#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig" #include "ephemeral/Flutter-Generated.xcconfig" diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions.podspec b/packages/cloud_functions/cloud_functions/ios/cloud_functions.podspec index a271c1e1b185..1ce70c8848da 100644 --- a/packages/cloud_functions/cloud_functions/ios/cloud_functions.podspec +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions.podspec @@ -24,8 +24,8 @@ Pod::Spec.new do |s| s.license = { :file => '../LICENSE' } s.authors = 'The Chromium Authors' s.source = { :path => '.' } - s.source_files = 'Classes/**/*.{h,m}' - s.public_header_files = 'Classes/*.h' + s.source_files = 'cloud_functions/Sources/cloud_functions/**/*.{h,m}' + s.public_header_files = 'cloud_functions/Sources/cloud_functions/include/*.h' s.ios.deployment_target = '13.0' # Flutter dependencies @@ -37,7 +37,7 @@ Pod::Spec.new do |s| s.static_framework = true s.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => "LIBRARY_VERSION=\\@\\\"#{library_version}\\\" LIBRARY_NAME=\\@\\\"flutter-fire-fn\\\"", + 'GCC_PREPROCESSOR_DEFINITIONS' => "LIBRARY_VERSION=\\\"#{library_version}\\\" LIBRARY_NAME=\\\"flutter-fire-fn\\\"", 'DEFINES_MODULE' => 'YES' } end diff --git a/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift new file mode 100644 index 000000000000..bf2024670682 --- /dev/null +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Package.swift @@ -0,0 +1,115 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +// Copyright 2024, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import Foundation +import PackageDescription + +enum ConfigurationError: Error { + case fileNotFound(String) + case parsingError(String) + case invalidFormat(String) +} + +let functionsDirectory = String(URL(string: #file)!.deletingLastPathComponent().absoluteString + .dropLast()) + +func loadFirebaseSDKVersion() throws -> String { + let firebaseCoreScriptPath = NSString.path(withComponents: [ + functionsDirectory, + "..", + "generated_firebase_sdk_version.txt", + ]) + do { + let version = try String(contentsOfFile: firebaseCoreScriptPath, encoding: .utf8) + .trimmingCharacters(in: .whitespacesAndNewlines) + return version + } catch { + throw ConfigurationError + .fileNotFound("Error loading or parsing generated_firebase_sdk_version.txt: \(error)") + } +} + +func loadPubspecVersions() throws -> (packageVersion: String, firebaseCoreVersion: String) { + let pubspecPath = NSString.path(withComponents: [functionsDirectory, "..", "..", "pubspec.yaml"]) + do { + let yamlString = try String(contentsOfFile: pubspecPath, encoding: .utf8) + let lines = yamlString.split(separator: "\n") + + guard let packageVersionLine = lines.first(where: { $0.starts(with: "version:") }) else { + throw ConfigurationError.invalidFormat("No package version line found in pubspec.yaml") + } + var packageVersion = packageVersionLine.split(separator: ":")[1] + .trimmingCharacters(in: .whitespaces) + .replacingOccurrences(of: "+", with: "-") + packageVersion = packageVersion.replacingOccurrences(of: "^", with: "") + + guard let firebaseCoreVersionLine = lines.first(where: { $0.contains("firebase_core:") }) else { + throw ConfigurationError + .invalidFormat("No firebase_core dependency version line found in pubspec.yaml") + } + var firebaseCoreVersion = firebaseCoreVersionLine.split(separator: ":")[1] + .trimmingCharacters(in: .whitespaces) + firebaseCoreVersion = firebaseCoreVersion.replacingOccurrences(of: "^", with: "") + + return (packageVersion, firebaseCoreVersion) + } catch { + throw ConfigurationError.fileNotFound("Error loading or parsing pubspec.yaml: \(error)") + } +} + +let library_version: String +let firebase_sdk_version_string: String +let firebase_core_version_string: String +let shared_spm_tag = "-firebase-core-swift" + +do { + library_version = try loadPubspecVersions().packageVersion + firebase_sdk_version_string = try loadFirebaseSDKVersion() + firebase_core_version_string = try loadPubspecVersions().firebaseCoreVersion +} catch { + fatalError("Failed to load configuration: \(error)") +} + +guard let firebase_sdk_version = Version(firebase_sdk_version_string) else { + fatalError("Invalid Firebase SDK version: \(firebase_sdk_version_string)") +} + +guard let shared_spm_version = Version("\(firebase_core_version_string)\(shared_spm_tag)") else { + fatalError("Invalid firebase_core version: \(firebase_core_version_string)\(shared_spm_tag)") +} + +let package = Package( + name: "cloud_functions", + platforms: [ + .iOS("13.0"), + ], + products: [ + .library(name: "cloud-functions", targets: ["cloud_functions"]), + ], + dependencies: [ + .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/flutterfire", exact: shared_spm_version), + ], + targets: [ + .target( + name: "cloud_functions", + dependencies: [ + .product(name: "FirebaseFunctions", package: "firebase-ios-sdk"), + // Wrapper dependency + .product(name: "firebase-core-shared", package: "flutterfire"), + ], + resources: [ + .process("Resources"), + ], + cSettings: [ + .headerSearchPath("include"), + .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_NAME", to: "\"flutter-fire-fn\""), + ] + ), + ] +) diff --git a/packages/cloud_functions/cloud_functions/ios/Classes/FLTFirebaseFunctionsPlugin.m b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/FLTFirebaseFunctionsPlugin.m similarity index 97% rename from packages/cloud_functions/cloud_functions/ios/Classes/FLTFirebaseFunctionsPlugin.m rename to packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/FLTFirebaseFunctionsPlugin.m index a98ba143f818..88a8342f290e 100644 --- a/packages/cloud_functions/cloud_functions/ios/Classes/FLTFirebaseFunctionsPlugin.m +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/FLTFirebaseFunctionsPlugin.m @@ -2,10 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "FLTFirebaseFunctionsPlugin.h" +#import "include/FLTFirebaseFunctionsPlugin.h" @import FirebaseFunctions; +#if __has_include() #import +#else +#import +#endif NSString *const kFLTFirebaseFunctionsChannelName = @"plugins.flutter.io/firebase_functions"; @@ -175,11 +179,11 @@ - (NSDictionary *_Nonnull)pluginConstantsForFIRApp:(FIRApp *)firebase_app { } - (NSString *_Nonnull)firebaseLibraryName { - return LIBRARY_NAME; + return @LIBRARY_NAME; } - (NSString *_Nonnull)firebaseLibraryVersion { - return LIBRARY_VERSION; + return @LIBRARY_VERSION; } - (NSString *_Nonnull)flutterChannelName { diff --git a/packages/cloud_functions/cloud_functions/ios/Assets/.gitkeep b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Resources/.gitkeep similarity index 100% rename from packages/cloud_functions/cloud_functions/ios/Assets/.gitkeep rename to packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/Resources/.gitkeep diff --git a/packages/cloud_functions/cloud_functions/ios/Classes/FLTFirebaseFunctionsPlugin.h b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/include/FLTFirebaseFunctionsPlugin.h similarity index 77% rename from packages/cloud_functions/cloud_functions/ios/Classes/FLTFirebaseFunctionsPlugin.h rename to packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/include/FLTFirebaseFunctionsPlugin.h index f08b5e53d050..ee6fbb56540d 100644 --- a/packages/cloud_functions/cloud_functions/ios/Classes/FLTFirebaseFunctionsPlugin.h +++ b/packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/include/FLTFirebaseFunctionsPlugin.h @@ -1,6 +1,7 @@ // Copyright 2020 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#import #if TARGET_OS_OSX #import @@ -9,7 +10,11 @@ #endif #import +#if __has_include() #import +#else +#import +#endif @interface FLTFirebaseFunctionsPlugin : FLTFirebasePlugin @end diff --git a/packages/cloud_functions/cloud_functions/ios/generated_firebase_sdk_version.txt b/packages/cloud_functions/cloud_functions/ios/generated_firebase_sdk_version.txt new file mode 100644 index 000000000000..72773deb895e --- /dev/null +++ b/packages/cloud_functions/cloud_functions/ios/generated_firebase_sdk_version.txt @@ -0,0 +1 @@ +11.4.0 diff --git a/packages/cloud_functions/cloud_functions/macos/Classes/FLTFirebaseFunctionsPlugin.h b/packages/cloud_functions/cloud_functions/macos/Classes/FLTFirebaseFunctionsPlugin.h deleted file mode 120000 index 2ec20dfbec11..000000000000 --- a/packages/cloud_functions/cloud_functions/macos/Classes/FLTFirebaseFunctionsPlugin.h +++ /dev/null @@ -1 +0,0 @@ -../../ios/Classes/FLTFirebaseFunctionsPlugin.h \ No newline at end of file diff --git a/packages/cloud_functions/cloud_functions/macos/Classes/FLTFirebaseFunctionsPlugin.m b/packages/cloud_functions/cloud_functions/macos/Classes/FLTFirebaseFunctionsPlugin.m deleted file mode 120000 index fa777c2efcdb..000000000000 --- a/packages/cloud_functions/cloud_functions/macos/Classes/FLTFirebaseFunctionsPlugin.m +++ /dev/null @@ -1 +0,0 @@ -../../ios/Classes/FLTFirebaseFunctionsPlugin.m \ No newline at end of file diff --git a/packages/cloud_functions/cloud_functions/macos/cloud_functions.podspec b/packages/cloud_functions/cloud_functions/macos/cloud_functions.podspec index 9523690d373a..4e568d28e4ed 100644 --- a/packages/cloud_functions/cloud_functions/macos/cloud_functions.podspec +++ b/packages/cloud_functions/cloud_functions/macos/cloud_functions.podspec @@ -41,8 +41,8 @@ Pod::Spec.new do |s| s.license = { :file => '../LICENSE' } s.authors = 'The Chromium Authors' s.source = { :path => '.' } - s.source_files = 'Classes/**/*.{h,m}' - s.public_header_files = 'Classes/*.h' + s.source_files = 'cloud_functions/Sources/cloud_functions/**/*.{h,m}' + s.public_header_files = 'cloud_functions/Sources/cloud_functions/include/*.h' s.platform = :osx, '10.13' # Flutter dependencies @@ -55,7 +55,7 @@ Pod::Spec.new do |s| s.static_framework = true s.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => "LIBRARY_VERSION=\\@\\\"#{library_version}\\\" LIBRARY_NAME=\\@\\\"flutter-fire-fn\\\"", + 'GCC_PREPROCESSOR_DEFINITIONS' => "LIBRARY_VERSION=\\\"#{library_version}\\\" LIBRARY_NAME=\\\"flutter-fire-fn\\\"", 'DEFINES_MODULE' => 'YES' } end diff --git a/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift new file mode 100644 index 000000000000..94ba37e78aed --- /dev/null +++ b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Package.swift @@ -0,0 +1,117 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +// Copyright 2024, the Chromium project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import Foundation +import PackageDescription + +enum ConfigurationError: Error { + case fileNotFound(String) + case parsingError(String) + case invalidFormat(String) +} + +let functionsDirectory = String(URL(string: #file)!.deletingLastPathComponent().absoluteString + .dropLast()) + +func loadFirebaseSDKVersion() throws -> String { + let firebaseCoreScriptPath = NSString.path(withComponents: [ + functionsDirectory, + "..", + "..", + "ios", + "generated_firebase_sdk_version.txt", + ]) + do { + let version = try String(contentsOfFile: firebaseCoreScriptPath, encoding: .utf8) + .trimmingCharacters(in: .whitespacesAndNewlines) + return version + } catch { + throw ConfigurationError + .fileNotFound("Error loading or parsing generated_firebase_sdk_version.txt: \(error)") + } +} + +func loadPubspecVersions() throws -> (packageVersion: String, firebaseCoreVersion: String) { + let pubspecPath = NSString.path(withComponents: [functionsDirectory, "..", "..", "pubspec.yaml"]) + do { + let yamlString = try String(contentsOfFile: pubspecPath, encoding: .utf8) + let lines = yamlString.split(separator: "\n") + + guard let packageVersionLine = lines.first(where: { $0.starts(with: "version:") }) else { + throw ConfigurationError.invalidFormat("No package version line found in pubspec.yaml") + } + var packageVersion = packageVersionLine.split(separator: ":")[1] + .trimmingCharacters(in: .whitespaces) + .replacingOccurrences(of: "+", with: "-") + packageVersion = packageVersion.replacingOccurrences(of: "^", with: "") + + guard let firebaseCoreVersionLine = lines.first(where: { $0.contains("firebase_core:") }) else { + throw ConfigurationError + .invalidFormat("No firebase_core dependency version line found in pubspec.yaml") + } + var firebaseCoreVersion = firebaseCoreVersionLine.split(separator: ":")[1] + .trimmingCharacters(in: .whitespaces) + firebaseCoreVersion = firebaseCoreVersion.replacingOccurrences(of: "^", with: "") + + return (packageVersion, firebaseCoreVersion) + } catch { + throw ConfigurationError.fileNotFound("Error loading or parsing pubspec.yaml: \(error)") + } +} + +let library_version: String +let firebase_sdk_version_string: String +let firebase_core_version_string: String +let shared_spm_tag = "-firebase-core-swift" + +do { + library_version = try loadPubspecVersions().packageVersion + firebase_sdk_version_string = try loadFirebaseSDKVersion() + firebase_core_version_string = try loadPubspecVersions().firebaseCoreVersion +} catch { + fatalError("Failed to load configuration: \(error)") +} + +guard let firebase_sdk_version = Version(firebase_sdk_version_string) else { + fatalError("Invalid Firebase SDK version: \(firebase_sdk_version_string)") +} + +guard let shared_spm_version = Version("\(firebase_core_version_string)\(shared_spm_tag)") else { + fatalError("Invalid firebase_core version: \(firebase_core_version_string)\(shared_spm_tag)") +} + +let package = Package( + name: "cloud_functions", + platforms: [ + .macOS("10.15"), + ], + products: [ + .library(name: "cloud-functions", targets: ["cloud_functions"]), + ], + dependencies: [ + .package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version), + .package(url: "https://github.com/firebase/flutterfire", exact: shared_spm_version), + ], + targets: [ + .target( + name: "cloud_functions", + dependencies: [ + .product(name: "FirebaseFunctions", package: "firebase-ios-sdk"), + // Wrapper dependency + .product(name: "firebase-core-shared", package: "flutterfire"), + ], + resources: [ + .process("Resources"), + ], + cSettings: [ + .headerSearchPath("include"), + .define("LIBRARY_VERSION", to: "\"\(library_version)\""), + .define("LIBRARY_NAME", to: "\"flutter-fire-fn\""), + ] + ), + ] +) diff --git a/packages/cloud_functions/cloud_functions/macos/cloud_functions/Sources/cloud_functions/FLTFirebaseFunctionsPlugin.m b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Sources/cloud_functions/FLTFirebaseFunctionsPlugin.m new file mode 120000 index 000000000000..6801f9eeb0ba --- /dev/null +++ b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Sources/cloud_functions/FLTFirebaseFunctionsPlugin.m @@ -0,0 +1 @@ +../../../../ios/cloud_functions/Sources/cloud_functions/FLTFirebaseFunctionsPlugin.m \ No newline at end of file diff --git a/packages/cloud_functions/cloud_functions/macos/Assets/.gitkeep b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Sources/cloud_functions/Resources/.gitkeep similarity index 100% rename from packages/cloud_functions/cloud_functions/macos/Assets/.gitkeep rename to packages/cloud_functions/cloud_functions/macos/cloud_functions/Sources/cloud_functions/Resources/.gitkeep diff --git a/packages/cloud_functions/cloud_functions/macos/cloud_functions/Sources/cloud_functions/include/FLTFirebaseFunctionsPlugin.h b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Sources/cloud_functions/include/FLTFirebaseFunctionsPlugin.h new file mode 120000 index 000000000000..55897cd68cde --- /dev/null +++ b/packages/cloud_functions/cloud_functions/macos/cloud_functions/Sources/cloud_functions/include/FLTFirebaseFunctionsPlugin.h @@ -0,0 +1 @@ +../../../../../ios/cloud_functions/Sources/cloud_functions/include/FLTFirebaseFunctionsPlugin.h \ No newline at end of file