From 61e5bbae7a9bb19a1d533c1adfb89072bf06dfd6 Mon Sep 17 00:00:00 2001 From: Vitor Maciel <710828+vitormf@users.noreply.github.com> Date: Thu, 21 May 2026 23:56:28 +0100 Subject: [PATCH 1/3] feat(macos): add Swift Package Manager support --- macos/flutter_pty.podspec | 2 +- macos/{ => flutter_pty}/Classes/flutter_pty.c | 2 +- macos/flutter_pty/Package.swift | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) rename macos/{ => flutter_pty}/Classes/flutter_pty.c (76%) create mode 100644 macos/flutter_pty/Package.swift diff --git a/macos/flutter_pty.podspec b/macos/flutter_pty.podspec index ecb41cc..a452820 100644 --- a/macos/flutter_pty.podspec +++ b/macos/flutter_pty.podspec @@ -18,7 +18,7 @@ A new Flutter FFI plugin project. # paths, so Classes contains a forwarder C file that relatively imports # `../src/*` so that the C sources can be shared among all target platforms. s.source = { :path => '.' } - s.source_files = 'Classes/**/*' + s.source_files = 'flutter_pty/Classes/**/*' s.dependency 'FlutterMacOS' s.platform = :osx, '10.11' diff --git a/macos/Classes/flutter_pty.c b/macos/flutter_pty/Classes/flutter_pty.c similarity index 76% rename from macos/Classes/flutter_pty.c rename to macos/flutter_pty/Classes/flutter_pty.c index f2a8ed9..b44c0d3 100644 --- a/macos/Classes/flutter_pty.c +++ b/macos/flutter_pty/Classes/flutter_pty.c @@ -1,3 +1,3 @@ // Relative import to be able to reuse the C sources. // See the comment in ../{projectName}}.podspec for more information. -#include "../../src/flutter_pty.c" +#include "../../../src/flutter_pty.c" diff --git a/macos/flutter_pty/Package.swift b/macos/flutter_pty/Package.swift new file mode 100644 index 0000000..6c1bb67 --- /dev/null +++ b/macos/flutter_pty/Package.swift @@ -0,0 +1,19 @@ +// swift-tools-version: 5.9 +import PackageDescription + +let package = Package( + name: "flutter_pty", + platforms: [ + .macOS("10.14") + ], + products: [ + .library(name: "flutter-pty", targets: ["flutter_pty"]) + ], + targets: [ + .target( + name: "flutter_pty", + path: "Classes", + publicHeadersPath: "." + ) + ] +) From 1d2a088d93fc23c42c46f440d3c3e34f82f5704e Mon Sep 17 00:00:00 2001 From: Vitor Maciel <710828+vitormf@users.noreply.github.com> Date: Mon, 8 Jun 2026 11:23:47 +0100 Subject: [PATCH 2/3] fix(macos): declare SPM library as static to fix framework embedding Dynamic SPM products are transitive deps of the static FlutterGeneratedPluginSwiftPackage and Xcode does not auto-embed them, causing a crash at launch. Declaring type: .static links flutter_pty directly into the app binary with no embedding needed. --- macos/flutter_pty/Package.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/macos/flutter_pty/Package.swift b/macos/flutter_pty/Package.swift index 6c1bb67..e9bc14a 100644 --- a/macos/flutter_pty/Package.swift +++ b/macos/flutter_pty/Package.swift @@ -7,7 +7,7 @@ let package = Package( .macOS("10.14") ], products: [ - .library(name: "flutter-pty", targets: ["flutter_pty"]) + .library(name: "flutter-pty", type: .static, targets: ["flutter_pty"]) ], targets: [ .target( From b43e9cb6ad33bc5f4ca2f881d0847e356b82812c Mon Sep 17 00:00:00 2001 From: Vitor Maciel <710828+vitormf@users.noreply.github.com> Date: Mon, 8 Jun 2026 12:07:14 +0100 Subject: [PATCH 3/3] fix(macos): use DynamicLibrary.process() instead of explicit framework open DynamicLibrary.open('flutter_pty.framework/flutter_pty') requires the framework to be present in the app bundle. With SPM type: .static the code is linked into the app binary but no .framework is embedded, so dlopen fails at runtime. DynamicLibrary.process() resolves symbols from the already-loaded process image, which works for both SPM (static) and CocoaPods (framework already mapped before Dart starts). --- lib/flutter_pty.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/flutter_pty.dart b/lib/flutter_pty.dart index 0ba652c..c057fea 100644 --- a/lib/flutter_pty.dart +++ b/lib/flutter_pty.dart @@ -11,7 +11,11 @@ const _libName = 'flutter_pty'; final DynamicLibrary _dylib = () { if (Platform.isMacOS || Platform.isIOS) { - return DynamicLibrary.open('$_libName.framework/$_libName'); + // DynamicLibrary.process() resolves symbols from the already-loaded process + // image, which works for both SPM static linking and CocoaPods dynamic + // embedding (in the latter case the framework is already mapped into the + // process by the time any Dart code runs). + return DynamicLibrary.process(); } if (Platform.isAndroid || Platform.isLinux) { return DynamicLibrary.open('lib$_libName.so');