You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[native_toolchain_c] LinkerOptions.treeshake fails to link on macOS and iOS if a symbol to keep is not defined #3737
This issue was generated by an AI coding agent (Jetski) on behalf of @mosuem.
LinkerOptions.treeshake(symbolsToKeep: ...) passes -Wl,-u,_<symbol> for every symbol to keep on macOS and iOS. ld64 documents -u symbol_name as "specifies that symbol symbol_name must be defined for the link to succeed", so if one of the symbols isn't defined by the input archives, the link fails with an undefined-symbols error.
Tree-shaking can easily ask for symbols that a library doesn't define, for example when bindings cover functions that a particular build or target leaves out. #3726 fixes the equivalent problem on Windows (LNK2001 from the generated module-definition file) by reading the symbol table of the input archives and only keeping the symbols they define. Linux and Android don't have the problem: for shared libraries, -u of a symbol that nothing defines is a no-op there.
Doing the same for macOS and iOS needs a reader for the BSD archive symbol table, which differs from the COFF/GNU one that #3726 reads: the first member is named __.SYMDEF or __.SYMDEF SORTED (or __.SYMDEF_64/__.SYMDEF_64 SORTED for 64-bit tables), usually with a BSD #1/<length> extended name stored at the start of the member data, followed by a little-endian ranlib table of (string offset, member offset) pairs and a string table. Mach-O symbol names carry a leading underscore, so _<symbol> is what to look up.
Until then, packages that tree-shake on macOS and iOS have to filter symbolsToKeep themselves.
Activity
[native_toolchain_c] Only keep symbols the input archives define on e…
dcharkes commentedon Oct 12, 2026
This is a result of:
#if#1589only when TFA cannot prove that you will never call it at runtime (at runtime you would fail to lookup the symbol!)
A workaround could be add
in the code that wraps the call, or structure your code in another way so that TFA can see the native calls are unreachable.
In your specific use case, which symbols are retained but shouldn't? How is your code structured? Any patterns we can observe but TFA can't?