Skip to content

Commit 4e28103

Browse files
feat(core): support for using SPM (Swift Package Manager) (#12786)
Co-authored-by: Loïc Sharma <[email protected]>
1 parent b8f3869 commit 4e28103

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+389
-52
lines changed

.github/workflows/all_plugins.yaml

+17-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,23 @@ jobs:
122122
run: |
123123
melos exec -c 1 --scope="*example*" --dir-exists="web" -- \
124124
"flutter build web"
125-
125+
swift-integration:
126+
runs-on: macos-latest
127+
timeout-minutes: 10
128+
steps:
129+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
130+
- uses: subosito/flutter-action@2783a3f08e1baf891508463f8c6653c258246225
131+
with:
132+
# TODO - enabling swift is on `master` channel at the moment. Update when it's on `stable`
133+
channel: 'master'
134+
- uses: bluefireteam/melos-action@5a8367ec4b9942d712528c398ff3f996e03bc230
135+
with:
136+
melos-version: '5.3.0'
137+
- name: 'Swift Integration Setup'
138+
run: flutter config --enable-swift-package-manager
139+
- name: 'Build Apps with Swift Package Manager'
140+
run: ./.github/workflows/scripts/swift-integration.sh
141+
126142
test:
127143
runs-on: ubuntu-latest
128144
timeout-minutes: 30

.github/workflows/ios.yaml

+17
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,23 @@ jobs:
7474
- name: 'Install Tools'
7575
run: |
7676
sudo npm i -g firebase-tools
77+
- name: 'Free up space'
78+
run: |
79+
sudo rm -rf \
80+
/usr/local/share/.cache \
81+
/Users/runner/Library/Caches \
82+
/Users/runner/Library/Developer/Xcode/DerivedData \
83+
/Users/runner/Library/Developer/CoreSimulator/Caches \
84+
/opt/microsoft/msedge \
85+
/opt/microsoft/powershell \
86+
/opt/pipx \
87+
/usr/lib/mono \
88+
/usr/local/julia* \
89+
/usr/local/lib/android \
90+
/usr/local/share/chromium \
91+
/usr/local/share/powershell \
92+
/usr/share/dotnet
93+
df -h /
7794
- name: 'Build Application'
7895
working-directory: ${{ matrix.working_directory }}
7996
run: |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/bin/bash
2+
3+
set -e
4+
5+
# Just Core example has pure Swift capability at the moment
6+
7+
8+
# firebase_core iOS example
9+
10+
# Setup for SPM integration
11+
cd packages/firebase_core/firebase_core/example/ios
12+
rm Podfile
13+
pod deintegrate
14+
15+
# Run the flutter build command and capture the output and exit status
16+
flutter_output=$(flutter build ios --no-codesign)
17+
flutter_exit_code=$?
18+
19+
# Check if the flutter build command was successful
20+
if [[ $flutter_exit_code -ne 0 ]]; then
21+
echo "Flutter build failed with exit code $flutter_exit_code."
22+
exit 1
23+
fi
24+
25+
# Check the output for the specific string
26+
if [[ "$flutter_output" =~ "Running pod install" ]]; then
27+
exit 1
28+
else
29+
echo "Successfully built iOS project using Swift Package Manager."
30+
fi
31+
32+
# firebase_core macOS example
33+
34+
# Setup for SPM integration
35+
cd ../macos
36+
rm Podfile
37+
pod deintegrate
38+
39+
# Run the flutter build command and capture the output and exit status
40+
flutter_output=$(flutter build macos)
41+
flutter_exit_code=$?
42+
43+
# Check if the flutter build command was successful
44+
if [[ $flutter_exit_code -ne 0 ]]; then
45+
echo "Flutter build failed with exit code $flutter_exit_code."
46+
exit 1
47+
fi
48+
49+
# Check the output for the specific string
50+
if [[ "$flutter_output" =~ "Running pod install" ]]; then
51+
exit 1
52+
else
53+
echo "Successfully built macOS project using Swift Package Manager."
54+
exit 0
55+
fi

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ flutter_export_environment.sh
1515

1616
examples/all_plugins/pubspec.yaml
1717

18+
Package.resolved
1819
Podfile.lock
1920
Pods/
2021
.symlinks/
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"
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"

packages/firebase_core/firebase_core/example/ios/Runner.xcodeproj/project.pbxproj

+22-25
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
/* Begin PBXBuildFile section */
1010
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
1111
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
12+
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
1213
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
1314
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
1415
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
@@ -56,6 +57,7 @@
5657
isa = PBXFrameworksBuildPhase;
5758
buildActionMask = 2147483647;
5859
files = (
60+
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
5961
CC8B39E3ACF96AAA7558280C /* Pods_Runner.framework in Frameworks */,
6062
);
6163
runOnlyForDeploymentPostprocessing = 0;
@@ -149,13 +151,15 @@
149151
97C146EC1CF9000F007C117D /* Resources */,
150152
9705A1C41CF9048500538489 /* Embed Frameworks */,
151153
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
152-
FE9FCD1596DCB6AB2B208201 /* [CP] Embed Pods Frameworks */,
153154
);
154155
buildRules = (
155156
);
156157
dependencies = (
157158
);
158159
name = Runner;
160+
packageProductDependencies = (
161+
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */,
162+
);
159163
productName = Runner;
160164
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
161165
productType = "com.apple.product-type.application";
@@ -184,6 +188,9 @@
184188
Base,
185189
);
186190
mainGroup = 97C146E51CF9000F007C117D;
191+
packageReferences = (
192+
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */,
193+
);
187194
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
188195
projectDirPath = "";
189196
projectRoot = "";
@@ -261,30 +268,6 @@
261268
shellPath = /bin/sh;
262269
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
263270
};
264-
FE9FCD1596DCB6AB2B208201 /* [CP] Embed Pods Frameworks */ = {
265-
isa = PBXShellScriptBuildPhase;
266-
buildActionMask = 2147483647;
267-
files = (
268-
);
269-
inputPaths = (
270-
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh",
271-
"${BUILT_PRODUCTS_DIR}/FirebaseCore/FirebaseCore.framework",
272-
"${BUILT_PRODUCTS_DIR}/FirebaseCoreInternal/FirebaseCoreInternal.framework",
273-
"${BUILT_PRODUCTS_DIR}/GoogleUtilities/GoogleUtilities.framework",
274-
"${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework",
275-
);
276-
name = "[CP] Embed Pods Frameworks";
277-
outputPaths = (
278-
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCore.framework",
279-
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FirebaseCoreInternal.framework",
280-
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/GoogleUtilities.framework",
281-
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework",
282-
);
283-
runOnlyForDeploymentPostprocessing = 0;
284-
shellPath = /bin/sh;
285-
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
286-
showEnvVarsInLog = 0;
287-
};
288271
/* End PBXShellScriptBuildPhase section */
289272

