emk / rust-musl-builder

Docker images for compiling static Rust binaries using musl-libc and musl-gcc, with static versions of useful C libraries. Supports openssl and diesel crates.
Apache License 2.0
1.54k stars 193 forks source link

Binary not static #37

Closed bomgar closed 6 years ago

bomgar commented 6 years ago

Hi,

for a while i was using rust-musl-builder as a git submodule. So I did not update. I tried to update to master and now my binary is no longer static. (same with the dockerhub version)

» file target/x86_64-unknown-linux-musl/release/fw                                                                                                                                                                                                     
target/x86_64-unknown-linux-musl/release/fw: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib/ld64.so.1, BuildID[sha1]=bc7437143885536c8640f165e4fccbc4fdaf2ff9, with debug_info, not stripped

Here is my repo https://github.com/brocode/fw

With commit 8ea04b5f166b18dfa4bd5c49c771e2598284f87f everything works fine.

bomgar commented 6 years ago

I used git bisect to track it down further. Assuming I did nothing wrong commit https://github.com/emk/rust-musl-builder/commit/fcc6921ddb8b38a592d73c611395bd92a2c68cfb seems to cause my problem.

bomgar commented 6 years ago

This seems to fix my problem

diff --git a/Dockerfile b/Dockerfile
index 0b1ec00..07e4d1a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -19,11 +19,7 @@ RUN apt-get update && \
         curl \
         file \
         git \
-        musl-dev \
         musl-tools \
-        libpq-dev \
-        libssl-dev \
-        pkgconf \
         sudo \
         xutils-dev \
         && \

I have no idea why.

bomgar commented 6 years ago

I tried again with the master branch

diff --git a/Dockerfile b/Dockerfile
index 43bf2b6..be81849 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -21,9 +21,6 @@ RUN apt-get update && \
         git \
         musl-dev \
         musl-tools \
-        libpq-dev \
-        libsqlite-dev \
-        libssl-dev \
         pkgconf \
         sudo \
         xutils-dev \
emk commented 6 years ago

Could you please run ldd on your binary, and let me know what libraries it is trying to dynamically link?

We actually have a test case which verifies that we're using static linking on a sample executable, which I run on every release. See ./test-image for details. You might want to try running that on your system and seeing what output it produces.

It's possible that your program somehow differs from the static executable in an important way.

bomgar commented 6 years ago

Test test-image work. I have two other projects which work completely fine. As I wrote before removing the listed packages fixes the problem. I just don't understand why that is.

ldd output

» ldd target/x86_64-unknown-linux-musl/release/fw                                                                                                                                                                                                                                                                                                
        linux-vdso.so.1 (0x00007ffe9c37c000)
        libz.so.1 => /usr/lib/libz.so.1 (0x00007f8013406000)
        libc.so.6 => /usr/lib/libc.so.6 (0x00007f801304f000)
        /lib/ld64.so.1 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f801361d000)
bomgar commented 6 years ago

The project has a package.sh. If you add your builder there you should be able to reproduce the problem. Currently it is using a docker container with the fix I mentioned above (removing libpq-dev, libsqlite-dev and libssl-dev) .

Building it with ekidd/rust-musl-builder:1.24.0 yields a file not found error when executing fw

mriehl commented 6 years ago

I found this is related to the git2 dependency in fw.

If I add a git2 dependency to the test-image project and do something like let local = Repository::init("fkbr"); in main.rs (just to get it to actually use the lib) it's not a static binary anymore and the test fails.

What I also fail to understand is why the package installation of libssl-dev (pretty sure it's this one at this point) causes the binary to be dynamically linked.

mriehl commented 6 years ago

So I narrowed it down to the libssl-dev package (if it's present then depending on git2 creates a dynamically linked binary, if not the binary is static) and even further to the zlib1g-dev package (which libssl-dev depends upon).

So if zlib1g-dev is present then the binary is not static, but if it's absent it's static.

mriehl commented 6 years ago

Hah. Exporting the env variable LIBZ_SYS_STATIC="1" fixes it. The zlib1g-dev dep led me to https://github.com/alexcrichton/libz-sys/blob/master/build.rs which uses the env variable to find out if it should try to use a static libz. It also has special handling for musl but I guess the system zlib comes first in some cases (like when zlib1g-dev is installed).

I think it would be great to export the variable LIBZ_SYS_STATIC="1" in the musl builder image, because you definitely want a static zlib. Any objections to a PR @emk ?

mriehl commented 6 years ago

Can't test right now but according to the build.rs from libz-sys setting TARGET=musl should also work. Maybe that's better since it's more generic

emk commented 6 years ago

@mriehl Wow, good job tracking this down! I would definitely be interested in a PR (and it looks like @bomgar has proposed one).

bomgar commented 6 years ago

For anyone interested in a workaround:

Use docker run -e LIBZ_SYS_STATIC=1