How to produce statically linked binary on OpenBSD


#1

I’m trying to produce a statically linked binary on OpenBSD. The reason it needs to be statically linked is that I intend for this binary to run early in the boot process. The binary would live in /sbin and should have the same linkage characteristics as the other tools in there:

$ ldd /sbin/mount
/sbin/mount:
        Start            End              Type Open Ref GrpRef Name
        000008457a4e3000 000008457a71c000 dlib 1    0   0      /sbin/mount

I’ve done a lot of research but most of the information out there appears largely irrelevant as it pertains to the inability of glibc to be statically linked, the use of musl libc, or Windows. As far as I can tell OpenBSD libc is perfectly capable of being statically linked. I just can’t work out how to convince Rust of this.

Some of the resources I’ve read so far:

Things I’ve tried/considered:

I’ve tried setting RUSTFLAGS="-C target-feature=+crt-static". It appears the intention of this flag is to enable static linking but it’s ignored on all platforms except Windows and Linux + musl.

I also tried a custom build script (build.rs) the emits lines like cargo:rustc-link-lib=static=c but that results in duplicate symbols as it’s trying to dynamically link the same library as well (at least I think that’s what’s happening).

Another approach that Shepmaster proposed in a StackOverflow answer is to take linking into my own hands via a custom target specification and linker invocation. I haven’t gone down this path yet as I’m trying to avoid building the linker invocation manually, but it could be an option.

Given that crt-static kinda looks like what I want I considered changing the libc crate to work like musl on Linux. I’m not sure how I’d get the rust compiler to use this version of libc though, perhaps this is possible with a replace section in Cargo.toml?

Any other thoughts or ideas?


#2

I tried patching the compiler to support crt-static but haven’t had much success there. It seems that for it to work I need to define a whole new target triple and configure it accordingly, which didn’t work for me as it affected how the compiler itself was built.

I also tried adding -C link-args=-static to RUSTFLAGS, which interestingly gets almost all the way there. The link stage fails because -Wl,-Bdynamic is also specified but if I remove that argument and rerun the command manually it does produce a static binary (that works)… not sure where that -Wl,-Bdynamic is coming from though, and how to suppress it.


#3

Have you made any progress on this?


#4

No I came to the conclusion that Rust on OpenBSD was a little too niche and bleeding edge at the moment and put the project on hold.