94

I am trying to create a static executable with Rust. I am not trying to link a particular library statically, I am trying to create a executable which does not use dynamic linking at all. I have the following (otherwise working) test:

$ cat hello.rs
fn main()
    {
    print!("Hello, world!\n");
    }
$ rustc hello.rs -o hello
$ file hello
hello: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV),
 dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, [etc]

Note the dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2. Static executables have statically linked instead. (And in my case corrupted section header size, although I would be pleasantly astonished if I could convince Rust to replicate that.)

What options do I need to pass to rustc to get it to generate an actual static executable (for concreteness: one which even file agrees is statically linked).

13
  • Perhaps the -C link-args='...' option can help you? Commented Aug 2, 2015 at 13:49
  • Note that your question only pertains to Linux - AFAIK, you cannot statically link executables on OS X. I'm not sure about Windows. Commented Aug 2, 2015 at 14:41
  • 3
    You might want to take a look at using musl instead of glibc wih rust Commented Aug 2, 2015 at 15:14
  • 1
    This internals thread may also be of interest. It also points towards musl. Commented Aug 2, 2015 at 16:40
  • 1
    @Mikhail, I don't know the precise details on other systems, but on linux (and give or take register allocation most other unixes) print bottoms out (via either function calls or inlining) to mov eax,1 ; mov ebx,fdout ; mov ecx bufptr ; mov edx buflen. It's probably possible to design a system call interface that truly requires dynamic linking, but only a raging incompetent would do so for a general purpose OS. Commented Aug 2, 2015 at 22:21

2 Answers 2

78

Rust statically links everything except glibc (and libgcc) by default.

If you want a 100% statically linked binary, you can use MUSL libc, which supports both arm64 and x86_64

To compile for x86_64:

rustup target add x86_64-unknown-linux-musl
cargo build --target=x86_64-unknown-linux-musl

For arm64:

rustup target add aarch64-unknown-linux-musl
cargo build --target=aarch64-unknown-linux-musl
Sign up to request clarification or add additional context in comments.

3 Comments

In 2019, is musl still the only way to get 100% statically linked binary? Can we get 100% statically linked binary with glibc now?
I don’t believe that glibc really intends to ever support it as a first-class thing, though I could be wrong.
This works (rustc 1.77.1), but note that the binary gets placed in target/x86_64-unknown-linux-musl/release
73

Since Rust 1.19, you can statically link the C runtime (CRT) to avoid this very common situation on Windows:

The program can't start because VCRUNTIME140.dll is missing from your computer. Try reinstalling the program to fix this problem.

Add this to your .cargo/config file, using the appropriate target triple for your platform:

[target.x86_64-pc-windows-msvc]
rustflags = ["-C", "target-feature=+crt-static"]

An alternative to editing .cargo/config is to pass -C target-feature=+crt-static to rustc by hand.

See also:

5 Comments

This compiler option is now also available for linux-gnu targets since 1.48. github.com/rust-lang/rust/blob/master/…
how does one do this when using cargo build?
this seems to cause proc macro dependencies unable to build
You need to specify the target, see stackoverflow.com/questions/58526782/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.