UniFFI: Swift release follow-ups#1091
Merged
Merged
Conversation
The CodeQL autofix landed in #1078 added `permissions: contents: read` at the top level of uniffi-packages.yml, which then forbids any nested job (including the called workflow uniffi-swift.yml) from requesting higher permissions — workflow validation fails with: Error calling workflow ... The nested job 'build-and-publish' is requesting 'contents: write', but is only allowed 'contents: read'. Neither job actually needs write: `gh release list` in resolve-tag is read-only, and the publish step authenticates to the hosting repo with UNIFFI_XCFRAMEWORK_PAT (not GITHUB_TOKEN). Drop the elevation on both so the workflow can start.
d78bf92 to
a60f3a8
Compare
cargo-make 0.37.25+ adds its own --force when running install_crate, so the explicit --force here makes cargo install reject the duplicate argument with exit 105.
LiveKit's feature/framework-wrapping branch (PR #96 against antoniusnaumann/cargo-swift) has been merged upstream. Point at the upstream merge commit fe7becf so the fork dependency goes away.
Multi-arch xcframework build is the long pole. -xlarge is arm64 + paid; expect roughly half the wall-clock of the default macos-26 runner.
Dedent the if/elif/else/endif tags to column 0 and use {%- consistently
so the rendered Package.swift no longer emits a blank line between
.target and .binaryTarget. Verified locally — diff against the existing
hosting-repo manifest now shows only the intended version/checksum
changes.
Add the built PrivacyInfo.xcprivacy to the publish files list so the
hosting repo's copy stays in sync if the source manifest ever changes
(today it's identical, but the workflow shouldn't depend on that).
pblazej
commented
May 15, 2026
| build-and-publish: | ||
| name: Build & publish Swift xcframework | ||
| runs-on: macos-26 | ||
| runs-on: macos-26-xlarge |
Contributor
Author
There was a problem hiding this comment.
It seems it leverages the cache heavily now.
Contributor
Author
There was a problem hiding this comment.
Maybe we can switch to https://namespace.so/docs/architecture/compute/macos
Inject CARGO_PROFILE_RELEASE_DEBUG=limited and CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO=packed into the swift-xcframework task only, gated on the cargo-make release profile. Cargo treats them as [profile.release] overrides during this build, so dsymutil emits a sidecar .dSYM next to each per-arch dylib at target/<arch>/release/deps/liblivekit_uniffi.dylib.dSYM (~8.5 MB each, ~94 MB across the 11 Apple targets). Scoping via env vars keeps the workspace Cargo.toml profile lean — FFI, node, and Linux/Windows/Android release builds stay stripped and debug-info-free. limited (line tables + types) is ~3× smaller than full. Verified locally with a clean rebuild.
pblazej
commented
May 15, 2026
| # Linux/Windows/Android) remain on the lean Cargo.toml profile. | ||
| # `split-debuginfo = "packed"` triggers dsymutil → produces .dSYM bundles next | ||
| # to each per-arch .dylib at target/<arch>/release/deps/lib<name>.dylib.dSYM. | ||
| CARGO_PROFILE_RELEASE_DEBUG = { value = "limited", condition = { profiles = ["release"] } } |
Contributor
Author
There was a problem hiding this comment.
Wdyt @ladvoc?
It's not integrated into cargo-swift yet (needs another patch) but would be good to have, especially during initial adoption.
I confirmed it works locally.
Contributor
Author
There was a problem hiding this comment.
We can also tackle that in a separate PR.
Add `--debug-symbols` to the cargo-swift invocation so each xcframework slice gets a sidecar dSYMs/<framework>.framework.dSYM bundle with the matching UUIDs (single-arch slices get the per-arch dSYM, universal slices get a lipo'd fat-Mach-O dSYM). Xcode and App Store Connect auto-load these for crash symbolisation; previously all Rust frames showed as hex addresses. `--debug-symbols` is the new flag added in livekit/cargo-swift#feature/dsyms (f94e766). Repin the install_crate to that revision until the patch lands upstream — the prior pin to antoniusnaumann/cargo-swift@fe7becf doesn't expose the flag. Expected size impact: xcframework.zip grows from ~5 MB to ~25 MB. About 90% of consumers won't ever inspect the dSYMs, but the cost is acceptable for the symbolisation win on the long tail.
tera-cli's --env mode warns 'unknown environment variable' for any env var name matching SWIFT_DEBUG_*. The conditional flag passed to cargo-swift was named SWIFT_DEBUG_SYMBOLS_FLAG and got flagged three times per swift-generate-manifest run (one per .tera render). Bisected by name — SWIFT_DSYMS_FLAG (and anything else not matching SWIFT_DEBUG_*) passes silently. Place it right next to the existing SWIFT_RELEASE_FLAG since both gate on the same release profile and land in the same cargo-swift invocation.
4d482a0 to
e052fb1
Compare
Adds a swift-check-size cargo-make task that runs between swift-xcframework and swift-zip-xcframework on the release profile. It measures the stripped, single-arch Mach-O at ios-arm64/Rust<name>.framework/Rust<name> inside the produced xcframework. That binary equals the bytes a typical iPhone user downloads after App Store thinning, so it's the most meaningful proxy for the dep's app-size impact. Universal / simulator slices are ~2x larger (two archs in one Mach-O) and would overcount. Default budget is 1 MiB. Current size is 932 KiB (88 KiB headroom) — tight enough to catch regressions, loose enough to absorb incremental uniffi-bindgen / std growth between releases. Bump SPM_SIZE_LIMIT_BYTES on the cargo-make invocation to land an intentional size jump.
Adds a swift-bloat cargo-make task that runs immediately after swift-xcframework and before swift-check-size, printing sections / compileunits / top-15 symbols from the iPhone-arm64 framework binary. Why bloaty over cargo-bloat: - analyses the actually shipped Mach-O (post-LTO, post-strip, post-lipo) instead of rebuilding a separate target - works with our [lib] crate-type = [cdylib, staticlib, lib] (cargo-bloat refuses: 'only bin/dylib/cdylib supported') - consumes the .dSYM we already embed via --debug-symbols for per-crate attribution at no extra cost Auto-installs via brew when missing; degrades to skip with a hint if neither bloaty nor brew is around so non-Mac contributors aren't blocked. Running before swift-check-size means a failing size gate ends with the diagnostic already in the log — no need to rerun anything to investigate.
Contributor
Author
|
2 notable mentions:
|
davidliu
approved these changes
May 21, 2026
Contributor
davidliu
left a comment
There was a problem hiding this comment.
LGTM, I'll see if I can get size and debug symbols stuff into android as well.
Move the Swift mode/dependency details out of the main README into a dedicated support/swift/README.md, and include the consumer-side Package.swift dependency snippet for local iteration. README points to it with a one-liner, matching the Android convention. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
Author
|
Merging, I split the README for Swift - similarly to Android (better choice). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up fixes surfaced while validating the publish pipeline against livekit/livekit-uniffi-xcframework#12.
Workflow
contents: write(blocked startup after the CodeQL autofix in UniFFI: Publish Swift packages #1078)--forcearg now that cargo-make adds its ownantoniusnaumann/cargo-swift@fe7becf— fork retired)macos-26-xlargefor ~½ wall-clockBuild output
Package.swiftto swift-tools 6.0.binaryTargetPrivacyInfo.xcprivacyin the publish setCARGO_PROFILE_RELEASE_{DEBUG=limited,SPLIT_DEBUGINFO=packed}into the swift-xcframework task so each per-arch dylib gets a sidecar.dSYM(~8.5 MB × 11 targets, ~94 MB raw) without touching the workspace's lean Cargo.toml profileDocs
AGENTS.md → README.mdAfter merge: re-dispatch
UniFFI packageswithdry_run=falseon a fresh test version to confirm end-to-end.