290273
/* Begin PBXSourcesBuildPhase section */
@@ -580,6 +563,20 @@
580563
defaultConfigurationName = Release;
581564
};
582565
/* End XCConfigurationList section */
566+
567+
/* Begin XCLocalSwiftPackageReference section */
568+
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = {
569+
isa = XCLocalSwiftPackageReference;
570+
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
571+
};
572+
/* End XCLocalSwiftPackageReference section */
573+
574+
/* Begin XCSwiftPackageProductDependency section */
575+
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = {
576+
isa = XCSwiftPackageProductDependency;
577+
productName = FlutterGeneratedPluginSwiftPackage;
578+
};
579+
/* End XCSwiftPackageProductDependency section */
583580
};
584581
rootObject = 97C146E61CF9000F007C117D /* Project object */;
585582
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>

packages/firebase_core/firebase_core/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme

+18
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,24 @@
55
<BuildAction
66
parallelizeBuildables = "YES"
77
buildImplicitDependencies = "YES">
8+
<PreActions>
9+
<ExecutionAction
10+
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
11+
<ActionContent
12+
title = "Run Prepare Flutter Framework Script"
13+
scriptText = "/bin/sh &quot;$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh&quot; prepare&#10;">
14+
<EnvironmentBuildable>
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
18+
BuildableName = "Runner.app"
19+
BlueprintName = "Runner"
20+
ReferencedContainer = "container:Runner.xcodeproj">
21+
</BuildableReference>
22+
</EnvironmentBuildable>
23+
</ActionContent>
24+
</ExecutionAction>
25+
</PreActions>
826
<BuildActionEntries>
927
<BuildActionEntry
1028
buildForTesting = "YES"
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/firebase_core/firebase_core/ios/firebase_core.podspec

