Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Portable binaries with Rust

I have problems building a portable executable with rust.

Running an executable simply built with cargo build on Ubuntu fails with

./test: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.14' not found (required by ./test)

Building with rustc ... -C link-args=-static fails to link correctly (output of ld ./test):

ld: error in ./test(.eh_frame); no .eh_frame_hdr table will be created.

Is there a way around this except building on an older system with an old glibc version?

like image 726
globin Avatar asked Oct 05 '14 12:10

globin


2 Answers

To avoid GLIBC errors, you can compile your own version of Rust against a static alternative libc, musl.

Get the latest stable release of musl and build it with option --disable-shared:

$ mkdir musldist
$ PREFIX=$(pwd)/musldist
$ ./configure --disable-shared --prefix=$PREFIX

then build Rust against musl:

$ ./configure --target=x86_64-unknown-linux-musl --musl-root=$PREFIX --prefix=$PREFIX

then build your project

$ echo 'fn main() { println!("Hello, world!"); }' > main.rs
$ rustc --target=x86_64-unknown-linux-musl main.rs
$ ldd main
    not a dynamic executable

For more information, look at the advanced linking section of the documentation.

As reported in the original documentation:

However, you may need to recompile your native libraries against musl before they can be linked against.


You can also use rustup.

Remove old Rust installed by rustup.sh

$ sudo /usr/local/lib/rustlib/uninstall.sh # only if you have 
$ rm $HOME/.rustup

Install rustup

$ curl https://sh.rustup.rs -sSf | sh
$ rustup default nightly  #just for ubuntu 14.04 (stable Rust 1.11.0 has linking issue)
$ rustup target add x86_64-unknown-linux-musl
$ export PATH=$HOME/.cargo/bin:$PATH
$ cargo new --bin hello && cd hello
$ cargo run --target=x86_64-unknown-linux-musl
$ ldd target/x86_64-unknown-linux-musl/debug/hello
    not a dynamic executable
like image 61
etreus Avatar answered Nov 11 '22 21:11

etreus


Glibc is not linked statically (much as we might have liked to, it goes out of its way to prevent this). As a result, the system libraries (libstd and such) are always dependent on the glibc version on which they were built. This is why the buildbots in the linux cluster mozilla uses are/were old versions of centos.

See https://github.com/rust-lang/rust/issues/9545 and https://github.com/rust-lang/rust/issues/7283

Unfortunately at this time I believe there is no workaround aside from making sure you build on a system with an older glibc than you're going to deploy to.

like image 45
Graydon Hoare Avatar answered Nov 11 '22 20:11

Graydon Hoare