From 781921002bfc4219f7bd3743ce5b88a0c44379d8 Mon Sep 17 00:00:00 2001 From: LiJianying Date: Thu, 12 Nov 2026 23:11:54 +0800 Subject: [PATCH 1/3] Build the Swift binding on Linux and Windows --- bindings/swift/Package.swift | 119 +++++++++++++++--- bindings/swift/Sources/CGTK3/module.modulemap | 5 + bindings/swift/Sources/CGTK3/shim.h | 1 + .../Sources/CNativeAPI/WindowsManifest.c | 14 +++ bindings/swift/Sources/CX11/module.modulemap | 5 + bindings/swift/Sources/CX11/shim.h | 4 + bindings/swift/Sources/CXI/module.modulemap | 5 + bindings/swift/Sources/CXI/shim.h | 1 + 8 files changed, 135 insertions(+), 19 deletions(-) create mode 100644 bindings/swift/Sources/CGTK3/module.modulemap create mode 100644 bindings/swift/Sources/CGTK3/shim.h create mode 100644 bindings/swift/Sources/CNativeAPI/WindowsManifest.c create mode 100644 bindings/swift/Sources/CX11/module.modulemap create mode 100644 bindings/swift/Sources/CX11/shim.h create mode 100644 bindings/swift/Sources/CXI/module.modulemap create mode 100644 bindings/swift/Sources/CXI/shim.h diff --git a/bindings/swift/Package.swift b/bindings/swift/Package.swift index d48154f..8ba3e8a 100644 --- a/bindings/swift/Package.swift +++ b/bindings/swift/Package.swift @@ -4,26 +4,113 @@ import PackageDescription // This source-checkout package compiles the workspace's `core` submodule // directly (Sources/CNativeAPI/core is a symlink), so it needs no CMake step -// and no separate native library at runtime. The package targets macOS, the -// platform this binding is built and tested on; the core also supports Windows -// and Linux, where SwiftPM would need each platform's own setup. +// and no separate native library at runtime. It builds on macOS, Linux and +// Windows; each host compiles only its own platform layer. +// +// The SwiftPM target rules below keep the platform split honest: +// * macOS links the Apple frameworks and compiles platform/macos. +// * Linux compiles platform/linux and gets its include/link flags from the +// gtk+-3.0, x11 and xi pkg-config modules through systemLibrary targets. +// pkg-config is used instead of unsafeFlags so the package stays usable as +// a SwiftPM dependency. +// * Windows compiles platform/windows (without the optional WinUI 3 layer) +// and links the Win32 libraries the core imports. WindowsManifest.c makes +// the linker embed the Common Controls v6 dependency the core needs. +// // `core/build` only exists after someone configures the core with CMake; the // package never needs it, but exclude it when present so SwiftPM does not // discover CMake's own sources. var excludes = [ - // Other platforms' implementations; the host's are compiled below. - "core/src/platform/android", - "core/src/platform/ios", - "core/src/platform/linux", - "core/src/platform/ohos", - "core/src/platform/wasm", - "core/src/platform/windows", // Not part of the library. "core/tests", "core/examples", "core/docs", "core/cmake", ] + +let platformExcludes: [String] +let nativeDependencies: [Target.Dependency] +let nativeLinkerSettings: [LinkerSetting] +let systemTargets: [Target] + +#if os(macOS) +platformExcludes = ["android", "ios", "linux", "ohos", "wasm", "windows"] +nativeDependencies = [] +nativeLinkerSettings = [ + .linkedFramework("Cocoa"), + .linkedFramework("CoreServices"), + .linkedFramework("QuartzCore"), + .linkedFramework("Carbon"), + .linkedFramework("IOKit"), + .linkedFramework("ServiceManagement"), +] +systemTargets = [] +#elseif os(Linux) +platformExcludes = ["android", "ios", "macos", "ohos", "wasm", "windows"] +nativeDependencies = ["CGTK3", "CX11", "CXI"] +nativeLinkerSettings = [ + .linkedLibrary("pthread"), + .linkedLibrary("dl"), + .linkedLibrary("m"), +] +systemTargets = [ + .systemLibrary( + name: "CGTK3", + path: "Sources/CGTK3", + pkgConfig: "gtk+-3.0", + providers: [.apt(["libgtk-3-dev"]), .yum(["gtk3-devel"])] + ), + .systemLibrary( + name: "CX11", + path: "Sources/CX11", + pkgConfig: "x11", + providers: [.apt(["libx11-dev"]), .yum(["libX11-devel"])] + ), + .systemLibrary( + name: "CXI", + path: "Sources/CXI", + pkgConfig: "xi", + providers: [.apt(["libxi-dev"]), .yum(["libXi-devel"])] + ), +] +#elseif os(Windows) +platformExcludes = ["android", "ios", "linux", "macos", "ohos", "wasm"] +nativeDependencies = [] +nativeLinkerSettings = [ + .linkedLibrary("user32"), + .linkedLibrary("shell32"), + .linkedLibrary("ole32"), + .linkedLibrary("oleaut32"), + .linkedLibrary("uuid"), + .linkedLibrary("comctl32"), + .linkedLibrary("dwmapi"), + .linkedLibrary("gdi32"), + .linkedLibrary("gdiplus"), + .linkedLibrary("crypt32"), + .linkedLibrary("advapi32"), + .linkedLibrary("version"), + .linkedLibrary("psapi"), + .linkedLibrary("shlwapi"), +] +systemTargets = [] +// WinUI 3 is opt-in in the core's CMake build; the Swift package ships the +// plain Win32 backend, so leave the XAML layer out. +excludes += [ + "core/src/platform/windows/menu_winui3_windows.cpp", + "core/src/platform/windows/message_dialog_winui3_windows.cpp", + "core/src/platform/windows/view_winui3_windows.cpp", + "core/src/platform/windows/window_winui3_windows.cpp", + "core/src/platform/windows/winui3_runtime_windows.cpp", +] +#else +platformExcludes = ["android", "ios", "linux", "macos", "ohos", "wasm", "windows"] +nativeDependencies = [] +nativeLinkerSettings = [] +systemTargets = [] +#endif + +excludes += platformExcludes.map { "core/src/platform/\($0)" } + let packageDirectory = URL(fileURLWithPath: #filePath).deletingLastPathComponent() if FileManager.default.fileExists( atPath: packageDirectory.appendingPathComponent("Sources/CNativeAPI/core/build").path @@ -37,20 +124,14 @@ let package = Package( products: [ .library(name: "NativeAPI", targets: ["NativeAPI"]) ], - targets: [ + targets: systemTargets + [ .target( name: "CNativeAPI", + dependencies: nativeDependencies, path: "Sources/CNativeAPI", exclude: excludes, publicHeadersPath: "include", - linkerSettings: [ - .linkedFramework("Cocoa"), - .linkedFramework("CoreServices"), - .linkedFramework("QuartzCore"), - .linkedFramework("Carbon"), - .linkedFramework("IOKit"), - .linkedFramework("ServiceManagement"), - ] + linkerSettings: nativeLinkerSettings ), .target(name: "NativeAPI", dependencies: ["CNativeAPI"], path: "Sources/NativeAPI"), .testTarget( diff --git a/bindings/swift/Sources/CGTK3/module.modulemap b/bindings/swift/Sources/CGTK3/module.modulemap new file mode 100644 index 0000000..34e0b00 --- /dev/null +++ b/bindings/swift/Sources/CGTK3/module.modulemap @@ -0,0 +1,5 @@ +module CGTK3 [system] { + header "shim.h" + link "gtk-3" + export * +} diff --git a/bindings/swift/Sources/CGTK3/shim.h b/bindings/swift/Sources/CGTK3/shim.h new file mode 100644 index 0000000..3e4515b --- /dev/null +++ b/bindings/swift/Sources/CGTK3/shim.h @@ -0,0 +1 @@ +#include diff --git a/bindings/swift/Sources/CNativeAPI/WindowsManifest.c b/bindings/swift/Sources/CNativeAPI/WindowsManifest.c new file mode 100644 index 0000000..cd7b5eb --- /dev/null +++ b/bindings/swift/Sources/CNativeAPI/WindowsManifest.c @@ -0,0 +1,14 @@ +/* + * The core's Win32 view layer imports GetWindowSubclass(), which only + * ComCtl32 v6 exports. Without a manifest that asks for v6, the loader binds + * the executable to the v5 DLL and terminates with STATUS_ENTRYPOINT_NOT_FOUND + * before main() runs. Embed the dependency from an object file so every + * executable that links this package gets it, with no manifest flag in + * Package.swift (which would have to be an unsafeFlag). + */ +#if defined(_WIN32) +#pragma comment(linker, "/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") +#endif + +/* Keep the translation unit non-empty on every compiler. */ +int nativeapi_swift_windows_manifest_anchor(void) { return 0; } diff --git a/bindings/swift/Sources/CX11/module.modulemap b/bindings/swift/Sources/CX11/module.modulemap new file mode 100644 index 0000000..9949304 --- /dev/null +++ b/bindings/swift/Sources/CX11/module.modulemap @@ -0,0 +1,5 @@ +module CX11 [system] { + header "shim.h" + link "X11" + export * +} diff --git a/bindings/swift/Sources/CX11/shim.h b/bindings/swift/Sources/CX11/shim.h new file mode 100644 index 0000000..e03d3c2 --- /dev/null +++ b/bindings/swift/Sources/CX11/shim.h @@ -0,0 +1,4 @@ +#include +#include +#include +#include diff --git a/bindings/swift/Sources/CXI/module.modulemap b/bindings/swift/Sources/CXI/module.modulemap new file mode 100644 index 0000000..72dbab3 --- /dev/null +++ b/bindings/swift/Sources/CXI/module.modulemap @@ -0,0 +1,5 @@ +module CXI [system] { + header "shim.h" + link "Xi" + export * +} diff --git a/bindings/swift/Sources/CXI/shim.h b/bindings/swift/Sources/CXI/shim.h new file mode 100644 index 0000000..1ea15fe --- /dev/null +++ b/bindings/swift/Sources/CXI/shim.h @@ -0,0 +1 @@ +#include From df0c1adae544e4a9f28d14e1c29bda0fa4e8b9ab Mon Sep 17 00:00:00 2001 From: LiJianying Date: Thu, 12 Nov 2026 23:54:05 +0800 Subject: [PATCH 2/3] Generate platform-neutral raw values in Swift enums A C enum without a fixed underlying type is UInt32 on Darwin/Linux and Int32 on Windows. numericCast lets the generated Swift compile on all three. --- bindings/swift/Sources/NativeAPI/Application.swift | 2 +- bindings/swift/Sources/NativeAPI/Dialog.swift | 2 +- bindings/swift/Sources/NativeAPI/Display.swift | 2 +- bindings/swift/Sources/NativeAPI/DragSource.swift | 2 +- bindings/swift/Sources/NativeAPI/FileDialog.swift | 4 ++-- .../Sources/NativeAPI/Foundation/Keyboard.swift | 4 ++-- bindings/swift/Sources/NativeAPI/Menu.swift | 6 +++--- .../swift/Sources/NativeAPI/MessageDialog.swift | 2 +- bindings/swift/Sources/NativeAPI/Placement.swift | 2 +- .../Sources/NativeAPI/PositioningStrategy.swift | 2 +- bindings/swift/Sources/NativeAPI/Shortcut.swift | 2 +- bindings/swift/Sources/NativeAPI/TrayIcon.swift | 4 ++-- bindings/swift/Sources/NativeAPI/UrlOpener.swift | 2 +- bindings/swift/Sources/NativeAPI/View.swift | 8 ++++---- bindings/swift/Sources/NativeAPI/Window.swift | 14 +++++++------- tools/codegen/bindings/src/swift.rs | 6 +++--- 16 files changed, 32 insertions(+), 32 deletions(-) diff --git a/bindings/swift/Sources/NativeAPI/Application.swift b/bindings/swift/Sources/NativeAPI/Application.swift index 24643c3..7e522d6 100644 --- a/bindings/swift/Sources/NativeAPI/Application.swift +++ b/bindings/swift/Sources/NativeAPI/Application.swift @@ -20,7 +20,7 @@ public enum Brightness: CInt { } var raw: native_brightness_t { - native_brightness_t(rawValue: UInt32(self.rawValue)) + native_brightness_t(rawValue: numericCast(self.rawValue)) } } diff --git a/bindings/swift/Sources/NativeAPI/Dialog.swift b/bindings/swift/Sources/NativeAPI/Dialog.swift index 2a4c2a9..75a2b60 100644 --- a/bindings/swift/Sources/NativeAPI/Dialog.swift +++ b/bindings/swift/Sources/NativeAPI/Dialog.swift @@ -20,6 +20,6 @@ public enum DialogModality: CInt { } var raw: native_dialog_modality_t { - native_dialog_modality_t(rawValue: UInt32(self.rawValue)) + native_dialog_modality_t(rawValue: numericCast(self.rawValue)) } } diff --git a/bindings/swift/Sources/NativeAPI/Display.swift b/bindings/swift/Sources/NativeAPI/Display.swift index a3efb0f..79ba597 100644 --- a/bindings/swift/Sources/NativeAPI/Display.swift +++ b/bindings/swift/Sources/NativeAPI/Display.swift @@ -24,7 +24,7 @@ public enum DisplayOrientation: CInt { } var raw: native_display_orientation_t { - native_display_orientation_t(rawValue: UInt32(self.rawValue)) + native_display_orientation_t(rawValue: numericCast(self.rawValue)) } } diff --git a/bindings/swift/Sources/NativeAPI/DragSource.swift b/bindings/swift/Sources/NativeAPI/DragSource.swift index 94dbd33..fc7ccd5 100644 --- a/bindings/swift/Sources/NativeAPI/DragSource.swift +++ b/bindings/swift/Sources/NativeAPI/DragSource.swift @@ -22,7 +22,7 @@ public enum DragOperation: CInt { } var raw: native_drag_operation_t { - native_drag_operation_t(rawValue: UInt32(self.rawValue)) + native_drag_operation_t(rawValue: numericCast(self.rawValue)) } } diff --git a/bindings/swift/Sources/NativeAPI/FileDialog.swift b/bindings/swift/Sources/NativeAPI/FileDialog.swift index 31003b0..477f8c6 100644 --- a/bindings/swift/Sources/NativeAPI/FileDialog.swift +++ b/bindings/swift/Sources/NativeAPI/FileDialog.swift @@ -22,7 +22,7 @@ public enum FileDialogMode: CInt { } var raw: native_file_dialog_mode_t { - native_file_dialog_mode_t(rawValue: UInt32(self.rawValue)) + native_file_dialog_mode_t(rawValue: numericCast(self.rawValue)) } } @@ -43,7 +43,7 @@ public enum FileDialogResult: CInt { } var raw: native_file_dialog_result_t { - native_file_dialog_result_t(rawValue: UInt32(self.rawValue)) + native_file_dialog_result_t(rawValue: numericCast(self.rawValue)) } } diff --git a/bindings/swift/Sources/NativeAPI/Foundation/Keyboard.swift b/bindings/swift/Sources/NativeAPI/Foundation/Keyboard.swift index bb18803..376e2e8 100644 --- a/bindings/swift/Sources/NativeAPI/Foundation/Keyboard.swift +++ b/bindings/swift/Sources/NativeAPI/Foundation/Keyboard.swift @@ -13,11 +13,11 @@ public struct ModifierKey: OptionSet, Sendable { } init(raw: native_modifier_key_t) { - self.init(rawValue: UInt32(raw.rawValue)) + self.init(rawValue: numericCast(raw.rawValue)) } var raw: native_modifier_key_t { - native_modifier_key_t(rawValue: rawValue) + native_modifier_key_t(rawValue: numericCast(rawValue)) } public static let shift = ModifierKey(rawValue: 1) diff --git a/bindings/swift/Sources/NativeAPI/Menu.swift b/bindings/swift/Sources/NativeAPI/Menu.swift index 1963676..ecd8373 100644 --- a/bindings/swift/Sources/NativeAPI/Menu.swift +++ b/bindings/swift/Sources/NativeAPI/Menu.swift @@ -22,7 +22,7 @@ public enum MenuBackend: CInt { } var raw: native_menu_backend_t { - native_menu_backend_t(rawValue: UInt32(self.rawValue)) + native_menu_backend_t(rawValue: numericCast(self.rawValue)) } } @@ -45,7 +45,7 @@ public enum MenuItemType: CInt { } var raw: native_menu_item_type_t { - native_menu_item_type_t(rawValue: UInt32(self.rawValue)) + native_menu_item_type_t(rawValue: numericCast(self.rawValue)) } } @@ -64,7 +64,7 @@ public enum MenuItemState: CInt { } var raw: native_menu_item_state_t { - native_menu_item_state_t(rawValue: UInt32(self.rawValue)) + native_menu_item_state_t(rawValue: numericCast(self.rawValue)) } } diff --git a/bindings/swift/Sources/NativeAPI/MessageDialog.swift b/bindings/swift/Sources/NativeAPI/MessageDialog.swift index 38eba5e..ff197aa 100644 --- a/bindings/swift/Sources/NativeAPI/MessageDialog.swift +++ b/bindings/swift/Sources/NativeAPI/MessageDialog.swift @@ -22,7 +22,7 @@ public enum MessageDialogResult: CInt { } var raw: native_message_dialog_result_t { - native_message_dialog_result_t(rawValue: UInt32(self.rawValue)) + native_message_dialog_result_t(rawValue: numericCast(self.rawValue)) } } diff --git a/bindings/swift/Sources/NativeAPI/Placement.swift b/bindings/swift/Sources/NativeAPI/Placement.swift index 63bbd1a..0143205 100644 --- a/bindings/swift/Sources/NativeAPI/Placement.swift +++ b/bindings/swift/Sources/NativeAPI/Placement.swift @@ -38,6 +38,6 @@ public enum Placement: CInt { } var raw: native_placement_t { - native_placement_t(rawValue: UInt32(self.rawValue)) + native_placement_t(rawValue: numericCast(self.rawValue)) } } diff --git a/bindings/swift/Sources/NativeAPI/PositioningStrategy.swift b/bindings/swift/Sources/NativeAPI/PositioningStrategy.swift index 84ab67a..146f6df 100644 --- a/bindings/swift/Sources/NativeAPI/PositioningStrategy.swift +++ b/bindings/swift/Sources/NativeAPI/PositioningStrategy.swift @@ -20,7 +20,7 @@ public enum PositioningStrategyType: CInt { } var raw: native_positioning_strategy_type_t { - native_positioning_strategy_type_t(rawValue: UInt32(self.rawValue)) + native_positioning_strategy_type_t(rawValue: numericCast(self.rawValue)) } } diff --git a/bindings/swift/Sources/NativeAPI/Shortcut.swift b/bindings/swift/Sources/NativeAPI/Shortcut.swift index 13024c7..bb5e457 100644 --- a/bindings/swift/Sources/NativeAPI/Shortcut.swift +++ b/bindings/swift/Sources/NativeAPI/Shortcut.swift @@ -20,7 +20,7 @@ public enum ShortcutScope: CInt { } var raw: native_shortcut_scope_t { - native_shortcut_scope_t(rawValue: UInt32(self.rawValue)) + native_shortcut_scope_t(rawValue: numericCast(self.rawValue)) } } diff --git a/bindings/swift/Sources/NativeAPI/TrayIcon.swift b/bindings/swift/Sources/NativeAPI/TrayIcon.swift index 093a110..684f4b0 100644 --- a/bindings/swift/Sources/NativeAPI/TrayIcon.swift +++ b/bindings/swift/Sources/NativeAPI/TrayIcon.swift @@ -24,7 +24,7 @@ public enum ContextMenuTrigger: CInt { } var raw: native_context_menu_trigger_t { - native_context_menu_trigger_t(rawValue: UInt32(self.rawValue)) + native_context_menu_trigger_t(rawValue: numericCast(self.rawValue)) } } @@ -41,7 +41,7 @@ public enum TrayIconPosition: CInt { } var raw: native_tray_icon_position_t { - native_tray_icon_position_t(rawValue: UInt32(self.rawValue)) + native_tray_icon_position_t(rawValue: numericCast(self.rawValue)) } } diff --git a/bindings/swift/Sources/NativeAPI/UrlOpener.swift b/bindings/swift/Sources/NativeAPI/UrlOpener.swift index 5ce4e75..09d546c 100644 --- a/bindings/swift/Sources/NativeAPI/UrlOpener.swift +++ b/bindings/swift/Sources/NativeAPI/UrlOpener.swift @@ -26,7 +26,7 @@ public enum UrlOpenErrorCode: CInt { } var raw: native_url_open_error_code_t { - native_url_open_error_code_t(rawValue: UInt32(self.rawValue)) + native_url_open_error_code_t(rawValue: numericCast(self.rawValue)) } } diff --git a/bindings/swift/Sources/NativeAPI/View.swift b/bindings/swift/Sources/NativeAPI/View.swift index 3564562..dffa72f 100644 --- a/bindings/swift/Sources/NativeAPI/View.swift +++ b/bindings/swift/Sources/NativeAPI/View.swift @@ -22,7 +22,7 @@ public enum ViewLayout: CInt { } var raw: native_view_layout_t { - native_view_layout_t(rawValue: UInt32(self.rawValue)) + native_view_layout_t(rawValue: numericCast(self.rawValue)) } } @@ -43,7 +43,7 @@ public enum ViewAlignment: CInt { } var raw: native_view_alignment_t { - native_view_alignment_t(rawValue: UInt32(self.rawValue)) + native_view_alignment_t(rawValue: numericCast(self.rawValue)) } } @@ -62,7 +62,7 @@ public enum TextAlignment: CInt { } var raw: native_text_alignment_t { - native_text_alignment_t(rawValue: UInt32(self.rawValue)) + native_text_alignment_t(rawValue: numericCast(self.rawValue)) } } @@ -79,7 +79,7 @@ public enum ViewBackend: CInt { } var raw: native_view_backend_t { - native_view_backend_t(rawValue: UInt32(self.rawValue)) + native_view_backend_t(rawValue: numericCast(self.rawValue)) } } diff --git a/bindings/swift/Sources/NativeAPI/Window.swift b/bindings/swift/Sources/NativeAPI/Window.swift index b489b28..fa7edb0 100644 --- a/bindings/swift/Sources/NativeAPI/Window.swift +++ b/bindings/swift/Sources/NativeAPI/Window.swift @@ -22,7 +22,7 @@ public enum TitleBarStyle: CInt { } var raw: native_title_bar_style_t { - native_title_bar_style_t(rawValue: UInt32(self.rawValue)) + native_title_bar_style_t(rawValue: numericCast(self.rawValue)) } } @@ -41,7 +41,7 @@ public enum WindowDockSide: CInt { } var raw: native_window_dock_side_t { - native_window_dock_side_t(rawValue: UInt32(self.rawValue)) + native_window_dock_side_t(rawValue: numericCast(self.rawValue)) } } @@ -62,7 +62,7 @@ public enum WindowCornerPreference: CInt { } var raw: native_window_corner_preference_t { - native_window_corner_preference_t(rawValue: UInt32(self.rawValue)) + native_window_corner_preference_t(rawValue: numericCast(self.rawValue)) } } @@ -99,7 +99,7 @@ public enum WindowProperty: CInt { } var raw: native_window_property_t { - native_window_property_t(rawValue: UInt32(self.rawValue)) + native_window_property_t(rawValue: numericCast(self.rawValue)) } } @@ -118,7 +118,7 @@ public enum WindowOcclusionState: CInt { } var raw: native_window_occlusion_state_t { - native_window_occlusion_state_t(rawValue: UInt32(self.rawValue)) + native_window_occlusion_state_t(rawValue: numericCast(self.rawValue)) } } @@ -147,7 +147,7 @@ public enum VisualEffect: CInt { } var raw: native_visual_effect_t { - native_visual_effect_t(rawValue: UInt32(self.rawValue)) + native_visual_effect_t(rawValue: numericCast(self.rawValue)) } } @@ -176,7 +176,7 @@ public enum ResizeEdge: CInt { } var raw: native_resize_edge_t { - native_resize_edge_t(rawValue: UInt32(self.rawValue)) + native_resize_edge_t(rawValue: numericCast(self.rawValue)) } } diff --git a/tools/codegen/bindings/src/swift.rs b/tools/codegen/bindings/src/swift.rs index 6487bee..6a53166 100644 --- a/tools/codegen/bindings/src/swift.rs +++ b/tools/codegen/bindings/src/swift.rs @@ -264,7 +264,7 @@ fn generate_swift_enum(out: &mut String, item: &Enum, prefix: &str) { writeln!(out, " }}").unwrap(); writeln!(out).unwrap(); writeln!(out, " var raw: {c_ty} {{").unwrap(); - writeln!(out, " {c_ty}(rawValue: UInt32(self.rawValue))").unwrap(); + writeln!(out, " {c_ty}(rawValue: numericCast(self.rawValue))").unwrap(); writeln!(out, " }}").unwrap(); writeln!(out, "}}").unwrap(); writeln!(out).unwrap(); @@ -286,11 +286,11 @@ fn generate_swift_option_set(out: &mut String, item: &Enum, c_ty: &str) { writeln!(out, " }}").unwrap(); writeln!(out).unwrap(); writeln!(out, " init(raw: {c_ty}) {{").unwrap(); - writeln!(out, " self.init(rawValue: UInt32(raw.rawValue))").unwrap(); + writeln!(out, " self.init(rawValue: numericCast(raw.rawValue))").unwrap(); writeln!(out, " }}").unwrap(); writeln!(out).unwrap(); writeln!(out, " var raw: {c_ty} {{").unwrap(); - writeln!(out, " {c_ty}(rawValue: rawValue)").unwrap(); + writeln!(out, " {c_ty}(rawValue: numericCast(rawValue))").unwrap(); writeln!(out, " }}").unwrap(); writeln!(out).unwrap(); for variant in &item.variants { From a2651e2bdd8232357d0ea76e30f7614a825611b6 Mon Sep 17 00:00:00 2001 From: LiJianying Date: Fri, 13 Nov 2026 00:09:01 +0800 Subject: [PATCH 3/3] Cast generated string-list counts for 32-bit long platforms C long is 64-bit on Linux/macOS and 32-bit on Windows; numericCast keeps the generated Swift compiling on all three. --- bindings/swift/Sources/NativeAPI/Clipboard.swift | 4 ++-- bindings/swift/Sources/NativeAPI/DragSource.swift | 2 +- bindings/swift/Sources/NativeAPI/FileDialog.swift | 2 +- bindings/swift/Sources/NativeAPI/LaunchAtLogin.swift | 2 +- tools/codegen/bindings/src/swift.rs | 8 ++++---- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/bindings/swift/Sources/NativeAPI/Clipboard.swift b/bindings/swift/Sources/NativeAPI/Clipboard.swift index 53a3825..276c12e 100644 --- a/bindings/swift/Sources/NativeAPI/Clipboard.swift +++ b/bindings/swift/Sources/NativeAPI/Clipboard.swift @@ -31,7 +31,7 @@ extension ClipboardData { raw.image = self.image?.nativeHandle ?? 0 if !self.filePaths.isEmpty { let pointers = self.filePaths.map { strdup($0) } - raw.file_paths.count = pointers.count + raw.file_paths.count = numericCast(pointers.count) raw.file_paths.items = UnsafeMutablePointer?>.allocate(capacity: pointers.count) for (index, pointer) in pointers.enumerated() { raw.file_paths.items[index] = pointer } } @@ -157,7 +157,7 @@ public final class Clipboard: Sendable { let filePathsPointers = filePaths.map { strdup($0) } defer { filePathsPointers.forEach { free($0) } } var filePathsList = native_string_list_t() - filePathsList.count = filePathsPointers.count + filePathsList.count = numericCast(filePathsPointers.count) if !filePathsPointers.isEmpty { filePathsList.items = UnsafeMutablePointer?>.allocate(capacity: filePathsPointers.count) for (index, pointer) in filePathsPointers.enumerated() { filePathsList.items[index] = pointer } diff --git a/bindings/swift/Sources/NativeAPI/DragSource.swift b/bindings/swift/Sources/NativeAPI/DragSource.swift index fc7ccd5..e8c20b1 100644 --- a/bindings/swift/Sources/NativeAPI/DragSource.swift +++ b/bindings/swift/Sources/NativeAPI/DragSource.swift @@ -89,7 +89,7 @@ public class DragSource { let filePathsPointers = filePaths.map { strdup($0) } defer { filePathsPointers.forEach { free($0) } } var filePathsList = native_string_list_t() - filePathsList.count = filePathsPointers.count + filePathsList.count = numericCast(filePathsPointers.count) if !filePathsPointers.isEmpty { filePathsList.items = UnsafeMutablePointer?>.allocate(capacity: filePathsPointers.count) for (index, pointer) in filePathsPointers.enumerated() { filePathsList.items[index] = pointer } diff --git a/bindings/swift/Sources/NativeAPI/FileDialog.swift b/bindings/swift/Sources/NativeAPI/FileDialog.swift index 477f8c6..cf96bc1 100644 --- a/bindings/swift/Sources/NativeAPI/FileDialog.swift +++ b/bindings/swift/Sources/NativeAPI/FileDialog.swift @@ -94,7 +94,7 @@ public class FileDialog { let extensionsPointers = extensions.map { strdup($0) } defer { extensionsPointers.forEach { free($0) } } var extensionsList = native_string_list_t() - extensionsList.count = extensionsPointers.count + extensionsList.count = numericCast(extensionsPointers.count) if !extensionsPointers.isEmpty { extensionsList.items = UnsafeMutablePointer?>.allocate(capacity: extensionsPointers.count) for (index, pointer) in extensionsPointers.enumerated() { extensionsList.items[index] = pointer } diff --git a/bindings/swift/Sources/NativeAPI/LaunchAtLogin.swift b/bindings/swift/Sources/NativeAPI/LaunchAtLogin.swift index 9a2d05c..2a7f8ed 100644 --- a/bindings/swift/Sources/NativeAPI/LaunchAtLogin.swift +++ b/bindings/swift/Sources/NativeAPI/LaunchAtLogin.swift @@ -88,7 +88,7 @@ public class LaunchAtLogin { let argumentsPointers = arguments.map { strdup($0) } defer { argumentsPointers.forEach { free($0) } } var argumentsList = native_string_list_t() - argumentsList.count = argumentsPointers.count + argumentsList.count = numericCast(argumentsPointers.count) if !argumentsPointers.isEmpty { argumentsList.items = UnsafeMutablePointer?>.allocate(capacity: argumentsPointers.count) for (index, pointer) in argumentsPointers.enumerated() { argumentsList.items[index] = pointer } diff --git a/tools/codegen/bindings/src/swift.rs b/tools/codegen/bindings/src/swift.rs index 6a53166..ccdd25d 100644 --- a/tools/codegen/bindings/src/swift.rs +++ b/tools/codegen/bindings/src/swift.rs @@ -941,7 +941,7 @@ fn render_param_bindings( ) .unwrap(); writeln!(out, "{indent}var {name}List = native_string_list_t()").unwrap(); - writeln!(out, "{indent}{name}List.count = {name}Pointers.count").unwrap(); + writeln!(out, "{indent}{name}List.count = numericCast({name}Pointers.count)").unwrap(); writeln!(out, "{indent}if !{name}Pointers.isEmpty {{").unwrap(); writeln!( out, @@ -973,7 +973,7 @@ fn render_param_bindings( ) .unwrap(); writeln!(out, "{indent}var {name}Map = native_string_map_t()").unwrap(); - writeln!(out, "{indent}{name}Map.count = {name}Keys.count").unwrap(); + writeln!(out, "{indent}{name}Map.count = numericCast({name}Keys.count)").unwrap(); writeln!(out, "{indent}if !{name}Keys.isEmpty {{").unwrap(); writeln!( out, @@ -1461,7 +1461,7 @@ fn swift_field_to_raw( "{indent} let pointers = self.{public}.map {{ strdup($0) }}" ) .unwrap(); - writeln!(out, "{indent} raw.{raw}.count = pointers.count").unwrap(); + writeln!(out, "{indent} raw.{raw}.count = numericCast(pointers.count)").unwrap(); writeln!( out, "{indent} raw.{raw}.items = UnsafeMutablePointer?>.allocate(capacity: pointers.count)" @@ -1486,7 +1486,7 @@ fn swift_field_to_raw( "{indent} let values = self.{public}.values.map {{ strdup($0) }}" ) .unwrap(); - writeln!(out, "{indent} raw.{raw}.count = keys.count").unwrap(); + writeln!(out, "{indent} raw.{raw}.count = numericCast(keys.count)").unwrap(); writeln!( out, "{indent} raw.{raw}.keys = UnsafeMutablePointer?>.allocate(capacity: keys.count)"