12

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?

globin
  • 432
  • 5
  • 13
  • 2
    You are asking about "portable" binaries, but you only list one system (Ubuntu) without any version information. Are there multiple systems involved? If so what are the distributions and their versions? – Shepmaster Dec 06 '14 at 17:47

2 Answers2

6

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.

Graydon Hoare
  • 436
  • 4
  • 3
5

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
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
etreus
  • 51
  • 1
  • 2