diff --git a/bindings/dart/lib/src/server/bindings.dart b/bindings/dart/lib/src/server/bindings.dart index 6e3228164..92e145acf 100644 --- a/bindings/dart/lib/src/server/bindings.dart +++ b/bindings/dart/lib/src/server/bindings.dart @@ -71,13 +71,14 @@ DynamicLibrary _defaultLib() { path = env['OUISYNC_LIB']!; } else if (env.containsKey('FLUTTER_TEST')) { // guess the location of flutter's build output - final String build; if (Platform.isMacOS) { - build = join(dirname(Platform.script.toFilePath()), 'ouisync'); + // On macOS, native library is packaged as a framework in the Dart package directory + path = join('ouisync', 'bindings', 'dart', 'darwin', 'OuisyncService.framework', 'OuisyncService'); } else { + final String build; build = join('..', '..'); + path = join(build, 'target', kReleaseMode ? 'release' : 'debug', name); } - path = join(build, 'target', kReleaseMode ? 'release' : 'debug', name); } else if (Platform.isIOS || Platform.isMacOS) { // In the packaged app the native core is embedded as OuisyncService.framework // (a loose .dylib is rejected by App Store validation). dyld resolves this diff --git a/bindings/swift/OuisyncLib/Sources/generated/Api.swift b/bindings/swift/OuisyncLib/Sources/generated/Api.swift index 8c8d9f08d..a354f6351 100644 --- a/bindings/swift/OuisyncLib/Sources/generated/Api.swift +++ b/bindings/swift/OuisyncLib/Sources/generated/Api.swift @@ -177,7 +177,7 @@ public enum AccessChange { switch v { case .string(let name): switch name { - case "Disable": return .disable + case "Disable": return .some(.disable) default: return nil } case .map(let m) where m.count == 1: @@ -285,9 +285,9 @@ public enum PeerState { switch v { case .string(let name): switch name { - case "Known": return .known - case "Connecting": return .connecting - case "Handshaking": return .handshaking + case "Known": return .some(.known) + case "Connecting": return .some(.connecting) + case "Handshaking": return .some(.handshaking) default: return nil } case .map(let m) where m.count == 1: @@ -1215,8 +1215,8 @@ internal enum Response { switch v { case .string(let name): switch name { - case "None": return .none - case "Unit": return .unit + case "None": return .some(.none) + case "Unit": return .some(.unit) default: return nil } case .map(let m) where m.count == 1: diff --git a/bindings/swift/OuisyncLib/build-xcframework-macos.sh b/bindings/swift/OuisyncLib/build-xcframework-macos.sh index fe8e66a8f..d2c58145d 100755 --- a/bindings/swift/OuisyncLib/build-xcframework-macos.sh +++ b/bindings/swift/OuisyncLib/build-xcframework-macos.sh @@ -12,21 +12,30 @@ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../../" && pwd)" PACKAGE_DIR="$SCRIPT_DIR" -ARCH="$(uname -m)" -case "$ARCH" in - arm64) TARGET="aarch64-apple-darwin" ;; - x86_64) TARGET="x86_64-apple-darwin" ;; - *) echo "Unsupported arch: $ARCH"; exit 1 ;; -esac +# Build a universal (arm64 + x86_64) macOS static lib, not just the host arch — +# Xcode links a universal binary by default, so a single-arch xcframework here +# causes "Undefined symbols for architecture x86_64/arm64" at link time. +TARGETS=(aarch64-apple-darwin x86_64-apple-darwin) BUILD_DIR="$PROJECT_ROOT/target" -LIB="$BUILD_DIR/$TARGET/release/libouisync_service.a" INCLUDE="$BUILD_DIR/swift-include" XCF="$PACKAGE_DIR/output/OuisyncLibFFI.xcframework" -echo "==> Building ouisync-service for $TARGET..." cd "$PROJECT_ROOT" -"$CARGO" build --package ouisync-service --release --target "$TARGET" +# Match the Xcode project's MACOSX_DEPLOYMENT_TARGET (13.0), otherwise rustc/clang +# embed the host SDK's version and Xcode warns about linking newer object files. +export MACOSX_DEPLOYMENT_TARGET=13.0 +for TARGET in "${TARGETS[@]}"; do + echo "==> Building ouisync-service for $TARGET..." + "$CARGO" build --package ouisync-service --release --target "$TARGET" +done + +ARM64_LIB="$BUILD_DIR/aarch64-apple-darwin/release/libouisync_service.a" +X86_64_LIB="$BUILD_DIR/x86_64-apple-darwin/release/libouisync_service.a" +LIB="$BUILD_DIR/lipo-macos/libouisync_service.a" +mkdir -p "$(dirname "$LIB")" +echo "==> lipo macos: $ARM64_LIB $X86_64_LIB" +lipo -create "$ARM64_LIB" "$X86_64_LIB" -output "$LIB" echo "==> Generating bindings header..." mkdir -p "$INCLUDE" diff --git a/bindings/swift/OuisyncLib/build-xcframework.sh b/bindings/swift/OuisyncLib/build-xcframework.sh index 868492c1d..d0e2e0202 100755 --- a/bindings/swift/OuisyncLib/build-xcframework.sh +++ b/bindings/swift/OuisyncLib/build-xcframework.sh @@ -39,6 +39,10 @@ XCF="$PACKAGE_DIR/output/OuisyncLibFFI.xcframework" # ── 1. Build each enabled target ────────────────────────────────────────────── cd "$PROJECT_ROOT" +# Match the Xcode project's MACOSX_DEPLOYMENT_TARGET (13.0) for macOS targets, +# otherwise rustc/clang embed the host SDK's version and Xcode warns about +# linking newer object files into an app targeting 13.0. +export MACOSX_DEPLOYMENT_TARGET=13.0 for TARGET in "${TARGETS[@]}"; do echo "==> Building ouisync-service for $TARGET..." "$CARGO" build --package ouisync-service $RELEASE_FLAG --target "$TARGET" @@ -98,14 +102,14 @@ for TARGET in aarch64-apple-darwin x86_64-apple-darwin; do macos_libs+=("$BUILD_DIR/$TARGET/$CONFIGURATION/libouisync_service.a") fi done -add_slice macos "${macos_libs[@]}" +add_slice macos "${macos_libs[@]+"${macos_libs[@]}"}" # iOS device: arm64 only (no lipo needed) ios_libs=() if target_enabled aarch64-apple-ios; then ios_libs+=("$BUILD_DIR/aarch64-apple-ios/$CONFIGURATION/libouisync_service.a") fi -add_slice ios "${ios_libs[@]}" +add_slice ios "${ios_libs[@]+"${ios_libs[@]}"}" # iOS simulator: universal binary from arm64-sim + x86_64 sim_libs=() @@ -114,7 +118,7 @@ for TARGET in aarch64-apple-ios-sim x86_64-apple-ios; do sim_libs+=("$BUILD_DIR/$TARGET/$CONFIGURATION/libouisync_service.a") fi done -add_slice ios-simulator "${sim_libs[@]}" +add_slice ios-simulator "${sim_libs[@]+"${sim_libs[@]}"}" xcodebuild -create-xcframework "${XCF_PARAMS[@]}" -output "$XCF" echo "==> Done: $XCF" diff --git a/utils/bindgen/src/swift.rs b/utils/bindgen/src/swift.rs index 29798dfb7..cc4ed08a5 100644 --- a/utils/bindgen/src/swift.rs +++ b/utils/bindgen/src/swift.rs @@ -237,7 +237,7 @@ fn write_complex_enum_decode(out: &mut dyn Write, item: &ComplexEnum) -> Result< if matches!(variant.fields, Fields::Unit) { let case_name = format!("{}", AsLowerCamelCase(variant_name)); let msgpack_name = format!("{}", AsUpperCamelCase(variant_name)); - writeln!(out, "{I}{I}{I}case \"{msgpack_name}\": return .{case_name}")?; + writeln!(out, "{I}{I}{I}case \"{msgpack_name}\": return .some(.{case_name})")?; } } writeln!(out, "{I}{I}{I}default: return nil")?; @@ -878,7 +878,7 @@ fn write_response_enum(out: &mut dyn Write, item: &ComplexEnum) -> Result<()> { if matches!(variant.fields, Fields::Unit) { let case_name = format!("{}", AsLowerCamelCase(variant_name)); let msgpack_name = variant_name.clone(); - writeln!(out, "{I}{I}{I}case \"{msgpack_name}\": return .{case_name}")?; + writeln!(out, "{I}{I}{I}case \"{msgpack_name}\": return .some(.{case_name})")?; } } writeln!(out, "{I}{I}{I}default: return nil")?;