Build in "external libraries"

Hi,
I try to compile app without need to install other dependieces on host so all libraries used in app shoul be static.
How to build release without using shared libraries?

$ cargo build --release 
   Compiling core v0.1.0 (/home/marcin/projects/rust/rust-nms/core)
   Compiling api v0.1.0 (/home/marcin/projects/rust/rust-nms/api)
   Compiling web v0.1.0 (/home/marcin/projects/rust/rust-nms/web)

    Finished release [optimized] target(s) in 4.46s
$ ldd target/release/nms
        linux-vdso.so.1 (0x00007ffe127ff000)
        libpq.so.5 => /lib/x86_64-linux-gnu/libpq.so.5 (0x00007fc42e337000)
        libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fc42e31c000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc42e2f9000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc42e1aa000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc42e1a4000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc42dfb2000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fc42e5d1000)
        libssl.so.1.1 => /lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007fc42df1e000)
        libcrypto.so.1.1 => /lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007fc42dc32000)
        libgssapi_krb5.so.2 => /lib/x86_64-linux-gnu/libgssapi_krb5.so.2 (0x00007fc42dbe5000)
        libldap_r-2.4.so.2 => /lib/x86_64-linux-gnu/libldap_r-2.4.so.2 (0x00007fc42db8f000)
        libkrb5.so.3 => /lib/x86_64-linux-gnu/libkrb5.so.3 (0x00007fc42dab2000)
        libk5crypto.so.3 => /lib/x86_64-linux-gnu/libk5crypto.so.3 (0x00007fc42da7f000)
        libcom_err.so.2 => /lib/x86_64-linux-gnu/libcom_err.so.2 (0x00007fc42da78000)
        libkrb5support.so.0 => /lib/x86_64-linux-gnu/libkrb5support.so.0 (0x00007fc42da69000)
        liblber-2.4.so.2 => /lib/x86_64-linux-gnu/liblber-2.4.so.2 (0x00007fc42da58000)
        libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007fc42da3c000)
        libsasl2.so.2 => /lib/x86_64-linux-gnu/libsasl2.so.2 (0x00007fc42da1f000)
        libgssapi.so.3 => /lib/x86_64-linux-gnu/libgssapi.so.3 (0x00007fc42d9d8000)
        libgnutls.so.30 => /lib/x86_64-linux-gnu/libgnutls.so.30 (0x00007fc42d802000)
        libkeyutils.so.1 => /lib/x86_64-linux-gnu/libkeyutils.so.1 (0x00007fc42d7fb000)
        libheimntlm.so.0 => /lib/x86_64-linux-gnu/libheimntlm.so.0 (0x00007fc42d7ef000)
        libkrb5.so.26 => /lib/x86_64-linux-gnu/libkrb5.so.26 (0x00007fc42d75c000)
        libasn1.so.8 => /lib/x86_64-linux-gnu/libasn1.so.8 (0x00007fc42d6b3000)
        libhcrypto.so.4 => /lib/x86_64-linux-gnu/libhcrypto.so.4 (0x00007fc42d67b000)
        libroken.so.18 => /lib/x86_64-linux-gnu/libroken.so.18 (0x00007fc42d662000)
        libp11-kit.so.0 => /lib/x86_64-linux-gnu/libp11-kit.so.0 (0x00007fc42d52c000)
        libidn2.so.0 => /lib/x86_64-linux-gnu/libidn2.so.0 (0x00007fc42d50a000)
        libunistring.so.2 => /lib/x86_64-linux-gnu/libunistring.so.2 (0x00007fc42d388000)
        libtasn1.so.6 => /lib/x86_64-linux-gnu/libtasn1.so.6 (0x00007fc42d370000)
        libnettle.so.7 => /lib/x86_64-linux-gnu/libnettle.so.7 (0x00007fc42d336000)
        libhogweed.so.5 => /lib/x86_64-linux-gnu/libhogweed.so.5 (0x00007fc42d2fe000)
        libgmp.so.10 => /lib/x86_64-linux-gnu/libgmp.so.10 (0x00007fc42d27a000)
        libwind.so.0 => /lib/x86_64-linux-gnu/libwind.so.0 (0x00007fc42d250000)
        libheimbase.so.1 => /lib/x86_64-linux-gnu/libheimbase.so.1 (0x00007fc42d23e000)
        libhx509.so.5 => /lib/x86_64-linux-gnu/libhx509.so.5 (0x00007fc42d1ee000)
        libsqlite3.so.0 => /lib/x86_64-linux-gnu/libsqlite3.so.0 (0x00007fc42d0c5000)
        libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007fc42d08a000)
        libffi.so.7 => /lib/x86_64-linux-gnu/libffi.so.7 (0x00007fc42d07e000)

How to make that all dependiency is build in executable?

Try building with the musl target.

https://doc.rust-lang.org/edition-guide/rust-2018/platform-and-target-support/musl-support-for-fully-static-binaries.html

Good to know, thank you very much.

It doesn't work :frowning: shared system libraries are still required :confused:

cargo build --target x86_64-unknown-linux-musl --release

[...]

   Compiling r2d2-diesel v1.0.0
   Compiling core v0.1.0 (/home/marcin/projects/rust/rust-nms/core)
   Compiling api v0.1.0 (/home/marcin/projects/rust/rust-nms/api)
   Compiling web v0.1.0 (/home/marcin/projects/rust/rust-nms/web)
   Compiling nms v0.1.0 (/home/marcin/projects/rust/rust-nms/nms)
    Finished release [optimized] target(s) in 1m 41s

$ ldd target/x86_64-unknown-linux-musl/release/nms
        linux-vdso.so.1 (0x00007fffa35e5000)
        libpq.so.5 => /lib/x86_64-linux-gnu/libpq.so.5 (0x00007f7df7321000)
        libssl.so.1.1 => /lib/x86_64-linux-gnu/libssl.so.1.1 (0x00007f7df728f000)
        libcrypto.so.1.1 => /lib/x86_64-linux-gnu/libcrypto.so.1.1 (0x00007f7df6fa3000)
        libgssapi_krb5.so.2 => /lib/x86_64-linux-gnu/libgssapi_krb5.so.2 (0x00007f7df6f56000)
        libldap_r-2.4.so.2 => /lib/x86_64-linux-gnu/libldap_r-2.4.so.2 (0x00007f7df6f00000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f7df6edd000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f7df6ce9000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f7df6ce3000)
        libkrb5.so.3 => /lib/x86_64-linux-gnu/libkrb5.so.3 (0x00007f7df6c06000)
        libk5crypto.so.3 => /lib/x86_64-linux-gnu/libk5crypto.so.3 (0x00007f7df6bd5000)
        libcom_err.so.2 => /lib/x86_64-linux-gnu/libcom_err.so.2 (0x00007f7df6bce000)
        libkrb5support.so.0 => /lib/x86_64-linux-gnu/libkrb5support.so.0 (0x00007f7df6bbf000)
        liblber-2.4.so.2 => /lib/x86_64-linux-gnu/liblber-2.4.so.2 (0x00007f7df6bac000)
        libresolv.so.2 => /lib/x86_64-linux-gnu/libresolv.so.2 (0x00007f7df6b90000)
        libsasl2.so.2 => /lib/x86_64-linux-gnu/libsasl2.so.2 (0x00007f7df6b73000)
        libgssapi.so.3 => /lib/x86_64-linux-gnu/libgssapi.so.3 (0x00007f7df6b2e000)
        libgnutls.so.30 => /lib/x86_64-linux-gnu/libgnutls.so.30 (0x00007f7df6958000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f7df75e0000)
        libkeyutils.so.1 => /lib/x86_64-linux-gnu/libkeyutils.so.1 (0x00007f7df6951000)
        libheimntlm.so.0 => /lib/x86_64-linux-gnu/libheimntlm.so.0 (0x00007f7df6943000)
        libkrb5.so.26 => /lib/x86_64-linux-gnu/libkrb5.so.26 (0x00007f7df68b0000)
        libasn1.so.8 => /lib/x86_64-linux-gnu/libasn1.so.8 (0x00007f7df6809000)
        libhcrypto.so.4 => /lib/x86_64-linux-gnu/libhcrypto.so.4 (0x00007f7df67d1000)
        libroken.so.18 => /lib/x86_64-linux-gnu/libroken.so.18 (0x00007f7df67b8000)
        libp11-kit.so.0 => /lib/x86_64-linux-gnu/libp11-kit.so.0 (0x00007f7df6680000)
        libidn2.so.0 => /lib/x86_64-linux-gnu/libidn2.so.0 (0x00007f7df665e000)
        libunistring.so.2 => /lib/x86_64-linux-gnu/libunistring.so.2 (0x00007f7df64dc000)
        libtasn1.so.6 => /lib/x86_64-linux-gnu/libtasn1.so.6 (0x00007f7df64c6000)
        libnettle.so.7 => /lib/x86_64-linux-gnu/libnettle.so.7 (0x00007f7df648c000)
        libhogweed.so.5 => /lib/x86_64-linux-gnu/libhogweed.so.5 (0x00007f7df6454000)
        libgmp.so.10 => /lib/x86_64-linux-gnu/libgmp.so.10 (0x00007f7df63ce000)
        libwind.so.0 => /lib/x86_64-linux-gnu/libwind.so.0 (0x00007f7df63a4000)
        libheimbase.so.1 => /lib/x86_64-linux-gnu/libheimbase.so.1 (0x00007f7df6392000)
        libhx509.so.5 => /lib/x86_64-linux-gnu/libhx509.so.5 (0x00007f7df6344000)
        libsqlite3.so.0 => /lib/x86_64-linux-gnu/libsqlite3.so.0 (0x00007f7df621b000)
        libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f7df61e0000)
        libffi.so.7 => /lib/x86_64-linux-gnu/libffi.so.7 (0x00007f7df61d2000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f7df6083000)

You will need to look up which dependencies those shared libraries come from and find the corresponding -sys crate. You can then check if the -sys crate has some special option to turn on static compilation for that -sys crate, and use that option if so.

If the -sys crate does not provide the option, the only way is to modify that -sys crate to add support for static linking.

You might also want to open an issue on those -sys crates and ask them to default to static linking when using the musl target, as recommended by this article.

In my case, diesel provides dependieces with libpq
diesel = { version="1.4.5", features = ["postgres"] }

and when I try to run executable build with MUSL I get segmentation fault

 target/x86_64-unknown-linux-musl/release/nms 
Initializing router
Starting server
🔧 Configured for production.
    => address: 0.0.0.0
    => port: 8000
    => log: critical
    => workers: 16
    => secret key: generated
    => limits: forms = 32KiB
    => keep-alive: 5s
    => read timeout: 5s
    => write timeout: 5s
    => tls: disabled
Warning: environment is 'production', but no `secret_key` is configured
Segmentation fault (core dumped)

Looking at the source for pq-sys which provides the postgres bindings, it seems like you might be able to build with the environment variable PQ_LIB_STATIC=true to get libpq to be linked statically. Not sure that thats what's causing the segfault but it's worth a shot.

Instead of statically linking everything, for an application with a large number of dynamically linked dependencies have you thought about putting it inside a Docker container?

Thank you, yes this should work but this causes another problems, because libpq needs another librararies which has to be set static also. With simple PQ_LIB_STATIC=true I get a lot of undefined references from linker.
I think that static linking with system's external libraries is not good idea.

Yes, I thought about this but docker isn't what I want to use. I'm going to create .deb and .rpm packages to provide it into production. So, in system packages I'll have to set dependieces and install it while installing my app.

I also don't know why :confused: Even with debug this only show "Segmentation fault" but in kern.log I'm getting this:

Mar 14 10:37:42 marcin-huawei kernel: [503224.325400] r2d2-worker-0[570760]: segfault at 0 ip 0000000000000000 sp 00007f4a0c3cb298 error 14
Mar 14 10:37:42 marcin-huawei kernel: [503224.325407] Code: Bad RIP value.
Mar 14 10:37:42 marcin-huawei kernel: [503224.325420] r2d2-worker-2[570762]: segfault at 0 ip 0000000000000000 sp 00007f4a0bfc2298 error 14
Mar 14 10:37:42 marcin-huawei kernel: [503224.325426] Code: Bad RIP value.

Thank you for interesting my issue.