Skip to content

-Zstaticlib-hide-internal-symbols and Zstaticlib-rename-internal-symbols: hide/rename internal symbols in staticlibs#155338

Open
cezarbbb wants to merge 10 commits into
rust-lang:mainfrom
cezarbbb:staticlib-symbol-hygiene
Open

-Zstaticlib-hide-internal-symbols and Zstaticlib-rename-internal-symbols: hide/rename internal symbols in staticlibs#155338
cezarbbb wants to merge 10 commits into
rust-lang:mainfrom
cezarbbb:staticlib-symbol-hygiene

Conversation

@cezarbbb
Copy link
Copy Markdown
Contributor

@cezarbbb cezarbbb commented Apr 15, 2026

View all comments

According to issue #104707, when building a staticlib, all Rust internal symbols — mangled symbols, #[rustc_std_internal_symbol] items, allocator shims, etc. — leak out of the static archive. In contrast, cdylib correctly exports only #[no_mangle] symbols via a linker version script.

Two flags are provided, respectively solved the problems of staticlibs exporting many unnecessary Rust internal symbols and multiple staticlibs causing duplicate symbol conflicts:

-Zstaticlib-hide-internal-symbols directly post-processes ELF object files in the archive: parsing the SHT_SYMTAB sections and setting STV_HIDDEN visibility on any GLOBAL/WEAK defined symbol that is not in the exported symbol set, without changing the binding. This is an in-place modification (only writing the st_other byte per matching entry), with zero overhead.

-Zstaticlib-rename-internal-symbols takes a two-pass global approach: first, it collects all defined GLOBAL/WEAK symbol names that are not in the exported symbol set across all .o files; then it renames those symbols in each .o file by appending a suffix (e.g. __rust_internal_), handling both definitions and undefined references so that cross-object-file references remain consistent. The implementation uses a "move strtab to end" strategy: it builds a new strtab with the renamed names, places it at the end of the file, and patches the strtab section header and the ELF e_shoff. When combined with -Zstaticlib-hide-internal-symbols, the renamed symbols also receive STV_HIDDEN visibility.

The two flags for symbol hiding and symbol renaming need to be decoupled, because hiding incurs virtually no overhead, whereas renaming comes with unavoidable costs. Reducing binary size and resolving duplicate symbol conflicts between multiple staticlibs are two distinct requirements. For this reason, I want to let developers choose and trade off between them based on their own needs.

Both flags only affect ELF targets; a warning is emitted for non-ELF targets

The test code are as follows:

1.a std rust staticlib:

use std::collections::HashMap;
use std::panic::{catch_unwind, AssertUnwindSafe};

#[no_mangle]
pub extern "C" fn my_add(a: i32, b: i32) -> i32 { a + b }

#[no_mangle]
pub extern "C" fn my_hash_lookup(key: u64) -> u64 {
    let mut map = HashMap::new();
    for i in 0..100u64 { map.insert(i, i.wrapping_mul(2654435761)); }
    *map.get(&key).unwrap_or(&0)
}

pub fn internal_reverse(s: &str) -> String { s.chars().rev().collect() }

#[no_mangle]
pub extern "C" fn my_format_number(n: i32) -> i32 {
    let s = format!("number: {}", n); s.len() as i32
}

#[no_mangle]
pub extern "C" fn my_safe_div(a: i32, b: i32) -> i32 {
    match catch_unwind(AssertUnwindSafe(|| {
        if b == 0 { panic!("division by zero!"); }
        a / b
    })) {
        Ok(result) => result,
        Err(_) => -1,
    }
}

#[no_mangle]
pub extern "C" fn my_uncaught_panic() { panic!("uncaught panic across FFI"); }

1.b downstream c program:

extern int my_add(int a, int b);
extern unsigned long my_hash_lookup(unsigned long key);
extern int my_format_number(int n);
extern int my_safe_div(int a, int b);
extern void my_uncaught_panic(void);

int main() {
    int failures = 0;
    if (my_add(10, 20) != 30) failures++;
    if (my_hash_lookup(5) != 5UL * 2654435761UL) failures++;
    if (my_format_number(42) != 10) failures++;
    if (my_safe_div(100, 5) != 20) failures++;
    if (my_safe_div(100, 0) != -1) failures++;
    pid_t pid = fork();
    if (pid == 0) { alarm(5); my_uncaught_panic(); _exit(0); }
    else { waitpid(pid, &status, 0); }
    return failures;
}

The test results with different compiler flags(which might cause binary size reduction) are as follows:
1.c result with -Zstaticlib-hide-internal-symbols

  settings                   OFF        ON  -Zsave     ALL    OFF.dynsym ON.dynsym 
  ------------------------------------------------------------------------
  default                 1.7M      1.5M  204K (12%)    1735       5    1730
  lto_thin                616K      584K  33K (5%)     246       5     241
  lto_fat                 525K      525K    0 (0%)       6       5       1
  opt_s                   1.7M      1.5M  204K (12%)    1735       5    1730
  opt_z                   1.7M      1.5M  204K (12%)    1735       5    1730
  lto_thin_z              602K      570K  32K (5%)     246       5     241
  lto_fat_z               514K      514K    0 (0%)       6       5       1
  full                    514K      514K    0 (0%)       6       5       1

1.d result with -Zstaticlib-hide-internal-symbols + -Zstaticlib-rename-internal-symbols

  settings                   OFF        ON  -Zsave     ALL    OFF.dynsym ON.dynsym 
  ------------------------------------------------------------------------
  default                 1.7M      1.5M  162K (9%)    1735       5    1730
  lto_thin                616K      599K  18K (2%)     246       5     241
  lto_fat                 525K      535K  -1% (-1%)       6       5       1
  opt_s                   1.7M      1.5M  162K (9%)    1735       5    1730
  opt_z                   1.7M      1.5M  162K (9%)    1735       5    1730
  lto_thin_z              602K      585K  18K (2%)     246       5     241
  lto_fat_z               514K      524K  -1% (-1%)       6       5       1
  full                    514K      523K  -1% (-1%)       6       5       1

2.a no_std rust staticlib

#![no_std]
#![feature(core_intrinsics)]

use core::panic::PanicInfo;

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! { loop {} }

#[no_mangle]
pub extern "C" fn embedded_add(a: i32, b: i32) -> i32 { a.wrapping_add(b) }

#[no_mangle]
pub extern "C" fn embedded_checksum(data: *const u8, len: usize) -> u8 {
    if data.is_null() { return 0; }
    let slice = unsafe { core::slice::from_raw_parts(data, len) };
    let mut sum: u8 = 0;
    for &byte in slice { sum = sum.wrapping_add(byte); }
    sum
}

fn internal_helper() -> i32 { 42 }
#[no_mangle]
pub extern "C" fn call_internal() -> i32 { internal_helper() }

#[no_mangle]
pub extern "C" fn embedded_trigger_abort() { core::intrinsics::abort(); }

2.b downstream c program

extern int embedded_add(int a, int b);
extern unsigned char embedded_checksum(const unsigned char *data, unsigned long len);
extern int call_internal(void);
extern void embedded_trigger_abort(void);

int main() {
    int failures = 0;
    if (embedded_add(10, 20) != 30) failures++;
    unsigned char data[] = {1, 2, 3};
    if (embedded_checksum(data, 3) != 6) failures++;
    if (call_internal() != 42) failures++;
    pid_t pid = fork();
    if (pid == 0) { embedded_trigger_abort(); _exit(0); }
    else { waitpid(pid, &status, 0); }
    return failures;
}

The test results with different compiler flags(which might cause binary size reduction) are as follows:
2.c result with -Zstaticlib-hide-internal-symbols

  settings                   OFF        ON  -Zsave     ALL    OFF.dynsym ON.dynsym 
  ------------------------------------------------------------------------
  default                 485K      429K  56K (11%)     490       4     486
  lto_thin                180K      180K    0 (0%)       4       4       0
  lto_fat                 179K      179K    0 (0%)       4       4       0
  opt_s                   485K      429K  56K (11%)     490       4     486
  opt_z                   485K      429K  56K (11%)     490       4     486
  lto_thin_z              180K      180K    0 (0%)       4       4       0
  lto_fat_z               179K      179K    0 (0%)       4       4       0
  full                    179K      179K    0 (0%)       4       4       0

2.d result with -Zstaticlib-hide-internal-symbols + -Zstaticlib-rename-internal-symbols

  settings                   OFF        ON  -Zsave     ALL    OFF.dynsym ON.dynsym 
  ------------------------------------------------------------------------
  default                 485K      447K  39K (7%)     490       4     486
  lto_thin                180K      189K  -5% (-5%)       4       4       0
  lto_fat                 179K      189K  -5% (-5%)       4       4       0
  opt_s                   485K      448K  38K (7%)     490       4     486
  opt_z                   485K      448K  38K (7%)     490       4     486
  lto_thin_z              180K      189K  -5% (-5%)       4       4       0
  lto_fat_z               179K      189K  -5% (-5%)       4       4       0
  full                    179K      189K  -5% (-5%)       4       4       0

Test results show that this compiler option is beneficial for scenarios where LTO cannot be enabled.

r? @bjorn3 @petrochenkov

@rustbot rustbot added A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-run-make Area: port run-make Makefiles to rmake.rs S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Apr 15, 2026
@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 15, 2026

r? @petrochenkov

rustbot has assigned @petrochenkov.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: codegen, compiler
  • codegen, compiler expanded to 69 candidates
  • Random selection from 16 candidates

@rustbot

This comment has been minimized.

@rustbot rustbot assigned bjorn3 and unassigned petrochenkov Apr 15, 2026
@bjorn3
Copy link
Copy Markdown
Member

bjorn3 commented Apr 15, 2026

This would also need to rename symbols to avoid conflicts between two rust staticlibs ending up getting linked together, right?

@bjorn3
Copy link
Copy Markdown
Member

bjorn3 commented Apr 15, 2026

The rust_eh_personality symbol is always kept visible to ensure .eh_frame unwinding works correctly for C consumers.

Why exactly is that the case? rust_eh_personality is actually the symbol that is most likely to cause conflicts as it is the only one whose name doesn't get mangled depending on the rustc version.

@cezarbbb cezarbbb force-pushed the staticlib-symbol-hygiene branch from ff707ad to 7ac49d1 Compare April 15, 2026 12:35
@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

This would also need to rename symbols to avoid conflicts between two rust staticlibs ending up getting linked together, right?

My primary goal right now is to reduce binary size, so I don't have immediate plans to implement symbol renaming. This means that linking multiple Rust staticlibs together can still result in multiple definition errors. Would you like me to address that in this PR as well? It seems feasible to implement — for example, by rehashing symbols and updating their references accordingly.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

The rust_eh_personality symbol is always kept visible to ensure .eh_frame unwinding works correctly for C consumers.

Why exactly is that the case? rust_eh_personality is actually the symbol that is most likely to cause conflicts as it is the only one whose name doesn't get mangled depending on the rustc version.

I previously assumed this symbol needed to remain externally visible to support scenarios requiring cross-language exception propagation. Do you think we should also set rust_eh_personality as hidden?

@bjorn3
Copy link
Copy Markdown
Member

bjorn3 commented Apr 15, 2026

If it isn't too hard it would be nice to do symbol renaming too. I think doing in-place modification isn't going to work for that though. Adding a unique suffix would require growing the size of the string table.

@bjorn3
Copy link
Copy Markdown
Member

bjorn3 commented Apr 15, 2026

I previously assumed this symbol needed to remain externally visible to support scenarios requiring cross-language exception propagation. Do you think we should also set rust_eh_personality as hidden?

rust_eh_personality is only meant to be referenced by the .eh_frame section of rust object files. The only reason it's name isn't mangled is because LLVM hard codes the name to determine the exception table format to emit.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

If it isn't too hard it would be nice to do symbol renaming too. I think doing in-place modification isn't going to work for that though. Adding a unique suffix would require growing the size of the string table.

Got it. I will first fix the rust_eh_personality issue, and then try to implement symbol renaming.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@cezarbbb cezarbbb force-pushed the staticlib-symbol-hygiene branch from 5e1c3a1 to c7d4e98 Compare April 16, 2026 03:27
@SparrowLii
Copy link
Copy Markdown
Member

@bors delegate=try

@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Apr 16, 2026

✌️ @cezarbbb, you can now perform try builds on this pull request!

You can now post @bors try to start a try build.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

@bors try

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request Apr 16, 2026
`-Zstaticlib-hide-internal-symbols`: Hide non-exported internal symbols from staticlibs
@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented Apr 16, 2026

☀️ Try build successful (CI)
Build commit: a9431d3 (a9431d37da1d0346038257cec9d94f2783997621, parent: e8e4541ff19649d95afab52fdde2c2eaa6829965)

@cezarbbb
Copy link
Copy Markdown
Contributor Author

@bors try jobs=x86_64-*

@rust-bors

This comment has been minimized.

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request May 11, 2026
`-Zstaticlib-hide-internal-symbols` and `Zstaticlib-rename-internal-symbols`: hide/rename internal symbols in staticlibs


try-job: dist-x86_64-apple
try-job: dist-aarch64-apple
try-job: dist-apple-various
try-job: aarch64-apple
@rust-bors rust-bors Bot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels May 11, 2026
@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented May 11, 2026

💔 Test for 94c46cf failed: CI. Failed job:

@rust-log-analyzer

This comment has been minimized.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

@bors try job=aarch64-apple

@rust-bors

This comment has been minimized.

rust-bors Bot pushed a commit that referenced this pull request May 11, 2026
`-Zstaticlib-hide-internal-symbols` and `Zstaticlib-rename-internal-symbols`: hide/rename internal symbols in staticlibs


try-job: aarch64-apple
@rust-bors
Copy link
Copy Markdown
Contributor

rust-bors Bot commented May 11, 2026

☀️ Try build successful (CI)
Build commit: a52f783 (a52f783a4c94bd174984e7cf584425ff9a1bd20c, parent: 8afb6a8b1b32fce2f8aa7520517833338dc36c5e)

@cezarbbb
Copy link
Copy Markdown
Contributor Author

It looks like the test passed on Apple targets. You can try the current modifications to see if they meet your requirements. @MicroDroid

@MicroDroid
Copy link
Copy Markdown

@cezarbbb Awesome, I think to test it out I just checkout this PR on my computer and build rustc of of it right?

@cezarbbb
Copy link
Copy Markdown
Contributor Author

Correct. Fetch my PR and build rustc(I think stage1 is enough), then you can validate it.

@MicroDroid
Copy link
Copy Markdown

I'll check it out in a sec and report it goes!

@MicroDroid
Copy link
Copy Markdown

Hey @cezarbbb, so I've been trying to get this to work for both Android and iOS, and I'll let you know what happened for each

