Skip to content

Commit dc0dee2

Browse files
russellwheatleyLyokone
authored andcommitted
feat(functions): Swift Package Manager support (#16770)
1 parent b538d8a commit dc0dee2

File tree

20 files changed

+262
-16
lines changed

20 files changed

+262
-16
lines changed

.github/workflows/all_plugins.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ jobs:
124124
"flutter build web"
125125
swift-integration:
126126
runs-on: macos-latest
127-
timeout-minutes: 30
127+
timeout-minutes: 40
128128
steps:
129129
- uses: actions/checkout@d632683dd7b4114ad314bca15554477dd762a938
130130
- uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225

.github/workflows/scripts/swift-integration.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ void main() async {
1010
await buildSwiftExampleApp('ios', 'cloud_firestore');
1111
await buildSwiftExampleApp('macos', 'firebase_core');
1212
await buildSwiftExampleApp('macos', 'cloud_firestore');
13+
await buildSwiftExampleApp('ios', 'cloud_functions');
14+
await buildSwiftExampleApp('macos', 'cloud_functions');
1315
}
1416

1517
Future<void> deleteFirstLine(String filePath) async {

packages/cloud_functions/cloud_functions/example/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
*.swp
66
.DS_Store
77
.atom/
8+
.build/
89
.buildlog/
910
.history
1011
.svn/
12+
.swiftpm/
1113
migrate_working_dir/
1214

1315
# IntelliJ related
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
1+
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
22
#include "Generated.xcconfig"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
1+
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
22
#include "Generated.xcconfig"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
1+
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
22
#include "ephemeral/Flutter-Generated.xcconfig"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
1+
#include? "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
22
#include "ephemeral/Flutter-Generated.xcconfig"

packages/cloud_functions/cloud_functions/ios/cloud_functions.podspec

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ Pod::Spec.new do |s|
2424
s.license = { :file => '../LICENSE' }
2525
s.authors = 'The Chromium Authors'
2626
s.source = { :path => '.' }
27-
s.source_files = 'Classes/**/*.{h,m}'
28-
s.public_header_files = 'Classes/*.h'
27+
s.source_files = 'cloud_functions/Sources/cloud_functions/**/*.{h,m}'
28+
s.public_header_files = 'cloud_functions/Sources/cloud_functions/include/*.h'
2929
s.ios.deployment_target = '13.0'
3030

3131
# Flutter dependencies
@@ -37,7 +37,7 @@ Pod::Spec.new do |s|
3737

3838
s.static_framework = true
3939
s.pod_target_xcconfig = {
40-
'GCC_PREPROCESSOR_DEFINITIONS' => "LIBRARY_VERSION=\\@\\\"#{library_version}\\\" LIBRARY_NAME=\\@\\\"flutter-fire-fn\\\"",
40+
'GCC_PREPROCESSOR_DEFINITIONS' => "LIBRARY_VERSION=\\\"#{library_version}\\\" LIBRARY_NAME=\\\"flutter-fire-fn\\\"",
4141
'DEFINES_MODULE' => 'YES'
4242
}
4343
end
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// swift-tools-version: 5.9
2+
// The swift-tools-version declares the minimum version of Swift required to build this package.
3+
4+
// Copyright 2024, the Chromium project authors. Please see the AUTHORS file
5+
// for details. All rights reserved. Use of this source code is governed by a
6+
// BSD-style license that can be found in the LICENSE file.
7+
8+
import Foundation
9+
import PackageDescription
10+
11+
enum ConfigurationError: Error {
12+
case fileNotFound(String)
13+
case parsingError(String)
14+
case invalidFormat(String)
15+
}
16+
17+
let functionsDirectory = String(URL(string: #file)!.deletingLastPathComponent().absoluteString
18+
.dropLast())
19+
20+
func loadFirebaseSDKVersion() throws -> String {
21+
let firebaseCoreScriptPath = NSString.path(withComponents: [
22+
functionsDirectory,
23+
"..",
24+
"generated_firebase_sdk_version.txt",
25+
])
26+
do {
27+
let version = try String(contentsOfFile: firebaseCoreScriptPath, encoding: .utf8)
28+
.trimmingCharacters(in: .whitespacesAndNewlines)
29+
return version
30+
} catch {
31+
throw ConfigurationError
32+
.fileNotFound("Error loading or parsing generated_firebase_sdk_version.txt: \(error)")
33+
}
34+
}
35+
36+
func loadPubspecVersions() throws -> (packageVersion: String, firebaseCoreVersion: String) {
37+
let pubspecPath = NSString.path(withComponents: [functionsDirectory, "..", "..", "pubspec.yaml"])
38+
do {
39+
let yamlString = try String(contentsOfFile: pubspecPath, encoding: .utf8)
40+
let lines = yamlString.split(separator: "\n")
41+
42+
guard let packageVersionLine = lines.first(where: { $0.starts(with: "version:") }) else {
43+
throw ConfigurationError.invalidFormat("No package version line found in pubspec.yaml")
44+
}
45+
var packageVersion = packageVersionLine.split(separator: ":")[1]
46+
.trimmingCharacters(in: .whitespaces)
47+
.replacingOccurrences(of: "+", with: "-")
48+
packageVersion = packageVersion.replacingOccurrences(of: "^", with: "")
49+
50+
guard let firebaseCoreVersionLine = lines.first(where: { $0.contains("firebase_core:") }) else {
51+
throw ConfigurationError
52+
.invalidFormat("No firebase_core dependency version line found in pubspec.yaml")
53+
}
54+
var firebaseCoreVersion = firebaseCoreVersionLine.split(separator: ":")[1]
55+
.trimmingCharacters(in: .whitespaces)
56+
firebaseCoreVersion = firebaseCoreVersion.replacingOccurrences(of: "^", with: "")
57+
58+
return (packageVersion, firebaseCoreVersion)
59+
} catch {
60+
throw ConfigurationError.fileNotFound("Error loading or parsing pubspec.yaml: \(error)")
61+
}
62+
}
63+
64+
let library_version: String
65+
let firebase_sdk_version_string: String
66+
let firebase_core_version_string: String
67+
let shared_spm_tag = "-firebase-core-swift"
68+
69+
do {
70+
library_version = try loadPubspecVersions().packageVersion
71+
firebase_sdk_version_string = try loadFirebaseSDKVersion()
72+
firebase_core_version_string = try loadPubspecVersions().firebaseCoreVersion
73+
} catch {
74+
fatalError("Failed to load configuration: \(error)")
75+
}
76+
77+
guard let firebase_sdk_version = Version(firebase_sdk_version_string) else {
78+
fatalError("Invalid Firebase SDK version: \(firebase_sdk_version_string)")
79+
}
80+
81+
guard let shared_spm_version = Version("\(firebase_core_version_string)\(shared_spm_tag)") else {
82+
fatalError("Invalid firebase_core version: \(firebase_core_version_string)\(shared_spm_tag)")
83+
}
84+
85+
let package = Package(
86+
name: "cloud_functions",
87+
platforms: [
88+
.iOS("13.0"),
89+
],
90+
products: [
91+
.library(name: "cloud-functions", targets: ["cloud_functions"]),
92+
],
93+
dependencies: [
94+
.package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version),
95+
.package(url: "https://github.com/firebase/flutterfire", exact: shared_spm_version),
96+
],
97+
targets: [
98+
.target(
99+
name: "cloud_functions",
100+
dependencies: [
101+
.product(name: "FirebaseFunctions", package: "firebase-ios-sdk"),
102+
// Wrapper dependency
103+
.product(name: "firebase-core-shared", package: "flutterfire"),
104+
],
105+
resources: [
106+
.process("Resources"),
107+
],
108+
cSettings: [
109+
.headerSearchPath("include"),
110+
.define("LIBRARY_VERSION", to: "\"\(library_version)\""),
111+
.define("LIBRARY_NAME", to: "\"flutter-fire-fn\""),
112+
]
113+
),
114+
]
115+
)

packages/cloud_functions/cloud_functions/ios/Classes/FLTFirebaseFunctionsPlugin.m renamed to packages/cloud_functions/cloud_functions/ios/cloud_functions/Sources/cloud_functions/FLTFirebaseFunctionsPlugin.m

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5-
#import "FLTFirebaseFunctionsPlugin.h"
5+
#import "include/FLTFirebaseFunctionsPlugin.h"
66

77
@import FirebaseFunctions;
8+
#if __has_include(<firebase_core/FLTFirebasePluginRegistry.h>)
89
#import <firebase_core/FLTFirebasePluginRegistry.h>
10+
#else
11+
#import <FLTFirebasePluginRegistry.h>
12+
#endif
913

1014
NSString *const kFLTFirebaseFunctionsChannelName = @"plugins.flutter.io/firebase_functions";
1115

@@ -175,11 +179,11 @@ - (NSDictionary *_Nonnull)pluginConstantsForFIRApp:(FIRApp *)firebase_app {
175179
}
176180

177181
- (NSString *_Nonnull)firebaseLibraryName {
178-
return LIBRARY_NAME;
182+
return @LIBRARY_NAME;
179183
}
180184

181185
- (NSString *_Nonnull)firebaseLibraryVersion {
182-
return LIBRARY_VERSION;
186+
return @LIBRARY_VERSION;
183187
}
184188

185189
- (NSString *_Nonnull)flutterChannelName {

0 commit comments

Comments
 (0)