In Solang, a Solidity compiler, we use LLVM (via inkwell) for emitting code and wasm-opt for optimizing our Wasm artifacts.
We noticed that, starting from version 0.114.0 on, wasm-opt introduces many namespace conflicts during linking, if it is used together with llvm-sys or as a transitive dependency.
= note: /usr/bin/ld: /home/glow/code/foo/target/debug/deps/libllvm_sys-a8e7e255aa417530.rlib(Debug.cpp.o):(.bss._ZN4llvm9DebugFlagE+0x0): multiple definition of `llvm::DebugFlag'; /home/gl ow/code/foo/target/debug/deps/libwasm_opt_sys-39024ee919d3d0a2.rlib(4036ad2f21ce3a71-LLVMDebug.o):/home/glow/code/foo/target/debug/build/wasm-opt-sys-6495f62a81ee79e6/out/LLVMDebug.cpp:43: first defined here
1 /usr/bin/ld: /home/glow/code/foo/target/debug/deps/libllvm_sys-a8e7e255aa417530.rlib(Debug.cpp.o): in function `llvm::dbgs() [clone .localalias]':
2 Debug.cpp:(.text._ZN4llvm4dbgsEv+0x0): multiple definition of `llvm::dbgs()'; /home/glow/code/foo/target/debug/deps/libwasm_opt_sys-39024ee919d3d0a2.rlib(4036ad2f21ce3a71-LLVMDeb ug.o):/home/glow/code/foo/target/debug/build/wasm-opt-sys-6495f62a81ee79e6/out/LLVMDebug.cpp:148: first defined here
...
Path.cpp:(.text._ZN4llvm3sys4path6nativeERKNS_5TwineERNS_15SmallVectorImplIcEENS1_5StyleE+0x0): multiple definition of `llvm::sys::path::native(llvm::Twine const&, llvm::SmallVectorImpl&, llvm::sys::path::Style)'; /home/glow/code/foo/target/debug/deps/libwasm_opt_sys-39024ee919d3d0a2.rlib(dae784741d7c58d5-Path.o):/home/glow/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasm-opt-sys-0.114.1/binaryen/third_party/llvm-project/Path.cpp:477: first defined here
collect2: error: ld returned 1 exit status
On a quick glance this seems to be caused by wasm-opt including a bunch of LLVM source dependencies.
This leaves anyone depending on LLVM and wasm-opt at the same time in an unfortunate situation.
To make matters worse, while Linux ld detects that and aborts the compilation, we noticed on our CI that on Mac (arm) the problem is worse: The linker on MacOS doesn't seem to care and compiles it anyways, instead resulting in a broken build artifact segfaulting at runtime ๐
Minimal reproducer
Just cargo build on a new rust project with the following:
Cargo.toml
[package] name = "foo" version = "0.1.0" edition = "2021" [dependencies] llvm-sys = "150.0.0" wasm-opt = "0.114"
src/main.rs
fn main() { unsafe { llvm_sys::core::LLVMModuleCreateWithName(std::ptr::null()) }; wasm_opt::OptimizationOptions::new_opt_level_0(); }