Skip to content

Make the @_cdecl exports in lib.swift public so Xcode 27 release builds link - #85

Merged
Brendonovich merged 1 commit into
Brendonovich:mainfrom
takakix2:fix/public-cdecl-exports
Oct 10, 2026
Merged

Brendonovich merged 1 commit into
Brendonovich:mainfrom
takakix2:fix/public-cdecl-exports

Conversation

@takakix2

@takakix2 takakix2 commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

On Xcode 27 (Swift 6.4), SwiftPM builds with Swift Build by default, and in -c release it gives non-public @_cdecl functions local visibility (t in nm). Rust consumers then fail to link with undefined symbols. src-swift/lib.swift exports four such functions — retain_object, release_object, data_from_bytes, string_from_bytes — none of them public.

This PR marks those four public. Nothing else changes; public keeps them global under both build systems and every configuration.

Why the llvm-objcopy step from #77 does not cover these

#77 re-globalizes @_cdecl symbols after the build, but only symbols in the package's own object member. When Tauri (or any package) depends on SwiftRs, these four live in the SwiftRs member of the dependent package's archive (e.g. libTauri.a), so they are skipped by design. Also, when llvm-tools is not installed the step prints a cargo:warning, but Cargo does not show build-script warnings from registry dependencies, so users see only the link error.

Measured (Xcode 27.0 27A266a, tauri 2.12.1, swift-rs 1.0.8, aarch64-apple-ios, plain tauri ios build — release)

setup result
as released, no llvm-tools 9 undefined symbols (Tauri's 4, two plugins' init_plugin_*, and retain_object / release_object / string_from_bytes)
as released, with llvm-tools 3 undefined: _retain_object, _release_object, _string_from_bytes
this change (+ the matching public change in tauri / plugins-workspace) links; Xcode archive and IPA export succeed

Standalone, building Tauri's ios-api package with the same arguments swift-rs passes (swift build -c release --triple arm64-apple-ios15.0 …) and checking nm on libTauri.a: the four symbols above are t with the Swift side at 1.0.7 and T with this change.

Tagging

SwiftPM resolves this package by git tag, and the newest tag is 1.0.7 — there is no 1.0.8 tag, although 1.0.8 is on crates.io. So the Swift side Tauri apps build today is 1.0.7. For this fix to reach them it needs a new tag after merging (e.g. 1.0.9).

Context

We ship an iOS app built with Tauri and currently publish its App Store builds with the workaround from tauri-apps/tauri#16130 (keep debuginfo so Swift is built in debug, optimize Rust). With this change and the matching ones in tauri and plugins-workspace, a plain release build links again with no workaround and no llvm-tools.

Related: tauri-apps/tauri#16130

Companion PRs: tauri-apps/tauri#16246, tauri-apps/plugins-workspace#3684

…ds link

Xcode 27's SwiftPM (Swift Build) gives non-public @_cdecl functions local
visibility in release builds, so retain_object, release_object,
data_from_bytes and string_from_bytes are undefined when Rust links. The
llvm-objcopy step only re-globalizes a package's own member, so these
(in the SwiftRs member of a dependent's archive) are not covered.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Brendonovich
Brendonovich merged commit 27a3685 into Brendonovich:main Oct 10, 2026
afadil added a commit to wealthfolio/wealthfolio that referenced this pull request Oct 13, 2026
tauri 2.12.3 and swift-rs 1.0.9 make the Swift @_cdecl entry points
that Rust links against public, so iOS release builds made with
Xcode 27 keep them global (tauri-apps/tauri#16246,
Brendonovich/swift-rs#85). Until now these builds linked only because
swift-rs re-globalizes the symbols when rustup's llvm-tools component
is installed. The tauri-plugin-mobile-share and tauri-plugin-web-auth
entry points are still not public upstream, so llvm-tools is still
needed for iOS release builds.

The patch releases also relaunch through LaunchServices on macOS
restart, keep delivering Channel messages after a handler throws, and
fix a panic when a once listener receives several events.

@tauri-apps/api moves to 2.12.3 with the crate. tauri-build, -codegen
and -macros move to 2.7.2, tauri-runtime and -runtime-wry to 2.12.1,
tauri-utils to 2.10.1. wry, tao and the plugins are unchanged.

Tested with Xcode 27.0 (27A266a): a release device archive
(tauri ios build --no-sign --archive-only --target aarch64) links,
and libTauri.a now exports its entry points globally on its own.
cargo check for wealthfolio-app and wealthfolio-server and
pnpm type-check pass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants