Skip to content

fix(flutter): stop shipping LTO bitcode in the iOS static lib (pub.dev 256MiB) - #196

Merged
eric8810 merged 2 commits into
masterfrom
fix/flutter-ios-staticlib-size
Sep 28, 2026
Merged

eric8810 merged 2 commits into
masterfrom
fix/flutter-ios-staticlib-size

Conversation

@eric8810

Copy link
Copy Markdown
Contributor

Problem

The v0.5.0 release failed on Publish Flutter to pub.dev: Uncompressed package archive is too large (size > 268435456). Every other release target (crates.io, npm, PyPI, Maven Central, GitHub Release) succeeded.

Root cause: a cargo staticlib never goes through a link step, so the workspace's lto = true only makes cargo pass -C embed-bitcode=yes — every codegen unit embeds its full LLVM bitcode (.llvmbc on ELF, __LLVM,__bitcode on Mach-O) and it stays in the .a forever. The 0.5.0 iOS xcframework slices hit ~128MB each (bitcode ≈80% + debug symbols), pushing the unpacked pub package past 256MiB. 0.3.0 (92MB/slice) had just squeaked under.

Fix

  • [profile.ios-release] (inherits release, lto = false) — used only by scripts/build-ios-xcframework.sh; opt-level = "z", codegen-units = 1 and strip are unchanged, and every other target keeps fat-LTO.
  • Script additionally runs strip -Sx (debug + local symbols; global symbols stay — the podspec force_load resolves against them) and xcrun bitcode_strip -r as a belt-and-braces guard.
  • CFBundleShortVersionString in the generated Info.plist was hardcoded 0.2.0; now read from Cargo.toml.
  • bindings/flutter/CHANGELOG.md gains the missing 0.5.0 entry (pub validation warning, and pub.dev renders it on the package page).
  • Main CHANGELOG 0.5.0 Fixed section records the size regression + fix.

Validation

  • Linux staticlib, same mechanism (cargo build --profile ios-release --target x86_64-unknown-linux-gnu -p aimux-ffi):
    • archive 138.4MB → 66.5MB after the script's strip -Sx
    • .llvmbc sections: 0 (was 16.9MB inside the single largest object)
  • RUSTFLAGS="-C lto=off" does not work (cargo orders its own profile flag after user RUSTFLAGS) — hence the dedicated profile.
  • The CI Flutter binding job (ci.yml) runs this script on macOS with flutter test, so the PR checks exercise the real Apple toolchain end to end.

Release follow-up

After merge: workflow_dispatch the Release workflow with only flutter enabled to re-publish the 0.5.0 package (android + ios artifacts rebuild with this fix; GitHub Release assets stay as-is).

…v 256MiB)

A cargo staticlib never goes through a link step, so the workspace's
fat-LTO (lto = true) only makes cargo pass -C embed-bitcode=yes: every
codegen unit embeds its full LLVM bitcode (.llvmbc on ELF, __LLVM,__bitcode
on Mach-O) and it stays in the .a forever. On the v0.5.0 xcframework each
slice hit ~128MB (bitcode ~80% + debug symbols); the two slices pushed the
uncompressed pub package past the 256MiB limit and pub.dev rejected the
release.

- new [profile.ios-release] (inherits release, lto = false); the iOS build
  script switches to it, keeping opt-level=z / codegen-units=1 / strip
- the script additionally runs strip -Sx (debug + local symbols; globals
  stay for the podspec force_load) and bitcode_strip -r as a guard
- measured on the Linux staticlib (same mechanism): 138.4MB -> 66.5MB;
  per-member .llvmbc gone (16.9MB in the largest single object)
- CFBundleShortVersionString in the generated Info.plist was hardcoded
  0.2.0; now read from Cargo.toml
- flutter CHANGELOG gains the missing 0.5.0 entry (pub validation warning)

Desktop .a artifacts on the GitHub Release keep the fat profile for now;
nothing links them at CI time and nothing limits their size.
Xcode 26.6's bitcode_strip fails on the LTO-off archive with 'internal
link edit command failed' (the tool has been dead weight since Apple
removed bitcode support in Xcode 14). Its only job was guarding against
a profile regression; a 64MiB size gate does that more directly and
maps onto the pub.dev package limit — a healthy slice is ~15-30MB, an
LTO/bitcode regression lands near 128MB.
@eric8810
eric8810 merged commit 7ce40c7 into master Sep 28, 2026
24 checks passed
@eric8810
eric8810 deleted the fix/flutter-ios-staticlib-size branch September 28, 2026 04:50
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.

1 participant