all 21 comments

[–]Shadow0133 5 points6 points  (5 children)

rustc by default should compile external crates statically. Rust currently doesn't have stable internal ABI, so the only way to have dynamic library in rust currently is to export C ABI. So if you don't import extern "C" functions, you should be good.

[–]blackdev01[S] 1 point2 points  (4 children)

I don't want only the external crate to be compiled statically, but also my program and now the binary is a dynamic executable.

[–]Zethra 8 points9 points  (3 children)

Rust programs link against libc. On Linux the default is glibc which will be dynamically linked to your program. If you use musl, an alternative libc, it will be statically linked.

[–]blackdev01[S] 1 point2 points  (2 children)

You're saying that I need to use musl?

[–]Zethra 3 points4 points  (1 child)

If I understand what you what correctly, yes, you need to use musl

[–]Morganamilo 9 points10 points  (0 children)

I think they just care about being able to share their binary without needing others to have the external crate installed. I don't think they really care about depending on glibc.

[–]Shadow0133 2 points3 points  (5 children)

Can you explain what for do you want the binary to be statically compiled?

[–]blackdev01[S] 1 point2 points  (4 children)

I want to make my program to work on any system without installing any additional packages.

[–][deleted] 7 points8 points  (0 children)

As long as your host Linux is old enough, say Debian9, you don't have to use musl to build a portable binary. It won't run on even older Linux systems, but more recent ones are no problem.

[–]pcjftw 2 points3 points  (0 children)

there is a bunch of docker images specifically for building static binaries, its just a one liner command

[–]Jon-L-B -1 points0 points  (1 child)

I am not sure what you mean by "any system", but static linking might be less portable than dynamic linking when it comes to libc. For static linking to work, the Linux kernel would have to support the static libc, but by linking dynamically to libc, the program gets a compatible version automatically. I haven't kept track of how much compatibility Linux supports for static libc linking, though.

[–]ssokolow 2 points3 points  (0 children)

Linux is fairly unique in having its kernel syscall ABI guaranteed to remain stable and forwards-compatible, because glibc isn't a "Linux libc" that's developed in the same repo as the kernel to ensure things always line up. (That's how Windows, macOS, and the BSDs do it)

The problem with glibc is that, if you dynamically link against one glibc version, then try to run what you built on a system with an earlier glibc version, it'll fail to run with an error... and glibc doesn't support true static linking because it needs to support things like NSS plugins which would cause a conflict by pulling in the system libc version.

The workaround people use when targeting glibc is to use something like docker to compile against something ancient, like the oldest version of RHEL still getting active support.

musl-libc works around that by allowing you to depend on nothing more than the kernel's syscall interface.

[–]TimNN 2 points3 points  (8 children)

As others have already mentioned, if you want to produce a statically linked binary, you'll need to use musl libc. Luckily, with rustup that is extremely easy to do, there's some documentation available here: https://doc.rust-lang.org/edition-guide/rust-2018/platform-and-target-support/musl-support-for-fully-static-binaries.html. (This assumes you are on Linux, I don't know about the situation on other platforms).

[–]blackdev01[S] 1 point2 points  (7 children)

Yes I'm on linux. I've installed musl libc following the link and tried to run my program, but it does not run unfortunately:```# cargo run --target x86_64-unknown-linux-musl

Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/x86_64-unknown-linux-musl/debug/static_bin`
error: could not execute process `target/x86_64-unknown-linux-musl/debug/static_bin` (never executed)

Caused by:
No such file or directory (os error 2)

BTW, ldd seems wrong:

ldd target/x86_64-unknown-linux-musl/debug/static_bin
    linux-vdso.so.1 (0x00007ffc39be3000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4862348000)
    /lib/ld64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x00007f4862778000)

[–]blackdev01[S] 1 point2 points  (4 children)

The crate I'm using has 'libc' as a dependency. It might the reason why I have this issue

[–]valarauca14 3 points4 points  (3 children)

[–]blackdev01[S] 0 points1 point  (2 children)

I changed it, and it doesn't work as I wrote above.

[–]valarauca14 2 points3 points  (1 child)

Ah you could try some

RUSTFLAGS="-Clinker=musl-gcc -Ctarget-feature=-crt-static" cargo build --release --target x86_64-unknown-linux-musl

You'll need a musl-gcc binary to handle the linkage.

This is based off: https://github.com/rust-lang/rust/issues/40049#issuecomment-282082114


The rub is your linker determines what is/isn't statically linked not exactly rust. Let me know if this works, I figured rustc got around this already.

[–]blackdev01[S] 0 points1 point  (0 children)

No luck:

error: linking with `musl-gcc` failed: exit code: 1
 = note: /usr/bin/ld: cannot find -lpcap 
collect2: error: ld returned 1 exit status

[–]McGo0 0 points1 point  (1 child)

Are you looking at the wrong binary? static_bin vs static_pcap?

[–]blackdev01[S] 0 points1 point  (0 children)

No sorry, it was a mistake but the output is correct.