Reputation: 20628
I wrote simple code in C, Go and Rust.
foo.c
#include <stdio.h>
int main()
{
printf("hello\n");
return 0;
}
foo.go
package main
import "fmt"
func main() {
fmt.Println("hello");
}
foo.rs
fn main() {
println!("hello");
}
Then I built them all.
$ gcc -static -o cfoo foo.c
$ go build -o gofoo foo.go
$ rustc -o rustfoo foo.rs
They run fine.
$ ./cfoo; ./gofoo; ./rustfoo
hello
hello
hello
The binary of Rust executable was too small compared to the other two, so I suspected that it is not a static executable.
$ ls -l cfoo gofoo rustfoo
-rwxr-xr-x 1 lone lone 755744 Oct 23 21:17 cfoo
-rwxr-xr-x 1 lone lone 1906945 Oct 23 21:17 gofoo
-rwxr-xr-x 1 lone lone 253528 Oct 23 21:17 rustfoo
I confirmed that Rust does not produce a static executable.
$ ldd cfoo gofoo rustfoo
cfoo:
not a dynamic executable
gofoo:
not a dynamic executable
rustfoo:
linux-vdso.so.1 (0x00007ffe6dfb7000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fd8d9b75000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fd8d9b6b000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fd8d9b4a000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fd8d9b30000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fd8d996f000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd8d9bbb000)
Is there any way to produce a static executable for Rust?
I checked other similar answers and they talk about using musl. Is there no way to produce a static executable with glibc? If I must use an alternate way, can you provide a step by step with commands to produce a static executable with rustc
?
Upvotes: 9
Views: 8904
Reputation: 30577
It seems things may have changed since this was originally answered.
First, you need to make sure you have a statically linked glibc available on your system. I'm using a RHEL system, so I did that with:
sudo yum install glibc-static
I believe the Ubuntu / Debian equivalent is:
sudo apt-get install libc6-dev
After that, you pass the option -C target-feature=+crt-static
to rustc when compiling your program:
$ rustc -o rustfoo -C target-feature=+crt-static main.rs
$ ldd rustfoo
not a dynamic executable
Of course few people run rustc by hand. You can instruct cargo to pass this option to rustc using the RUSTFLAGS
environment variable, like this:
RUSTFLAGS="-C target-feature=+crt-static" cargo build --target x86_64-unknown-linux-gnu
The reason you have to add the --target
option, even if you are building for the host platform, is that if you don't then the options supplied via RUSTFLAGS
will be applied when building compile time code such as proc macros, etc which may cause those to fail to compile. If you explicitly specify a target platform then the RUSTFLAGS
are only applied when compiling code for the target platform. See also this bug report.
If you want it to always build statically like this, without needing an environment variable, then you can create a file .cargo/config.toml
within your project top directory, and put the following content into it:
[build]
rustflags = ["-C", "target-feature=+crt-static"]
target = "x86_64-unknown-linux-gnu"
References:
Upvotes: 21
Reputation: 100100
You need to compile for MUSL, otherwise Rust will depend on your libc.
Upvotes: 0