diff --git a/.github/workflows/pr_check_macos.yml b/.github/workflows/pr_check_macos.yml index 6cb2384d..a293a7fd 100644 --- a/.github/workflows/pr_check_macos.yml +++ b/.github/workflows/pr_check_macos.yml @@ -54,6 +54,9 @@ jobs: working-directory: zstandard_macos run: flutter analyze + - name: Verify version-resolved SwiftPM and Release FFI symbols + run: python3 scripts/test_swiftpm_package.py + - name: Run package tests working-directory: zstandard_macos run: flutter test diff --git a/.github/workflows/release_workflow.yml b/.github/workflows/release_workflow.yml index 3aa56924..1d588ac6 100644 --- a/.github/workflows/release_workflow.yml +++ b/.github/workflows/release_workflow.yml @@ -669,6 +669,9 @@ jobs: else flutter config --no-enable-swift-package-manager fi + - name: Verify version-resolved SwiftPM and Release FFI symbols + if: matrix.platform == 'macos' && matrix.dependency_manager == 'swiftpm' + run: python3 scripts/test_swiftpm_package.py - name: Get dependencies and build Apple example env: PLATFORM: ${{ matrix.platform }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ab96875..03d9a140 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.5.6 - Release patch fix versioned SwiftPM resolution 188 + +- Fix SwiftPM resolution of the native package through immutable exact-version dependencies by removing unsafe linker flags (issue #188, PR #189). +- Preserve all ten Dart FFI entry points in iOS/macOS SwiftPM Release builds through plugin registration and a retained native symbol table. +- Add a version-resolved SwiftPM Release regression with dynamic symbol lookup and one-shot/streaming roundtrips to PR and release validation. +- Minimum supported SDKs remain Dart `^3.12.0` and Flutter `>=3.44.0` (published 1.5.0 used Dart `^3.6.0` and Flutter `>=3.3.0`). CI uses Flutter 3.47.2. + ## 1.5.5 - Release fix Android native sources from the Windows Pub cache - Fix Android native-source discovery for consumers using the Windows Pub cache, including paths with spaces, Unicode and correctly resolved package-config URIs. diff --git a/Package.swift b/Package.swift index 881908fb..c4374472 100644 --- a/Package.swift +++ b/Package.swift @@ -13,7 +13,7 @@ let package = Package( products: [ .library( name: "zstandard-native", - targets: ["zstandard_native"] + targets: ["zstandard_ffi"] ), ], targets: [ @@ -36,24 +36,14 @@ let package = Package( // internal zstd translation units consume these declarations. .define("ZSTD_STATIC_LINKING_ONLY"), .define("ZSTD_DISABLE_ASM"), - ], - // Flutter's SwiftPM integration links this target statically into - // the application. Keep the FFI entry points in the final image - // even when release dead-code stripping is enabled. - linkerSettings: [ - .unsafeFlags([ - "-Xlinker", "-u", "-Xlinker", "_ZSTD_compress", - "-Xlinker", "-u", "-Xlinker", "_ZSTD_decompress", - "-Xlinker", "-u", "-Xlinker", "_ZSTD_compressBound", - "-Xlinker", "-u", "-Xlinker", "_ZSTD_isError", - "-Xlinker", "-u", "-Xlinker", "_ZSTD_getFrameContentSize", - "-Xlinker", "-u", "-Xlinker", "_ZSTD_createDStream", - "-Xlinker", "-u", "-Xlinker", "_ZSTD_initDStream", - "-Xlinker", "-u", "-Xlinker", "_ZSTD_decompressStream", - "-Xlinker", "-u", "-Xlinker", "_ZSTD_freeDStream", - "-Xlinker", "-u", "-Xlinker", "_ZSTD_DStreamOutSize", - ]) ] ), + // Keep the Dart-only entry points without unsafe dependency flags. + .target( + name: "zstandard_ffi", + dependencies: ["zstandard_native"], + path: "zstandard_native/src/swiftpm", + publicHeadersPath: "include" + ), ] ) diff --git a/docs/architecture/ffi-implementation.md b/docs/architecture/ffi-implementation.md index 601d5fba..83799b87 100644 --- a/docs/architecture/ffi-implementation.md +++ b/docs/architecture/ffi-implementation.md @@ -41,8 +41,9 @@ application. Repository checkouts may use the adjacent package; published consumers resolve it through Dart's package configuration. Build scripts never select an arbitrary matching Pub-cache directory. -SwiftPM force-loads the complete FFI symbol surface because its static linker -could otherwise remove Dart-only entry points. CocoaPods builds the equivalent +SwiftPM plugin registration links a C shim with a retained table of the ten +FFI entry points, preventing its static linker from removing Dart-only symbols +without using unsafe package flags. CocoaPods builds the equivalent C set in an embedded framework. CLI tests open every required symbol; runtime roundtrips exercise the same codec. diff --git a/docs/development/apple-dependencies.md b/docs/development/apple-dependencies.md index ab24b4c5..36177b09 100644 --- a/docs/development/apple-dependencies.md +++ b/docs/development/apple-dependencies.md @@ -32,7 +32,7 @@ The iOS and macOS manifests depend on the repository-level SwiftPM facade: ```swift .package( url: "https://github.com/vypdev/zstandard.git", - exact: "1.5.0" + exact: "1.5.5" ) ``` @@ -42,7 +42,12 @@ mutable branches are never used in a published manifest. The SwiftPM target deliberately excludes unsupported or unnecessary upstream directories and disables assembly for the Apple build. It also preserves the -FFI entry points when release dead-code stripping is enabled. The public +FFI entry points when release dead-code stripping is enabled. The product +includes a project-owned C shim in `zstandard_native/src/swiftpm/`. SwiftPM +plugin registration calls `ZstandardNativeRetainSymbols`, pulling in a +`used` table of the ten Dart FFI entry points. This keeps version-based +resolution compatible with SwiftPM without `unsafeFlags`; the upstream C +sources and CocoaPods implementation remain unchanged. The public headers in `zstandard_native/src/zstd/include/` are thin forwarding headers; the actual headers and all C implementation files remain in the canonical directory. @@ -54,6 +59,13 @@ native integration tests, not only by manifest parsing. ## Verification policy +Run `python3 scripts/test_swiftpm_package.py` on macOS for the standalone +regression. It creates an isolated local Git dependency with a semantic version +tag, builds a consumer in Release with dead stripping, resolves every required +symbol using `dlsym`, and exercises one-shot and streaming roundtrips. A local +path or revision dependency alone would not detect the unsafe-flags regression. + + Every Apple change must be tested through both dependency managers on the ARM64 self-hosted macOS runner: diff --git a/scripts/test_swiftpm_package.py b/scripts/test_swiftpm_package.py new file mode 100644 index 00000000..f60ca0a2 --- /dev/null +++ b/scripts/test_swiftpm_package.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +"""Build a version-resolved SwiftPM consumer and check Release FFI symbols. + +The dependency is an isolated, locally tagged copy of the candidate source. +A path or revision dependency would bypass SwiftPM's unsafe-flags check. +""" +from pathlib import Path +import platform +import shutil +import subprocess +import tempfile + +ROOT = Path(__file__).resolve().parents[1] + +PROBE = r'''#include +#include +#include +#include +#include + +#define REQUIRE(condition) do { \ + if (!(condition)) { \ + fprintf(stderr, "Failed: %s\n", #condition); \ + return 1; \ + } \ +} while (0) + +#define LOAD(name) \ + __typeof__(&name) name##Fn = (__typeof__(&name))dlsym(RTLD_DEFAULT, #name); \ + REQUIRE(name##Fn != NULL) + +int main(void) { + ZstandardNativeRetainSymbols(); + LOAD(ZSTD_compress); + LOAD(ZSTD_decompress); + LOAD(ZSTD_compressBound); + LOAD(ZSTD_isError); + LOAD(ZSTD_getFrameContentSize); + LOAD(ZSTD_createDStream); + LOAD(ZSTD_initDStream); + LOAD(ZSTD_decompressStream); + LOAD(ZSTD_freeDStream); + LOAD(ZSTD_DStreamOutSize); + + const char input[] = "Version-resolved SwiftPM FFI roundtrip"; + char compressed[256]; + char output[256]; + REQUIRE(ZSTD_compressBoundFn(sizeof(input)) <= sizeof(compressed)); + size_t size = ZSTD_compressFn(compressed, sizeof(compressed), input, sizeof(input), 3); + REQUIRE(!ZSTD_isErrorFn(size)); + REQUIRE(ZSTD_getFrameContentSizeFn(compressed, size) == sizeof(input)); + REQUIRE(ZSTD_decompressFn(output, sizeof(output), compressed, size) == sizeof(input)); + REQUIRE(memcmp(input, output, sizeof(input)) == 0); + + ZSTD_DStream *stream = ZSTD_createDStreamFn(); + REQUIRE(stream != NULL); + REQUIRE(!ZSTD_isErrorFn(ZSTD_initDStreamFn(stream))); + REQUIRE(ZSTD_DStreamOutSizeFn() > 0); + ZSTD_inBuffer source = { compressed, size, 0 }; + ZSTD_outBuffer destination = { output, sizeof(output), 0 }; + REQUIRE(ZSTD_decompressStreamFn(stream, &destination, &source) == 0); + REQUIRE(source.pos == size && destination.pos == sizeof(input)); + REQUIRE(memcmp(input, output, sizeof(input)) == 0); + REQUIRE(!ZSTD_isErrorFn(ZSTD_freeDStreamFn(stream))); + puts("All 10 FFI symbols survive Release dead stripping; one-shot and streaming roundtrips pass."); + return 0; +} +''' + + +def run(*command, cwd): + subprocess.run(command, cwd=cwd, check=True, timeout=300) + + +def main(): + if platform.system() != 'Darwin': + raise SystemExit('This Apple linker regression test requires macOS and Swift.') + with tempfile.TemporaryDirectory(prefix='zstandard-swiftpm-') as folder: + root = Path(folder) + dependency = root / 'zstandard' + dependency.mkdir() + shutil.copyfile(ROOT / 'Package.swift', dependency / 'Package.swift') + shutil.copytree(ROOT / 'zstandard_native/src', dependency / 'zstandard_native/src') + run('git', 'init', '-q', cwd=dependency) + run('git', 'add', '.', cwd=dependency) + run('git', '-c', 'user.name=SwiftPM regression', '-c', + 'user.email=swiftpm-test@example.invalid', 'commit', '-qm', 'Candidate fixture', cwd=dependency) + run('git', 'tag', '1.0.0', cwd=dependency) + + consumer = root / 'consumer' + (consumer / 'Sources/Probe').mkdir(parents=True) + (consumer / 'Sources/Probe/main.c').write_text(PROBE) + (consumer / 'Package.swift').write_text('''// swift-tools-version: 5.9 +import PackageDescription +let package = Package( + name: "Probe", + platforms: [.macOS(.v10_15)], + dependencies: [.package(url: "''' + dependency.as_uri() + '''", exact: "1.0.0")], + targets: [.executableTarget(name: "Probe", dependencies: [ + .product(name: "zstandard-native", package: "zstandard") + ])] +) +''') + build = root / 'build' + run('swift', 'build', '--configuration', 'release', '--scratch-path', str(build), + '--cache-path', str(root / 'cache'), '-Xlinker', '-dead_strip', cwd=consumer) + run(str(build / 'release/Probe'), cwd=consumer) + + +if __name__ == '__main__': + main() diff --git a/zstandard/CHANGELOG.md b/zstandard/CHANGELOG.md index 0ab96875..03d9a140 100644 --- a/zstandard/CHANGELOG.md +++ b/zstandard/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.5.6 - Release patch fix versioned SwiftPM resolution 188 + +- Fix SwiftPM resolution of the native package through immutable exact-version dependencies by removing unsafe linker flags (issue #188, PR #189). +- Preserve all ten Dart FFI entry points in iOS/macOS SwiftPM Release builds through plugin registration and a retained native symbol table. +- Add a version-resolved SwiftPM Release regression with dynamic symbol lookup and one-shot/streaming roundtrips to PR and release validation. +- Minimum supported SDKs remain Dart `^3.12.0` and Flutter `>=3.44.0` (published 1.5.0 used Dart `^3.6.0` and Flutter `>=3.3.0`). CI uses Flutter 3.47.2. + ## 1.5.5 - Release fix Android native sources from the Windows Pub cache - Fix Android native-source discovery for consumers using the Windows Pub cache, including paths with spaces, Unicode and correctly resolved package-config URIs. diff --git a/zstandard/pubspec.yaml b/zstandard/pubspec.yaml index 586cc302..93a92660 100644 --- a/zstandard/pubspec.yaml +++ b/zstandard/pubspec.yaml @@ -1,6 +1,6 @@ name: zstandard description: "Flutter plugin for fast Zstandard compression and decompression across native and WebAssembly platforms." -version: 1.5.5 +version: 1.5.6 homepage: https://vyp.dev repository: https://github.com/vypdev/zstandard @@ -28,13 +28,13 @@ flutter: dependencies: flutter: sdk: flutter - zstandard_android: ^1.5.5 - zstandard_ios: ^1.5.5 - zstandard_linux: ^1.5.5 - zstandard_macos: ^1.5.5 - zstandard_platform_interface: ^1.5.5 - zstandard_web: ^1.5.5 - zstandard_windows: ^1.5.5 + zstandard_android: ^1.5.6 + zstandard_ios: ^1.5.6 + zstandard_linux: ^1.5.6 + zstandard_macos: ^1.5.6 + zstandard_platform_interface: ^1.5.6 + zstandard_web: ^1.5.6 + zstandard_windows: ^1.5.6 dev_dependencies: flutter_lints: ^6.0.0 diff --git a/zstandard_android/CHANGELOG.md b/zstandard_android/CHANGELOG.md index 0ab96875..03d9a140 100644 --- a/zstandard_android/CHANGELOG.md +++ b/zstandard_android/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.5.6 - Release patch fix versioned SwiftPM resolution 188 + +- Fix SwiftPM resolution of the native package through immutable exact-version dependencies by removing unsafe linker flags (issue #188, PR #189). +- Preserve all ten Dart FFI entry points in iOS/macOS SwiftPM Release builds through plugin registration and a retained native symbol table. +- Add a version-resolved SwiftPM Release regression with dynamic symbol lookup and one-shot/streaming roundtrips to PR and release validation. +- Minimum supported SDKs remain Dart `^3.12.0` and Flutter `>=3.44.0` (published 1.5.0 used Dart `^3.6.0` and Flutter `>=3.3.0`). CI uses Flutter 3.47.2. + ## 1.5.5 - Release fix Android native sources from the Windows Pub cache - Fix Android native-source discovery for consumers using the Windows Pub cache, including paths with spaces, Unicode and correctly resolved package-config URIs. diff --git a/zstandard_android/pubspec.yaml b/zstandard_android/pubspec.yaml index bb849d47..5263695b 100644 --- a/zstandard_android/pubspec.yaml +++ b/zstandard_android/pubspec.yaml @@ -1,6 +1,6 @@ name: zstandard_android description: Android implementation of the Zstandard compression plugin for Flutter applications. -version: 1.5.5 +version: 1.5.6 homepage: https://vyp.dev repository: https://github.com/vypdev/zstandard/tree/master/zstandard_android @@ -12,8 +12,8 @@ environment: dependencies: flutter: sdk: flutter - zstandard_platform_interface: ^1.5.5 - zstandard_native: ^1.5.5 + zstandard_platform_interface: ^1.5.6 + zstandard_native: ^1.5.6 ffi: ^2.2.0 dev_dependencies: diff --git a/zstandard_cli/CHANGELOG.md b/zstandard_cli/CHANGELOG.md index 0ab96875..03d9a140 100644 --- a/zstandard_cli/CHANGELOG.md +++ b/zstandard_cli/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.5.6 - Release patch fix versioned SwiftPM resolution 188 + +- Fix SwiftPM resolution of the native package through immutable exact-version dependencies by removing unsafe linker flags (issue #188, PR #189). +- Preserve all ten Dart FFI entry points in iOS/macOS SwiftPM Release builds through plugin registration and a retained native symbol table. +- Add a version-resolved SwiftPM Release regression with dynamic symbol lookup and one-shot/streaming roundtrips to PR and release validation. +- Minimum supported SDKs remain Dart `^3.12.0` and Flutter `>=3.44.0` (published 1.5.0 used Dart `^3.6.0` and Flutter `>=3.3.0`). CI uses Flutter 3.47.2. + ## 1.5.5 - Release fix Android native sources from the Windows Pub cache - Fix Android native-source discovery for consumers using the Windows Pub cache, including paths with spaces, Unicode and correctly resolved package-config URIs. diff --git a/zstandard_cli/lib/src/bin/libzstandard_macos.dylib b/zstandard_cli/lib/src/bin/libzstandard_macos.dylib index 6cfb1e6c..05a07bb7 100755 Binary files a/zstandard_cli/lib/src/bin/libzstandard_macos.dylib and b/zstandard_cli/lib/src/bin/libzstandard_macos.dylib differ diff --git a/zstandard_cli/lib/src/bin/zstandard_windows_arm64.dll b/zstandard_cli/lib/src/bin/zstandard_windows_arm64.dll index b8403a64..1cd72c27 100644 Binary files a/zstandard_cli/lib/src/bin/zstandard_windows_arm64.dll and b/zstandard_cli/lib/src/bin/zstandard_windows_arm64.dll differ diff --git a/zstandard_cli/lib/src/bin/zstandard_windows_x64.dll b/zstandard_cli/lib/src/bin/zstandard_windows_x64.dll index a6d9a1f3..ec867f7b 100644 Binary files a/zstandard_cli/lib/src/bin/zstandard_windows_x64.dll and b/zstandard_cli/lib/src/bin/zstandard_windows_x64.dll differ diff --git a/zstandard_cli/lib/src/cli_runner.dart b/zstandard_cli/lib/src/cli_runner.dart index 9a27036f..86936680 100644 --- a/zstandard_cli/lib/src/cli_runner.dart +++ b/zstandard_cli/lib/src/cli_runner.dart @@ -8,7 +8,7 @@ import 'utils/constants.dart'; import 'zstandard_cli_base.dart'; /// Version of the command-line interface. -const String zstandardCliVersion = '1.5.5'; +const String zstandardCliVersion = '1.5.6'; /// Runs the compression command and returns a process exit code. Future runCompressCommand( diff --git a/zstandard_cli/pubspec.yaml b/zstandard_cli/pubspec.yaml index 3b03aefc..1fc86b71 100644 --- a/zstandard_cli/pubspec.yaml +++ b/zstandard_cli/pubspec.yaml @@ -1,6 +1,6 @@ name: zstandard_cli description: Command-line interface for compressing and decompressing files with Zstandard. -version: 1.5.5 +version: 1.5.6 executables: zstandard-compress: compress @@ -16,7 +16,7 @@ dependencies: ffi: ^2.2.0 path: ^1.9.1 platform: ^3.1.6 - zstandard_native: ^1.5.5 + zstandard_native: ^1.5.6 dev_dependencies: coverage: ^1.15.0 diff --git a/zstandard_ios/CHANGELOG.md b/zstandard_ios/CHANGELOG.md index 0ab96875..03d9a140 100644 --- a/zstandard_ios/CHANGELOG.md +++ b/zstandard_ios/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.5.6 - Release patch fix versioned SwiftPM resolution 188 + +- Fix SwiftPM resolution of the native package through immutable exact-version dependencies by removing unsafe linker flags (issue #188, PR #189). +- Preserve all ten Dart FFI entry points in iOS/macOS SwiftPM Release builds through plugin registration and a retained native symbol table. +- Add a version-resolved SwiftPM Release regression with dynamic symbol lookup and one-shot/streaming roundtrips to PR and release validation. +- Minimum supported SDKs remain Dart `^3.12.0` and Flutter `>=3.44.0` (published 1.5.0 used Dart `^3.6.0` and Flutter `>=3.3.0`). CI uses Flutter 3.47.2. + ## 1.5.5 - Release fix Android native sources from the Windows Pub cache - Fix Android native-source discovery for consumers using the Windows Pub cache, including paths with spaces, Unicode and correctly resolved package-config URIs. diff --git a/zstandard_ios/ios/zstandard_ios.podspec b/zstandard_ios/ios/zstandard_ios.podspec index 60aaad28..419a9af9 100644 --- a/zstandard_ios/ios/zstandard_ios.podspec +++ b/zstandard_ios/ios/zstandard_ios.podspec @@ -5,7 +5,7 @@ Pod::Spec.new do |s| s.cocoapods_version = '>= 1.11.0' # for script_phase :before_headers s.name = 'zstandard_ios' - s.version = '1.5.5' + s.version = '1.5.6' s.summary = 'iOS implementation of the Zstandard Flutter plugin.' s.description = <<-DESC Native Zstandard compression and bounded decompression for Flutter on iOS. diff --git a/zstandard_ios/ios/zstandard_ios/Package.swift b/zstandard_ios/ios/zstandard_ios/Package.swift index c36ae80c..b7b63587 100644 --- a/zstandard_ios/ios/zstandard_ios/Package.swift +++ b/zstandard_ios/ios/zstandard_ios/Package.swift @@ -10,7 +10,7 @@ let nativePackageDependency: Package.Dependency = { // Match the immutable repository tag carrying this plugin release. return .package( url: "https://github.com/vypdev/zstandard.git", - exact: "1.5.5" + exact: "1.5.6" ) }() diff --git a/zstandard_ios/ios/zstandard_ios/Sources/zstandard_ios/ZstandardIosPlugin.swift b/zstandard_ios/ios/zstandard_ios/Sources/zstandard_ios/ZstandardIosPlugin.swift index 2fa7cccc..8b62bbbb 100644 --- a/zstandard_ios/ios/zstandard_ios/Sources/zstandard_ios/ZstandardIosPlugin.swift +++ b/zstandard_ios/ios/zstandard_ios/Sources/zstandard_ios/ZstandardIosPlugin.swift @@ -1,8 +1,14 @@ import Flutter import UIKit +#if SWIFT_PACKAGE +import zstandard_ffi +#endif public class ZstandardIosPlugin: NSObject, FlutterPlugin { public static func register(with registrar: FlutterPluginRegistrar) { + #if SWIFT_PACKAGE + ZstandardNativeRetainSymbols() + #endif let channel = FlutterMethodChannel(name: "plugins.flutter.io/zstandard", binaryMessenger: registrar.messenger()) let instance = ZstandardIosPlugin() registrar.addMethodCallDelegate(instance, channel: channel) diff --git a/zstandard_ios/pubspec.yaml b/zstandard_ios/pubspec.yaml index d0499d36..4c357423 100644 --- a/zstandard_ios/pubspec.yaml +++ b/zstandard_ios/pubspec.yaml @@ -1,6 +1,6 @@ name: zstandard_ios description: iOS implementation of the Zstandard compression plugin for Flutter applications. -version: 1.5.5 +version: 1.5.6 homepage: https://vyp.dev repository: https://github.com/vypdev/zstandard/tree/master/zstandard_ios @@ -12,8 +12,8 @@ environment: dependencies: flutter: sdk: flutter - zstandard_platform_interface: ^1.5.5 - zstandard_native: ^1.5.5 + zstandard_platform_interface: ^1.5.6 + zstandard_native: ^1.5.6 ffi: ^2.2.0 dev_dependencies: diff --git a/zstandard_ios/test/spm_package_test.dart b/zstandard_ios/test/spm_package_test.dart index f76bdf25..34f2004b 100644 --- a/zstandard_ios/test/spm_package_test.dart +++ b/zstandard_ios/test/spm_package_test.dart @@ -27,18 +27,8 @@ void main() { if (rootManifest.existsSync()) { final rootContents = rootManifest.readAsStringSync(); expect(rootContents, contains('path: "zstandard_native/src/zstd"')); - for (final symbol in [ - '_ZSTD_compress', - '_ZSTD_decompress', - '_ZSTD_isError', - '_ZSTD_createDStream', - '_ZSTD_initDStream', - '_ZSTD_decompressStream', - '_ZSTD_freeDStream', - '_ZSTD_DStreamOutSize', - ]) { - expect(rootContents, contains(symbol)); - } + expect(rootContents, isNot(contains('unsafeFlags'))); + expect(rootContents, contains('targets: ["zstandard_ffi"]')); } }); } diff --git a/zstandard_linux/CHANGELOG.md b/zstandard_linux/CHANGELOG.md index 0ab96875..03d9a140 100644 --- a/zstandard_linux/CHANGELOG.md +++ b/zstandard_linux/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.5.6 - Release patch fix versioned SwiftPM resolution 188 + +- Fix SwiftPM resolution of the native package through immutable exact-version dependencies by removing unsafe linker flags (issue #188, PR #189). +- Preserve all ten Dart FFI entry points in iOS/macOS SwiftPM Release builds through plugin registration and a retained native symbol table. +- Add a version-resolved SwiftPM Release regression with dynamic symbol lookup and one-shot/streaming roundtrips to PR and release validation. +- Minimum supported SDKs remain Dart `^3.12.0` and Flutter `>=3.44.0` (published 1.5.0 used Dart `^3.6.0` and Flutter `>=3.3.0`). CI uses Flutter 3.47.2. + ## 1.5.5 - Release fix Android native sources from the Windows Pub cache - Fix Android native-source discovery for consumers using the Windows Pub cache, including paths with spaces, Unicode and correctly resolved package-config URIs. diff --git a/zstandard_linux/pubspec.yaml b/zstandard_linux/pubspec.yaml index 48f437d7..e5bb7434 100644 --- a/zstandard_linux/pubspec.yaml +++ b/zstandard_linux/pubspec.yaml @@ -1,6 +1,6 @@ name: zstandard_linux description: Linux implementation of the Zstandard compression plugin for Flutter applications. -version: 1.5.5 +version: 1.5.6 homepage: https://vyp.dev repository: https://github.com/vypdev/zstandard/tree/master/zstandard_linux @@ -12,8 +12,8 @@ environment: dependencies: flutter: sdk: flutter - zstandard_platform_interface: ^1.5.5 - zstandard_native: ^1.5.5 + zstandard_platform_interface: ^1.5.6 + zstandard_native: ^1.5.6 ffi: ^2.2.0 dev_dependencies: diff --git a/zstandard_macos/CHANGELOG.md b/zstandard_macos/CHANGELOG.md index 0ab96875..03d9a140 100644 --- a/zstandard_macos/CHANGELOG.md +++ b/zstandard_macos/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.5.6 - Release patch fix versioned SwiftPM resolution 188 + +- Fix SwiftPM resolution of the native package through immutable exact-version dependencies by removing unsafe linker flags (issue #188, PR #189). +- Preserve all ten Dart FFI entry points in iOS/macOS SwiftPM Release builds through plugin registration and a retained native symbol table. +- Add a version-resolved SwiftPM Release regression with dynamic symbol lookup and one-shot/streaming roundtrips to PR and release validation. +- Minimum supported SDKs remain Dart `^3.12.0` and Flutter `>=3.44.0` (published 1.5.0 used Dart `^3.6.0` and Flutter `>=3.3.0`). CI uses Flutter 3.47.2. + ## 1.5.5 - Release fix Android native sources from the Windows Pub cache - Fix Android native-source discovery for consumers using the Windows Pub cache, including paths with spaces, Unicode and correctly resolved package-config URIs. diff --git a/zstandard_macos/macos/zstandard_macos.podspec b/zstandard_macos/macos/zstandard_macos.podspec index 59d78ab4..459bf664 100644 --- a/zstandard_macos/macos/zstandard_macos.podspec +++ b/zstandard_macos/macos/zstandard_macos.podspec @@ -5,7 +5,7 @@ Pod::Spec.new do |s| s.cocoapods_version = '>= 1.11.0' # for script_phase :before_headers s.name = 'zstandard_macos' - s.version = '1.5.5' + s.version = '1.5.6' s.summary = 'macOS implementation of the Zstandard Flutter plugin.' s.description = <<-DESC Native Zstandard compression and bounded decompression for Flutter on macOS. diff --git a/zstandard_macos/macos/zstandard_macos/Package.swift b/zstandard_macos/macos/zstandard_macos/Package.swift index 115e45da..acb05e95 100644 --- a/zstandard_macos/macos/zstandard_macos/Package.swift +++ b/zstandard_macos/macos/zstandard_macos/Package.swift @@ -10,7 +10,7 @@ let nativePackageDependency: Package.Dependency = { // Match the immutable repository tag carrying this plugin release. return .package( url: "https://github.com/vypdev/zstandard.git", - exact: "1.5.5" + exact: "1.5.6" ) }() diff --git a/zstandard_macos/macos/zstandard_macos/Sources/zstandard_macos/ZstandardMacosPlugin.swift b/zstandard_macos/macos/zstandard_macos/Sources/zstandard_macos/ZstandardMacosPlugin.swift index 678c538a..adc71ed8 100644 --- a/zstandard_macos/macos/zstandard_macos/Sources/zstandard_macos/ZstandardMacosPlugin.swift +++ b/zstandard_macos/macos/zstandard_macos/Sources/zstandard_macos/ZstandardMacosPlugin.swift @@ -1,8 +1,14 @@ import Cocoa import FlutterMacOS +#if SWIFT_PACKAGE +import zstandard_ffi +#endif public class ZstandardMacosPlugin: NSObject, FlutterPlugin { public static func register(with registrar: FlutterPluginRegistrar) { + #if SWIFT_PACKAGE + ZstandardNativeRetainSymbols() + #endif let channel = FlutterMethodChannel(name: "plugins.flutter.io/zstandard", binaryMessenger: registrar.messenger) let instance = ZstandardMacosPlugin() registrar.addMethodCallDelegate(instance, channel: channel) diff --git a/zstandard_macos/pubspec.yaml b/zstandard_macos/pubspec.yaml index 22a37b82..521a000b 100644 --- a/zstandard_macos/pubspec.yaml +++ b/zstandard_macos/pubspec.yaml @@ -1,6 +1,6 @@ name: zstandard_macos description: macOS implementation of the Zstandard compression plugin for Flutter applications. -version: 1.5.5 +version: 1.5.6 homepage: https://vyp.dev repository: https://github.com/vypdev/zstandard/tree/master/zstandard_macos @@ -12,8 +12,8 @@ environment: dependencies: flutter: sdk: flutter - zstandard_platform_interface: ^1.5.5 - zstandard_native: ^1.5.5 + zstandard_platform_interface: ^1.5.6 + zstandard_native: ^1.5.6 ffi: ^2.2.0 dev_dependencies: diff --git a/zstandard_macos/test/spm_package_test.dart b/zstandard_macos/test/spm_package_test.dart index e7995772..1525d57c 100644 --- a/zstandard_macos/test/spm_package_test.dart +++ b/zstandard_macos/test/spm_package_test.dart @@ -28,18 +28,8 @@ void main() { if (rootManifest.existsSync()) { final rootContents = rootManifest.readAsStringSync(); expect(rootContents, contains('path: "zstandard_native/src/zstd"')); - for (final symbol in [ - '_ZSTD_compress', - '_ZSTD_decompress', - '_ZSTD_isError', - '_ZSTD_createDStream', - '_ZSTD_initDStream', - '_ZSTD_decompressStream', - '_ZSTD_freeDStream', - '_ZSTD_DStreamOutSize', - ]) { - expect(rootContents, contains(symbol)); - } + expect(rootContents, isNot(contains('unsafeFlags'))); + expect(rootContents, contains('targets: ["zstandard_ffi"]')); } }); } diff --git a/zstandard_native/CHANGELOG.md b/zstandard_native/CHANGELOG.md index 0ab96875..03d9a140 100644 --- a/zstandard_native/CHANGELOG.md +++ b/zstandard_native/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.5.6 - Release patch fix versioned SwiftPM resolution 188 + +- Fix SwiftPM resolution of the native package through immutable exact-version dependencies by removing unsafe linker flags (issue #188, PR #189). +- Preserve all ten Dart FFI entry points in iOS/macOS SwiftPM Release builds through plugin registration and a retained native symbol table. +- Add a version-resolved SwiftPM Release regression with dynamic symbol lookup and one-shot/streaming roundtrips to PR and release validation. +- Minimum supported SDKs remain Dart `^3.12.0` and Flutter `>=3.44.0` (published 1.5.0 used Dart `^3.6.0` and Flutter `>=3.3.0`). CI uses Flutter 3.47.2. + ## 1.5.5 - Release fix Android native sources from the Windows Pub cache - Fix Android native-source discovery for consumers using the Windows Pub cache, including paths with spaces, Unicode and correctly resolved package-config URIs. diff --git a/zstandard_native/pubspec.yaml b/zstandard_native/pubspec.yaml index 20002e87..e972cba1 100644 --- a/zstandard_native/pubspec.yaml +++ b/zstandard_native/pubspec.yaml @@ -1,6 +1,6 @@ name: zstandard_native description: Native zstd C sources and FFI bindings for the zstandard Flutter plugin. -version: 1.5.5 +version: 1.5.6 homepage: https://vyp.dev repository: https://github.com/vypdev/zstandard/tree/master/zstandard_native diff --git a/zstandard_native/src/swiftpm/include/zstandard_ffi.h b/zstandard_native/src/swiftpm/include/zstandard_ffi.h new file mode 100644 index 00000000..14daeef5 --- /dev/null +++ b/zstandard_native/src/swiftpm/include/zstandard_ffi.h @@ -0,0 +1,15 @@ +#ifndef ZSTANDARD_FFI_H +#define ZSTANDARD_FFI_H + +#ifdef __cplusplus +extern "C" { +#endif + +// Call during SwiftPM plugin registration to link the Dart FFI entry points. +void ZstandardNativeRetainSymbols(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/zstandard_native/src/swiftpm/zstandard_ffi.c b/zstandard_native/src/swiftpm/zstandard_ffi.c new file mode 100644 index 00000000..82859644 --- /dev/null +++ b/zstandard_native/src/swiftpm/zstandard_ffi.c @@ -0,0 +1,23 @@ +#include "zstandard_ffi.h" +#include + +// Mach-O's used attribute protects this table and its references from Release +// dead stripping. Registration pulls this object into the statically linked app. +// Keep this project-owned shim outside the vendored upstream zstd source tree. +__attribute__((used)) +static void (*const zstandard_ffi_symbols[])(void) = { + (void (*)(void))ZSTD_compress, + (void (*)(void))ZSTD_decompress, + (void (*)(void))ZSTD_compressBound, + (void (*)(void))ZSTD_isError, + (void (*)(void))ZSTD_getFrameContentSize, + (void (*)(void))ZSTD_createDStream, + (void (*)(void))ZSTD_initDStream, + (void (*)(void))ZSTD_decompressStream, + (void (*)(void))ZSTD_freeDStream, + (void (*)(void))ZSTD_DStreamOutSize, +}; + +void ZstandardNativeRetainSymbols(void) { + // Linking this object retains the used symbol table; no zstd call is needed. +} diff --git a/zstandard_platform_interface/CHANGELOG.md b/zstandard_platform_interface/CHANGELOG.md index 0ab96875..03d9a140 100644 --- a/zstandard_platform_interface/CHANGELOG.md +++ b/zstandard_platform_interface/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.5.6 - Release patch fix versioned SwiftPM resolution 188 + +- Fix SwiftPM resolution of the native package through immutable exact-version dependencies by removing unsafe linker flags (issue #188, PR #189). +- Preserve all ten Dart FFI entry points in iOS/macOS SwiftPM Release builds through plugin registration and a retained native symbol table. +- Add a version-resolved SwiftPM Release regression with dynamic symbol lookup and one-shot/streaming roundtrips to PR and release validation. +- Minimum supported SDKs remain Dart `^3.12.0` and Flutter `>=3.44.0` (published 1.5.0 used Dart `^3.6.0` and Flutter `>=3.3.0`). CI uses Flutter 3.47.2. + ## 1.5.5 - Release fix Android native sources from the Windows Pub cache - Fix Android native-source discovery for consumers using the Windows Pub cache, including paths with spaces, Unicode and correctly resolved package-config URIs. diff --git a/zstandard_platform_interface/pubspec.yaml b/zstandard_platform_interface/pubspec.yaml index e9811910..f9a89367 100644 --- a/zstandard_platform_interface/pubspec.yaml +++ b/zstandard_platform_interface/pubspec.yaml @@ -1,6 +1,6 @@ name: zstandard_platform_interface description: A common platform interface for the zstandard plugin. -version: 1.5.5 +version: 1.5.6 homepage: https://vyp.dev repository: https://github.com/vypdev/zstandard/tree/master/zstandard_platform_interface diff --git a/zstandard_web/CHANGELOG.md b/zstandard_web/CHANGELOG.md index 0ab96875..03d9a140 100644 --- a/zstandard_web/CHANGELOG.md +++ b/zstandard_web/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.5.6 - Release patch fix versioned SwiftPM resolution 188 + +- Fix SwiftPM resolution of the native package through immutable exact-version dependencies by removing unsafe linker flags (issue #188, PR #189). +- Preserve all ten Dart FFI entry points in iOS/macOS SwiftPM Release builds through plugin registration and a retained native symbol table. +- Add a version-resolved SwiftPM Release regression with dynamic symbol lookup and one-shot/streaming roundtrips to PR and release validation. +- Minimum supported SDKs remain Dart `^3.12.0` and Flutter `>=3.44.0` (published 1.5.0 used Dart `^3.6.0` and Flutter `>=3.3.0`). CI uses Flutter 3.47.2. + ## 1.5.5 - Release fix Android native sources from the Windows Pub cache - Fix Android native-source discovery for consumers using the Windows Pub cache, including paths with spaces, Unicode and correctly resolved package-config URIs. diff --git a/zstandard_web/pubspec.yaml b/zstandard_web/pubspec.yaml index db3446af..5821307c 100644 --- a/zstandard_web/pubspec.yaml +++ b/zstandard_web/pubspec.yaml @@ -1,6 +1,6 @@ name: zstandard_web description: Web implementation of the Zstandard compression plugin for Flutter applications. -version: 1.5.5 +version: 1.5.6 homepage: https://vyp.dev repository: https://github.com/vypdev/zstandard/tree/master/zstandard_web @@ -22,7 +22,7 @@ dependencies: sdk: flutter flutter_web_plugins: sdk: flutter - zstandard_platform_interface: ^1.5.5 + zstandard_platform_interface: ^1.5.6 web: ^1.1.1 dev_dependencies: diff --git a/zstandard_windows/CHANGELOG.md b/zstandard_windows/CHANGELOG.md index 0ab96875..03d9a140 100644 --- a/zstandard_windows/CHANGELOG.md +++ b/zstandard_windows/CHANGELOG.md @@ -1,3 +1,10 @@ +## 1.5.6 - Release patch fix versioned SwiftPM resolution 188 + +- Fix SwiftPM resolution of the native package through immutable exact-version dependencies by removing unsafe linker flags (issue #188, PR #189). +- Preserve all ten Dart FFI entry points in iOS/macOS SwiftPM Release builds through plugin registration and a retained native symbol table. +- Add a version-resolved SwiftPM Release regression with dynamic symbol lookup and one-shot/streaming roundtrips to PR and release validation. +- Minimum supported SDKs remain Dart `^3.12.0` and Flutter `>=3.44.0` (published 1.5.0 used Dart `^3.6.0` and Flutter `>=3.3.0`). CI uses Flutter 3.47.2. + ## 1.5.5 - Release fix Android native sources from the Windows Pub cache - Fix Android native-source discovery for consumers using the Windows Pub cache, including paths with spaces, Unicode and correctly resolved package-config URIs. diff --git a/zstandard_windows/pubspec.yaml b/zstandard_windows/pubspec.yaml index 80c9f242..07fd6699 100644 --- a/zstandard_windows/pubspec.yaml +++ b/zstandard_windows/pubspec.yaml @@ -1,6 +1,6 @@ name: zstandard_windows description: Windows implementation of the Zstandard compression plugin for Flutter applications. -version: 1.5.5 +version: 1.5.6 homepage: https://vyp.dev repository: https://github.com/vypdev/zstandard/tree/master/zstandard_windows @@ -12,8 +12,8 @@ environment: dependencies: flutter: sdk: flutter - zstandard_platform_interface: ^1.5.5 - zstandard_native: ^1.5.5 + zstandard_platform_interface: ^1.5.6 + zstandard_native: ^1.5.6 ffi: ^2.2.0 dev_dependencies: