Recently, I updated the Rust toolchain to 1.70, and started to see a lot of warning like the following ones. It seems a staticlib for GNU target compiled with Rust 1.70 seems to generate incompatible binary with GNU. Before reporting to Rust's repository, I'd like to make sure I don't make some silly mistake since I'm not very familiar with the compiler things.
Warning: .drectve `-exclude-symbols:_ZN7testpkg11hello_world17ha68eef8a416aa303E ' unrecognized
Warning: corrupt .drectve at end of def file
The context is that, an OSS project, extendr, which I'm a member of, uses Rust to generate a staticlib for R programming language. Since R is GNU, the target needs to be GNU. This is what the minimal steps to reproduce the warning looks like. I also created a repository to reproduce the warning: GitHub - yutannihilation/rust170_gnu_warning (You can check the GHA results)
The warning happens on the last step, so it should be that the generated staticlib is incompatible with GCC, the GNU toolchain.
# compile Rust code to create a staticlib
cargo build --target=x86_64-pc-windows-gnu --lib --release
# compile the C code
gcc -c main.c -o main.o
# create DLL from the object and staticlib
gcc -o testpkgrust170_gnu_warning.dll main.o -L./target/x86_64-pc-windows-gnu/release -lrust170_gnu_warning -lws2_32 -ladvapi32 -luserenv -lbcrypt -lntdll
I couldn't find a reliable reference, but, reading several SO answers (e.g. https://stackoverflow.com/a/37676997), it seems this warning ("corrupt .drectve") indicates the incompatibility between compilers. Rust 1.70 upgrades LLVM to version 16, so I suspect there's some unexpected change in LLVM 16. Among the items described in the release note, this one feels related, since this is the only one that is related to linker directives.
I don't know exact the reason, my guess is that GNU linker doesn't support the .drective entries emitted by LLVM. though I think it should be safe to ignore the warnings, as those symbols are mangled rust symbols, they shouldn't conflict with C/C++ symbols. the only possible downside I can think of is the final linked artifact might be bloated with extra useless exports.
you can try to use lld instead of the GNU ld for the final linking step. or you might check if there's newer version of GNU toolchain that does support the directive entries.
GNU linker doesn't support the .drective entries emitted by LLVM
Yes. The question is, why the directives unsupported by GNU are emitted for GNU target? I feel this is not what the things are supposed to be. So I'm about to report to Rust's repository.
it should be safe to ignore the warnings
Yes and no. I agree we can ignore the warnings, but it seems the concern described in the LLVM's commit can be a real problem:
as all symbols are exported, it can easily overflow the max number of exported symbols in a DLL (65536).
Anyway, as the directive is not supported, I think there's no way to avoid this possible overflow.
you can try to use lld instead of the GNU ld for the final linking step.
Thanks for the suggestion. But, unfortunately, this is not possible. As I described above, since this is for R, the project needs to stick with the toolchain that compiles R.