Adding additional platform support for crt-static


#1

I am interested in adding additional platform support for crt-static (RFC 1721), specifically for OpenBSD, although if there are other candidates out there I’d be prepared to look into supporting them too. OpenBSD supports statically linking libc (the binaries in /sbin and /usr/sbin are in fact statically linked), so in theory should be able to operate like Windows where crt-static just enables static linking. This is in contrast to musl where it’s an entirely different target.

So far I have resorted to ridiculous hacks to create a statically linked Rust binary on OpenBSD.

Gory details of hackery

I set RUSTFLAGS to -C link-args=-static and specify a custom linker in .cargo/config:

[target.x86_64-unknown-openbsd]
linker = "/usr/src/sbin/rrc/static-linker"

that custom linker is just a python script that filters out the -Wl,-Bdynamic argument and passes the rest onto cc (clang):

static-linker:

#!/usr/bin/env python2.7

import os, sys

# Filter out dynamic command line argument
args = filter(lambda arg: arg != "-Wl,-Bdynamic", sys.argv[1:])

os.execvp("cc", args)

Looking over the PRs that introduced crt-static (rust, libc) I attempted patching the compiler:

--- src/liblibc/src/unix/mod.rs.orig
+++ src/liblibc/src/unix/mod.rs
@@ -225,10 +225,15 @@ cfg_if! {
     } else if #[cfg(any(target_os = "macos",
                         target_os = "ios",
                         target_os = "android",
-                        target_os = "openbsd",
                         target_os = "bitrig"))] {
         #[link(name = "c")]
         #[link(name = "m")]
+        extern {}
+    } else if #[cfg(target_os = "openbsd")] {
+        #[link(name = "c", kind = "static", cfg(target_feature = "crt-static"))]
+        #[link(name = "c", cfg(not(target_feature = "crt-static")))]
+        #[link(name = "m", kind = "static", cfg(target_feature = "crt-static"))]
+        #[link(name = "m", cfg(not(target_feature = "crt-static")))]
         extern {}
     } else if #[cfg(target_os = "haiku")] {
         #[link(name = "root")]

This built but the resulting compiler appears to work the same as the unpatched one (still produces dynamically linked binaries) and I’m kind of at a loss of what to try next. I’m looking for guidance on how to approach this, places to look, etc. Any help would be most appreciated.