How to link openssl statically

According to the docs OPENSSL_STATIC=1 should be enough, but when I check the target with ldd, I get the following:

	linux-vdso.so.1 (0x00007fffb0fea000)
	libssl.so.1.1 => /lib64/libssl.so.1.1 (0x00007f3a70d69000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f3a70b65000)
	libcrypto.so.1.1 => /lib64/libcrypto.so.1.1 (0x00007f3a706dd000)
	librt.so.1 => /lib64/librt.so.1 (0x00007f3a704d5000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f3a702b6000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f3a7009f000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f3a6fcbc000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f3a71f26000)
	libm.so.6 => /lib64/libm.so.6 (0x00007f3a6f967000)
	libz.so.1 => /lib64/libz.so.1 (0x00007f3a6f750000)

where one can still see that libcrypto and libssl are still linked dynamically.

Note that my program does not link to openssl directly, but via the prometheus crate which requires it.

I installed openssl-static, openssl-devel and openssl.

pkg-config --libs openssl 
-lssl -lcrypto
pkg-config --static --libs openssl
-lssl -lz -ldl -lz -ldl -lcrypto -lz -ldl 

Note that during the build I get a warning

   // snip
   Compiling openssl-sys v0.9.23
   Compiling idna v0.1.4
   Compiling thread_local v0.3.5
   Compiling solicit v0.4.4
   Compiling bytes v0.4.5
   Compiling csv-core v0.1.3
   Compiling aho-corasick v0.6.4
   Compiling aho-corasick v0.5.3
   Compiling syn v0.11.11
   Compiling num-iter v0.1.34
   Compiling tempfile v2.2.0
   Compiling statrs v0.9.0
   Compiling url v1.6.0
   Compiling csv v1.0.0-beta.5
   Compiling regex v0.2.3
   Compiling num v0.1.41
   Compiling gag v0.1.9
   Compiling thread-id v2.0.0

warning: redundant linker flag specified for library `z`

warning: redundant linker flag specified for library `dl`

warning: redundant linker flag specified for library `z`

warning: redundant linker flag specified for library `dl`
    // snip
```

With verbose:

```
     Running `rustc --crate-name openssl_sys /home/f/.cargo/registry/src/github.com-1ecc6299db9ec823/openssl-sys-0.9.23/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=3be85fe6db4223d7 -C extra-filename=-3be85fe6db4223d7 --out-dir /home/f/Projects/myapp/target/debug/deps -L dependency=/home/f/Projects/myapp/target/debug/deps --extern libc=/home/f/Projects/myapp/target/debug/deps/liblibc-4f3539ec4d4c1da4.rlib --cap-lints allow --cfg 'osslconf="OPENSSL_NO_EC2M"' --cfg ossl110 --cfg ossl110f -l ssl -l z -l dl -l z -l dl -l crypto -l z -l dl`
```

Any hints/tipps on how to make this work?
1 Like

So I found this: https://github.com/sfackler/rust-openssl/issues/183

Which says essentiall OPENSSL_STATIC is ignore unless OPENSSL_LIB_DIR and OPENSSL_INCLUDE_DIR are specified:

$ env
OPENSSL_STATIC=yes
OPENSSL_LIB_DIR=/usr/lib64/
OPENSSL_INCLUDE_DIR=/usr/include/
$ exa -1 /usr/lib64  | rg "ssl|crypto"
libssl.so -> libssl.so.1.1.0g
libssl.so.1.0.2m
libssl.so.1.1 -> libssl.so.1.1.0g
libssl.so.1.1.0g
libssl.so.10 -> libssl.so.1.0.2m
libssl3.so
libcrypto.so -> libcrypto.so.1.1.0g
libcrypto.so.1.0.2m
libcrypto.so.1.1 -> libcrypto.so.1.1.0g
libcrypto.so.1.1.0g
libcrypto.so.10 -> libcrypto.so.1.0.2m
libcryptopp.so.6 -> libcryptopp.so.6.0.0
libcryptopp.so.6.0.0
// and a few more

$ cargo clean
$ cargo build
   /// snip
   Compiling csv v1.0.0-beta.5
error: could not find native static library `ssl`, perhaps an -L flag is missing?

error: Could not compile `openssl-sys`.
warning: build failed, waiting for other jobs to finish...
error: build failed
     Running `rustc --crate-name openssl_sys /home/f/.cargo/registry/src/github.com-1ecc6299db9ec823/openssl-sys-0.9.23/src/lib.rs --crate-type lib --emit=dep-info,link -C debuginfo=2 -C metadata=e45e5731dbca71b8 -C extra-filename=-e45e5731dbca71b8 --out-dir /home/f/Projects/myapp/target/debug/deps -L dependency=/home/f/Projects/myapp/target/debug/deps --extern libc=/home/f/Projects/myapp/target/debug/deps/liblibc-2c6ca039d96103da.rlib --cap-lints allow -L native=/usr/lib64/ --cfg 'osslconf="OPENSSL_NO_EC2M"' --cfg ossl110 --cfg ossl110f -l static=ssl -l static=crypto`

That's how far I get, but adding an -L flag does not seem to change much.

Any hints/help?

You need a statically compiled openssl library in the first place. Most default packages on distributions don't have that, so you need to look for either another package doing this or compiling openssl manually to a static library.

Actually it can not work. I had to copy all the static libs into /usr/local/lib64/ and thus it would alaways link against the dynamic version.

So the above issues actually arose since I accidentally erased openssl-static again.

Now that libcrypto and libssl are linking, I get issues regarding zlib.

As the exa command showed you, there is no static build for ssl and crypto. You need to compile it yourself and point OPENSSL_LIB_DIR and OPENSSL_INCLUDE_DIR to it.

$ env | rg OPENSSL_        
OPENSSL_STATIC=yes
OPENSSL_INCLUDE_DIR=/usr/include/
OPENSSL_LIB_DIR=/usr/local/lib64/

and after installib zlib-static and openssl-static

$ exa -1 /usr/lib64 | rg "\.a$"
libc_nonshared.a
libcrypto.a
libg.a
libieee.a
libimaevm.a
libmcheck.a
libmvec_nonshared.a
libpthread_nonshared.a
librpcsvc.a
libssl.a
libz.a

which I copied to /usr/local/lib64

$ exa -1 /usr/local/lib64  
libcrypto.a
libcrypto.so
libcrypto.so.1.0.2m
libcrypto.so.1.1
libcrypto.so.1.1.0g
libcrypto.so.10
libcryptopp.so.6
libcryptopp.so.6.0.0
libssl.a
libssl.so
libssl.so.1.0.2m
libssl.so.1.1
libssl.so.1.1.0g
libssl.so.10
libssl3.so
libz.a

ending up with:

  = note: /home/f/Projects/myapp/target/debug/deps/libopenssl_sys-eb87722056d2a428.rlib(c_zlib.o): In function `zlib_stateful_expand_block':
          (.text+0x3b): undefined reference to `inflate'
          /home/f/Projects/myapp/target/debug/deps/libopenssl_sys-eb87722056d2a428.rlib(c_zlib.o): In function `zlib_stateful_compress_block':
          (.text+0xa4): undefined reference to `deflate'
          /home/f/Projects/myapp/target/debug/deps/libopenssl_sys-eb87722056d2a428.rlib(c_zlib.o): In function `zlib_stateful_finish':
          (.text+0xd9): undefined reference to `inflateEnd'
          (.text+0xe2): undefined reference to `deflateEnd'
          /home/f/Projects/myapp/target/debug/deps/libopenssl_sys-eb87722056d2a428.rlib(c_zlib.o): In function `zlib_stateful_init':
          (.text+0x1a8): undefined reference to `inflateInit_'
          (.text+0x21a): undefined reference to `deflateInit_'
          /home/f/Projects/myapp/target/debug/deps/libopenssl_sys-eb87722056d2a428.rlib(c_zlib.o): In function `bio_zlib_ctrl':
          (.text+0x3dc): undefined reference to `deflate'
          (.text+0x5a4): undefined reference to `zError'
          /home/f/Projects/myapp/target/debug/deps/libopenssl_sys-eb87722056d2a428.rlib(c_zlib.o): In function `bio_zlib_write':
          (.text+0x6b0): undefined reference to `deflate'
          (.text+0x76c): undefined reference to `zError'
          (.text+0x7df): undefined reference to `deflateInit_'
          /home/f/Projects/myapp/target/debug/deps/libopenssl_sys-eb87722056d2a428.rlib(c_zlib.o): In function `bio_zlib_read':
          (.text+0x8c8): undefined reference to `inflate'
          (.text+0x944): undefined reference to `zError'
          (.text+0x9c5): undefined reference to `inflateInit_'
          /home/f/Projects/myapp/target/debug/deps/libopenssl_sys-eb87722056d2a428.rlib(c_zlib.o): In function `bio_zlib_free':
          (.text+0xa35): undefined reference to `inflateEnd'
          (.text+0xa60): undefined reference to `deflateEnd'
          collect2: error: ld returned 1 exit status

Please check the follow up above this

This might not be exactly what you're looking for, but @japaric has a repo that discusses how to get OpenSSL to cross compile (I presume statically): https://github.com/japaric/cross

Well this even fails to start building:

$ cross build
Unable to find image 'japaric/x86_64-unknown-linux-gnu:v0.1.14' locally
Trying to pull repository docker.io/japaric/x86_64-unknown-linux-gnu ... 
sha256:5ffa267d810f5e4906a2482a19d7b47a4e6f27778b81864df058b68e6abae9ec: Pulling from docker.io/japaric/x86_64-unknown-linux-gnu
93a256801089: Pull complete 
cd246578dce9: Pull complete 
f0c93f69d03b: Pull complete 
d8f4936186e9: Pull complete 
0ca90a15a5fb: Pull complete 
196074e30343: Pull complete 
cacd8e87cca3: Pull complete 
89b11c340cb4: Pull complete 
3bc3b68f2993: Pull complete 
51031edc0e16: Pull complete 
917e54992537: Pull complete 
e92d71a64a15: Pull complete 
Digest: sha256:5ffa267d810f5e4906a2482a19d7b47a4e6f27778b81864df058b68e6abae9ec
Status: Downloaded newer image for docker.io/japaric/x86_64-unknown-linux-gnu:v0.1.14
sh: 1: cargo: Permission denied

where the normal cargo

$ cargo build

works just fine.

$ cross build --target x86_64-unknown-linux-musl
sh: 1: cargo: Permission denied

where

$ cargo build --target x86_64-unknown-linux-musl
// snip
   Compiling rust-crypto v0.2.36
error: failed to run custom build command for `rust-crypto v0.2.36`

Fails as expected.

If you're fine with using musl, you have to compile openssl with musl first (and any other C dependencies)

Tbh, this exactly the rabbit hole I wanted to avoid going down by using the packaged static libs of fedora.

Considering your ldd output it would just be openssl no? It's pretty straightforward.

Unfortunately no. Once crypt and ssl are linked, the next level is zlib which seems to be a bit more nasty since it is dependency of the C library but not of the rust crate.

Did you manage to find a solution?

The only solution I cam up with was using a container which has musl and statically compiled openssl and lz in it.

Checkout these:

https://github.com/emk/rust-musl-builder
https://github.com/clux/muslrust

Since I am using concourse ci and I can easily hook the container as environment into concourse ci, that was good enough for me.

Note that you still have to setup the env variables for OPENSSL accordingly to my previous posts!

I recommend to always use ldd on the resulting binary to verify.