+3-3
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/**/*'
28-
s.public_header_files = 'Classes/**/*.h'
27+
s.source_files = 'firebase_core/Sources/firebase_core/**/*.{h,m}'
28+
s.public_header_files = 'firebase_core/Sources/firebase_core/include/**/*.h'
2929

3030
s.ios.deployment_target = '13.0'
3131

@@ -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-core\\\"",
40+
'GCC_PREPROCESSOR_DEFINITIONS' => "LIBRARY_VERSION=\\\"#{library_version}\\\" LIBRARY_NAME=\\\"flutter-fire-core\\\"",
4141
'DEFINES_MODULE' => 'YES'
4242
}
4343
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
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 iosRootDirectory = String(URL(string: #file)!.deletingLastPathComponent().absoluteString
18+
.dropLast())
19+
20+
func loadPubspecVersion() throws -> String {
21+
let pubspecPath = NSString.path(withComponents: [iosRootDirectory, "..", "..", "pubspec.yaml"])
22+
do {
23+
let yamlString = try String(contentsOfFile: pubspecPath, encoding: .utf8)
24+
if let versionLine = yamlString.split(separator: "\n")
25+
.first(where: { $0.starts(with: "version:") }) {
26+
let version = versionLine.split(separator: ":")[1].trimmingCharacters(in: .whitespaces)
27+
return version.replacingOccurrences(of: "+", with: "-")
28+
} else {
29+
throw ConfigurationError.invalidFormat("No version line found in pubspec.yaml")
30+
}
31+
} catch {
32+
throw ConfigurationError.fileNotFound("Error loading or parsing pubspec.yaml: \(error)")
33+
}
34+
}
35+
36+
func loadFirebaseSDKVersion() throws -> String {
37+
let firebaseCoreScriptPath = NSString.path(withComponents: [
38+
iosRootDirectory,
39+
"..",
40+
"..",
41+
"..",
42+
"firebase_core",
43+
"ios",
44+
"firebase_sdk_version.rb",
45+
])
46+
do {
47+
let content = try String(contentsOfFile: firebaseCoreScriptPath, encoding: .utf8)
48+
let pattern = #"def firebase_sdk_version!\(\)\n\s+'([^']+)'\nend"#
49+
if let regex = try? NSRegularExpression(pattern: pattern, options: []),
50+
let match = regex.firstMatch(
51+
in: content,
52+
range: NSRange(content.startIndex..., in: content)
53+
) {
54+
if let versionRange = Range(match.range(at: 1), in: content) {
55+
return String(content[versionRange])
56+
} else {
57+
throw ConfigurationError.invalidFormat("Invalid format in firebase_sdk_version.rb")
58+
}
59+
} else {
60+
throw ConfigurationError.parsingError("No match found in firebase_sdk_version.rb")
61+
}
62+
} catch {
63+
throw ConfigurationError
64+
.fileNotFound("Error loading or parsing firebase_sdk_version.rb: \(error)")
65+
}
66+
}
67+
68+
let library_version: String
69+
let firebase_sdk_version_string: String
70+
71+
do {
72+
library_version = try loadPubspecVersion()
73+
firebase_sdk_version_string = try loadFirebaseSDKVersion()
74+
} catch {
75+
fatalError("Failed to load configuration: \(error)")
76+
}
77+
78+
guard let firebase_sdk_version = Version(firebase_sdk_version_string) else {
79+
fatalError("Invalid Firebase SDK version: \(firebase_sdk_version_string)")
80+
}
81+
82+
let package = Package(
83+
name: "firebase_core",
84+
platforms: [
85+
.iOS("13.0"),
86+
],
87+
products: [
88+
.library(name: "firebase-core", targets: ["firebase_core"]),
89+
],
90+
dependencies: [
91+
.package(url: "https://github.com/firebase/firebase-ios-sdk", from: firebase_sdk_version),
92+
],
93+
targets: [
94+
.target(
95+
name: "firebase_core",
96+
dependencies: [
97+
// No product for firebase-core so we pull in the smallest one
98+
.product(name: "FirebaseInstallations", package: "firebase-ios-sdk"),
99+
],
100+
resources: [
101+
.process("Resources"),
102+
],
103+
cSettings: [
104+
.headerSearchPath("include/firebase_core"),
105+
.define("LIBRARY_VERSION", to: "\"\(library_version)\""),
106+
.define("LIBRARY_NAME", to: "\"flutter-fire-core\""),
107+
]
108+
),
109+
]
110+
)

0 commit comments

Comments
 (0)