Android (aarch64-linux-android)

  1. I ran
    cargo +custom-stage1 build --target $TARGET --release
    
    (custom-stage1 is the custom Rust I built off this PR's branch)
  2. I got error:
    error: unknown `-Z` flag specified: staticlib-rename-internal-symbols`
    
  3. I ran:
    RUSTFLAGS="-Zstaticlib-rename-internal-symbols" \
    cargo +custom-stage1 build --target $TARGET --release
    
  4. I got error:
    error: -Zstaticlib-rename-internal-symbols can only be used with `--crate-type staticlib`
    
    ❓ Which is confusing? Cargo.toml already has crate-type = ["staticlib"]
  5. I ran:
    RUSTFLAGS="-Zstaticlib-rename-internal-symbols --crate-type staticlib" \
    cargo +custom-stage1 build --target $TARGET --release
    
  6. I got error:
    ...
    error: `#[panic_handler]` function required, but not found
    error: unwinding panics are not supported without std
      |
      = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding
      = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem
    
    error: no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
    ...
    

I think this is an error in my system and not due to your PR? I couldn't get past this, cause I already had proper config.toml set when building Rust:

[build]
host = ["aarch64-apple-darwin"]
target = ["aarch64-apple-darwin", "aarch64-linux-android", "arm-linux-androideabi", "i686-linux-android", "x86_64-linux-android"]
android-ndk = "/Users/overcoder/Library/Android/sdk/ndk/27.3.13750724/"

And I built entire stage1 + cargo and linked it with rustup toolchain link custom-stage1 build/host/stage1, and inspecting build/ stuff is indeed compiled seemingly correctly, so not sure what's going wrong here

iOS

iOS builds succeeded ✅ (same commands as above) but I tried inspecting the identifiers using nm -g --no-demangle and from the looks of it the symbols are just unchanged? The line I am highlighting in the screenshot below is exactly a symbol that's been causing duplicates for me:

image

For reference:

$ cargo +custom-stage1 -vV

cargo 1.97.0-dev (4f9b52075 2026-05-01)
release: 1.97.0-dev
commit-hash: 4f9b52075316e9ced380c8fa492858048d5758b6
commit-date: 2026-05-01
host: aarch64-apple-darwin
libgit2: 1.9.2 (sys:0.20.4 vendored)
libcurl: 8.7.1 (sys:0.4.88+curl-8.20.0 system ssl:(SecureTransport) LibreSSL/3.3.6)
os: Mac OS 15.7.3 [64-bit]

$ rustc +custom-stage1 -vV

rustc 1.97.0-dev
binary: rustc
commit-hash: unknown
commit-date: unknown
host: aarch64-apple-darwin
release: 1.97.0-dev
LLVM version: 22.1.4

@MicroDroid
Copy link
Copy Markdown

Oh my bad, looks like I forgot to set -Zstaticlib-rename-internal-symbols for the iOS build to begin with... sorry I'll try that in a bit and report back

@MicroDroid
Copy link
Copy Markdown

Ok a new short summary is I tried building with this command for both iOS and Android:

RUSTFLAGS="-Zstaticlib-rename-internal-symbols --crate-type staticlib" \
    cargo +custom-stage1 build --target $TARGET --release

And for both targets I got this error:

error: `#[panic_handler]` function required, but not found

error: unwinding panics are not supported without std
  |
  = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding
  = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem

error: could not compile `cfg-if` (lib) due to 2 previous errors
warning: build failed, waiting for other jobs to finish...
error: could not compile `subtle` (lib) due to 2 previous errors
error: could not compile `typenum` (lib) due to 2 previous errors

However if I build with just:

cargo +custom-stage1 build --target $TARGET --release

Then build succeeds.

In other words it seems like -Zstaticlib-rename-internal-symbols breaks the build process and I'm not exactly sure why.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

It seems that I made a stupid mistake — the flag was using a fatal error instead of a warning when the crate-type isn't staticlib. Since Cargo passes RUSTFLAGS to all dependencies (which are lib crates), this kills their compilation.

The fix is to just emit a warning and continue. I'll fix it shortly.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

You can try again.

@MicroDroid
Copy link
Copy Markdown

Already in-progress, should report back in a bit :)

But one thing I noticed is that now builds emit a warning every dependency crate which is a bit spammy / likely unintended.

@MicroDroid
Copy link
Copy Markdown

MicroDroid commented May 14, 2026

Preliminarily speaking, I think it is renaming user-defined symbols, causing undefined symbol errors when the output goes into the linking stage:

ld.lld: error: undefined symbol: rust::cxxbridge1::String::String(char const*)
>>> referenced by READACTEDClient.cpp:89 (/Users/overcoder/dev/REDACTED/packages/react-native/cpp/READACTEDClient.cpp:89)
>>>               READACTEDClient.cpp.o:(READACTEDClient::generateKeyPackage()) in archive READACTEDSpec_cxxmodule_autolinked_build/libREDACTED.a

ld.lld: error: undefined symbol: READACTEDBridge::generateKeyPackage(READACTEDBridge::GenerateKeyPackageInput)
>>> referenced by READACTEDClient.cpp:88 (/Users/overcoder/dev/REDACTED/packages/react-native/cpp/READACTEDClient.cpp:88)
>>>               READACTEDClient.cpp.o:(READACTEDClient::generateKeyPackage()) in archive READACTEDSpec_cxxmodule_autolinked_build/libREDACTED.a

ld.lld: error: undefined symbol: rust::cxxbridge1::String::~String()
>>> referenced by READACTEDRustBridge.h:108 (/Users/overcoder/dev/REDACTED/packages/react-native/cpp/include/READACTEDRustBridge.h:108)
>>>               READACTEDClient.cpp.o:(READACTEDClient::generateKeyPackage()) in archive READACTEDSpec_cxxmodule_autolinked_build/libREDACTED.a
>>> referenced by READACTEDRustBridge.h:99 (/Users/overcoder/dev/REDACTED/packages/react-native/cpp/include/READACTEDRustBridge.h:99)
>>>               READACTEDClient.cpp.o:(READACTEDClient::generateKeyPackage()) in archive READACTEDSpec_cxxmodule_autolinked_build/libREDACTED.a
>>> referenced by READACTEDRustBridge.h:99 (/Users/overcoder/dev/REDACTED/packages/react-native/cpp/include/READACTEDRustBridge.h:99)
>>>               READACTEDClient.cpp.o:(READACTEDClient::generateKeyPackage()) in archive READACTEDSpec_cxxmodule_autolinked_build/libREDACTED.a
clang++: error: linker command failed with exit code 1 (use -v to see invocation)
ninja: build stopped: subcommand failed.

(I am using cxx.rs btw)

Simply toggling the rename flag off fixes this build error.

Still investigating.

@MicroDroid
Copy link
Copy Markdown

I think the rename flag indeed modifies public symbols:

$ nm -g --demangle without-rename-flag/libmls_rust.a 2>/dev/null | grep REDACTED

0000000000000000 T _REDACTEDBridge$cxxbridge1$190$generateKeyPackage
                 U _REDACTEDBridge$cxxbridge1$190$generateKeyPackage
0000000000000000 T REDACTEDBridge::generateKeyPackage(REDACTEDBridge::GenerateKeyPackageInput)

$ nm -g --demangle with-rename-flag/libmls_rust.a 2>/dev/null | grep REDACTED

0000000000000000 T _REDACTEDBridge$cxxbridge1$190$generateKeyPackage
                 U _REDACTEDBridge$cxxbridge1$190$generateKeyPackage
0000000000000000 T __ZN9REDACTEDBridge18generateKeyPackageENS_23GenerateKeyPackageInputE_rse4eba72a7f00581d

When linking against without-rename-flag/libmls_rust.a, REDACTEDBridge::generateKeyPackage(REDACTEDBridge::GenerateKeyPackageInput) is found but when linking against with-rename-flag/libmls_rust.a, it isn't.

It also seems like the flag breaks mangling somehow as such it could demangle REDACTEDBridge::generateKeyPackage(REDACTEDBridge::GenerateKeyPackageInput) but it failed to demangle __ZN9REDACTEDBridge18generateKeyPackageENS_23GenerateKeyPackageInputE_rse4eba72a7f00581d, although it seems like the linker doesn't particularly complain about this.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

I see. The rename logic processed all .o files in the archive, including C/C++ .o files from native libraries. These native symbols were not in exported_symbols, so they were incorrectly renamed.

@cezarbbb
Copy link
Copy Markdown
Contributor Author

I think I can filter by filename and only process .rcgu.o files (there should be no exceptions this way?).

@MicroDroid
Copy link
Copy Markdown

I have no idea, but let me test that already on my setup

@MicroDroid
Copy link
Copy Markdown

I think I'm like 99% sure renaming works flawlessly now.

So my setup was 2 Rust libraries being ported to C++ via cxx.rs and linked independently into a mobile app.

There were duplicate symbol errors, with 2 categories of symbols being duplicate:

  • cxx.rs's own symbols, but I wrote a script to rename those
  • Rust stdlib symbols

For one of the Rust libraries I built it with the -Zstaticlib-rename-internal-symbols flag and then ran the output through the script I wrote to process cxx.rs symbols, and then I built the mobile app and it just built without any issues.

That was for Android though, for iOS I'll get that tested very soon too, maybe within the next hour.

@MicroDroid
Copy link
Copy Markdown

Took me long time to test for iOS cause I'm having other unrelated issues with the iOS build, but nonetheless judging by how far I am I think the patch just works on iOS too ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-LLVM Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues. A-run-make Area: port run-make Makefiles to rmake.rs S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants