emk / rust-musl-builder

Docker images for compiling static Rust binaries using musl-libc and musl-gcc, with static versions of useful C libraries. Supports openssl and diesel crates.
Apache License 2.0
1.54k stars 193 forks source link

Has anybody succeeded with static build with dependent C++ library? #65

Closed izderadicka closed 5 years ago

izderadicka commented 5 years ago

Hi,

I'm trying to build static binary, which depends on taglib, which is C++ library with C bindings. I use this rust crate, which binds this library - https://github.com/ebassi/taglib-rust.

After bit of playing around I ended up with link failure, where only two symbols are missing __dso_handle and __sprintf_chk - first one seems to be generic problem of static linking of C++ library - as refered here https://github.com/rust-lang/rust/issues/36710#issuecomment-364623950 (with some possible workaround), for second symbol I'm not sure - it looks like some incompatibility between glibc and musl libc? Musl faq says "The existing libstdc++ is actually compatible with musl in most cases and could be used by copying it into the musl library path".

Here are steps I've done to compile (using this image):

cd ..
curl -sL https://taglib.org/releases/taglib-1.11.1.tar.gz | tar xzv
cd taglib-1.11.1/
CC=musl-gcc CPPFLAGS=-I/usr/local/musl/include cmake  -DCMAKE_INSTALL_PREFIX:PATH=/usr/local/musl .
make && sudo make install
cd ../src

# in ~/.cargo/config add
# [target.x86_64-unknown-linux-musl]
# rustflags=["-C", "link-arg=-lstdc++", "-C", "link-arg=-lz"]
sudo cp /usr/lib/gcc/x86_64-linux-gnu/5/libstdc++.a /usr/local/musl/lib

cargo build --release

And got this error:

= note: /usr/local/musl/lib//libstdc++.a(system_error.o): In function `_GLOBAL__sub_I_system_error.cc':                                                                                                    
          (.text.startup._GLOBAL__sub_I_system_error.cc+0x3): undefined reference to `__dso_handle'                                                                                                          
          /usr/local/musl/lib//libstdc++.a(system_error.o): In function `_GLOBAL__sub_I_system_error.cc':                                                                                                    
          (.text.startup._GLOBAL__sub_I_system_error.cc+0x21): undefined reference to `__dso_handle'                                                                                                         
          /home/rust/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-musl/lib/libstd-cd33df8f773a8d34.rlib(std-cd33df8f773a8d34.std.qsu1i6tj-cgu.2.rcgu.o):(.data._rust_extern_with_linkage___dso_handle.llvm.11799784290520478383+0x0): undefined reference to `__dso_handle'
          /usr/local/musl/lib//libtag_c.a(tag_c.cpp.o): In function `__static_initialization_and_destruction_0(int, int)':                                                                                   
          tag_c.cpp:(.text+0xe66): undefined reference to `__dso_handle'                                                                                                                                     
          tag_c.cpp:(.text+0xe84): undefined reference to `__dso_handle'                                                                                                                                     
          /usr/local/musl/lib//libtag.a(mpegfile.cpp.o):mpegfile.cpp:(.text+0x19fe): more undefined references to `__dso_handle' follow                                                                      
          /usr/local/musl/lib//libstdc++.a(cp-demangle.o): In function `d_print_comp_inner':                                                                                                                 
          (.text+0x4007): undefined reference to `__sprintf_chk'                                                                                                                                             
          /usr/local/musl/lib//libstdc++.a(cp-demangle.o): In function `d_print_comp_inner':                                                                                                                 
          (.text+0x5869): undefined reference to `__sprintf_chk'                                                                                                                                             
          /usr/local/musl/lib//libstdc++.a(cp-demangle.o): In function `d_print_comp_inner':                                                                                                                 
          (.text+0x5cef): undefined reference to `__sprintf_chk'                                                                                                                                             
          /usr/local/musl/lib//libstdc++.a(cp-demangle.o): In function `d_print_comp_inner':                                                                                                                 
          (.text+0x5e56): undefined reference to `__sprintf_chk'                                                                                                                                             
          /usr/local/musl/lib//libstdc++.a(cp-demangle.o): In function `d_print_comp_inner':                                                                                                                 
          (.text+0x69c6): undefined reference to `__sprintf_chk'                                                                                                                                             
          /usr/local/musl/lib//libstdc++.a(cp-demangle.o):(.text+0x87b8): more undefined references to `__sprintf_chk' follow                                                                                
          /usr/local/musl/lib//libstdc++.a(messages_members.o): In function `(anonymous namespace)::get_catalogs()':                                                                                         
          (.text._ZN12_GLOBAL__N_112get_catalogsEv+0xa1): undefined reference to `__dso_handle'                                                                                                              
          /usr/local/musl/lib//libstdc++.a(messages_members_cow.o): In function `(anonymous namespace)::get_catalogs()':                                                                                     
          (.text._ZN12_GLOBAL__N_112get_catalogsEv+0xa1): undefined reference to `__dso_handle'                                                                                                              
          /usr/bin/ld: /home/rust/src/target/x86_64-unknown-linux-musl/release/deps/audioserve-ab76b24750bd4658: hidden symbol `__dso_handle' isn't defined                                                  
          /usr/bin/ld: final link failed: Bad value                                                                                                                                                          
          collect2: error: ld returned 1 exit status  

My question is if somebody has experiences with using C++ library in static build, if I'm doing something wrong or if there are any recommendation how to process, I'm not much expert on c/c++, I saw that possibily of custom build script, but I guess it'll still not solve the problem with second symbol __sprintf_chk.

Thanks

emk commented 5 years ago

I'm sorry to hear about this problem!

Unfortunately, you should probably assume that fixing a complicated C or C++ library to build and work with a musl-libc cross compiler can be very tricky. I usually expect to spend about 4 hours debugging problems like these whenever I add a new C library, and that's with lots of web searches for similar problems. Basically, static linking is a bit of a hack, and not all libraries and toolchains support it. You can either push through and find a solution, or you can use regular dynamic linking. I wish I had a better answer for you. :-(

jeromegn commented 5 years ago

I've had a lot of success with statically linking C++ libs when I ran my build inside a alpine container with an explicit target for alpine musl.

For example: https://github.com/superfly/fly.rs/blob/master/Dockerfile