49
votes

I am trying to create a static executable with Rust. I am not trying to statically link a particular library, 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 can convince Rust to replicate that.)

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

2
Perhaps the -C link-args='...' option can help you? - llogiq
Note that your question only pertains to Linux - AFAIK, you cannot statically link executables on OS X. I'm not sure about Windows. - Shepmaster
You might want to take a look at using musl instead of glibc wih rust - Renato Zannon
This internals thread may also be of interest. It also points towards musl. - Shepmaster
@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. - David X

2 Answers

36
votes

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:

33
votes

Rust statically links everything but glibc (and libgcc, iirc) by default.

If you want to get a 100% statically linked binary, you can use MUSL with 1.1. https://github.com/rust-lang/rust/pull/24777 is the initial support, we hope to make it much easier to use in the future.