1

I'm trying to statically build my rust application, using MUSL.

My application uses sqlcipher. This means a statically built executable must include the openssl and sqlcipher C libraries.

I'm using https://github.com/emk/rust-musl-builder, so I wrote a Dockerfile which starts with their dockerfile, which already provides a MUSL environment including a statically built musl-enabled openssl.

So "all I need" is to build sqlcipher and then my rust application. Unfortunately this has a proven very complicated for me.

Here is my current docker file:

FROM ekidd/rust-musl-builder

# sqlcipher requirements
ENV TZ=Europe/Ljubljana
RUN sudo sh -c "ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone"
RUN sudo apt update
RUN sudo apt install tcl -y

# sqlcipher
RUN VERS=4.4.1 && \
    cd /home/rust/libs && \
    curl -LO https://github.com/sqlcipher/sqlcipher/archive/v$VERS.tar.gz && \
    tar xzf v$VERS.tar.gz && cd sqlcipher-$VERS && \
    CC=musl-gcc ./configure  --host=x86_64-pc-linux-gnu --target=x86_64-linux-musl --prefix=/usr/local/musl --disable-tcl --disable-shared --with-crypto-lib=none --enable-static=yes --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC -DSQLCIPHER_CRYPTO_OPENSSL -I/usr/include/x86_64-linux-musl -I/usr/local/musl/include -I/usr/local/musl/include/openssl" LDFLAGS=" /usr/local/musl/lib/libcrypto.a" && \
    make && sudo make install && \
    cd .. && rm -rf v$VERS.tar.gz sqlcipher-$VERS

# bring in my rust source
ADD --chown=rust:rust ./ .

# build my rust code
ENV RUSTFLAGS='-L/usr/local/musl/lib  -L/usr/lib/x86_64-linux-musl  -L/lib/x86_64-linux-musl -C linker=musl-gcc -Clink-arg=/usr/local/musl/lib/libcrypto.a -Clink-arg=/usr/local/musl/lib/libsqlcipher.a -C link-arg=/lib/ld-musl-x86_64.so.1 -Clink-arg=/usr/lib/x86_64-linux-musl/libc.a -Ctarget-feature=-crt-static -Clink-arg=-no-pie -C target-feature=+crt-static'
ENV PKG_CONFIG_ALLOW_CROSS=1
ENV PKG_CONFIG_ALL_STATIC=true
ENV OPENSSL_STATIC=true
ENV LIBZ_SYS_STATIC=1
CMD cargo build --target x86_64-unknown-linux-musl --release --bin projectpad-cli && cp /home/rust/src/target/x86_64-unknown-linux-musl/release/projectpad-cli /host

(my rust source is at https://github.com/emmanueltouzery/projectpad2)

This succeeds entirely and generates a binary, but it's not statically linked:

ldd projectpad-cli 
    /lib/ld-musl-x86_64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x00007f56d6749000)
    linux-vdso.so.1 (0x00007fff301f7000)

file projectpad-cli
     projectpad-cli: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-musl-x86_64.so.1, with debug_info, not stripped

Attempting to run this binary crashes in malloc_usable_size () from /lib/ld-musl-x86_64.so.1.

I believe it's because my system doesn't have the MUSL linker and so it uses the glibc/gcc one, and this causes issues.

I'm thinking that if I could manage to produce a really static binary, that wouldn't have references to the linker, this would possibly work.

Any idea what I'm doing wrong? I experimented with some builder.rs printlns, but I currently don't have any.

1 Answer 1

1

OK, I found it...

I'm pretty sure the problem was the -C link-arg=/lib/ld-musl-x86_64.so.1 flag. This more or less forced a dynamic executable I think. Removing it fixed the issue :-)

# -*- mode: dockerfile -*-
#
# An example Dockerfile showing how to add new static C libraries using
# musl-gcc.

FROM ekidd/rust-musl-builder

# https://rtfm.co.ua/en/docker-configure-tzdata-and-timezone-during-build/
ENV TZ=Europe/Ljubljana
RUN sudo sh -c "ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone"

RUN sudo apt update

RUN sudo apt install tcl -y

# Build a static copy of sqlcipher.
# https://github.com/sqlcipher/sqlcipher/issues/132#issuecomment-122908672 
# also related https://discuss.zetetic.net/t/cross-compile-sqlicipher-for-arm/2104/4
# https://github.com/sqlcipher/sqlcipher/issues/276
# https://github.com/rust-lang/rust/issues/40049
RUN VERS=4.4.1 && \
    cd /home/rust/libs && \
    curl -LO https://github.com/sqlcipher/sqlcipher/archive/v$VERS.tar.gz && \
    tar xzf v$VERS.tar.gz && cd sqlcipher-$VERS && \
    CC=musl-gcc ./configure  --host=x86_64-pc-linux-gnu --target=x86_64-linux-musl --prefix=/usr/local/musl --disable-tcl --disable-shared --with-crypto-lib=none --enable-static=yes --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC -DSQLCIPHER_CRYPTO_OPENSSL -I/usr/include/x86_64-linux-musl -I/usr/local/musl/include -I/usr/local/musl/include/openssl" LDFLAGS=" /usr/local/musl/lib/libcrypto.a" && \
    make && sudo make install && \
    cd .. && rm -rf v$VERS.tar.gz sqlcipher-$VERS

ADD --chown=rust:rust ./ .

# https://stackoverflow.com/questions/40695010/how-to-compile-a-static-musl-binary-of-a-rust-project-with-native-dependencies
# https://github.com/rust-lang/rust/issues/54243

ENV RUSTFLAGS='-L/usr/local/musl/lib  -L/usr/lib/x86_64-linux-musl  -L/lib/x86_64-linux-musl -C linker=musl-gcc -Clink-arg=/usr/local/musl/lib/libcrypto.a -Clink-arg=/usr/local/musl/lib/libsqlcipher.a -Clink-arg=/usr/lib/x86_64-linux-musl/libc.a'
ENV PKG_CONFIG_ALLOW_CROSS=1
ENV PKG_CONFIG_ALL_STATIC=true
ENV OPENSSL_STATIC=true
ENV LIBZ_SYS_STATIC=1
CMD cargo build --target x86_64-unknown-linux-musl --release --bin projectpad-cli && cp /home/rust/src/target/x86_64-unknown-linux-musl/release/projectpad-cli /host
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.