rust - rust:构建一个静态链接的二进制文件,包括外部 C 库
问题描述
我正在尝试使用 MUSL 静态构建我的 rust 应用程序。
我的应用程序使用 sqlcipher。这意味着静态构建的可执行文件必须包含 openssl 和 sqlcipher C 库。
我正在使用https://github.com/emk/rust-musl-builder,所以我写了一个Dockerfile
以他们的 dockerfile 开头的,它已经提供了一个 MUSL 环境,包括一个静态构建的支持 musl 的 openssl。
所以“我所需要的”就是构建 sqlcipher,然后构建我的 rust 应用程序。不幸的是,这对我来说非常复杂。
这是我当前的 docker 文件:
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
(我的锈源在https://github.com/emmanueltouzery/projectpad2)
这完全成功并生成一个二进制文件,但它不是静态链接的:
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
尝试在 /lib/ld-musl-x86_64.so.1 的 malloc_usable_size () 中运行此二进制文件时会崩溃。
我相信这是因为我的系统没有 MUSL 链接器,所以它使用 glibc/gcc 链接器,这会导致问题。
我在想,如果我能设法生成一个真正静态的二进制文件,它不会引用链接器,这可能会奏效。
知道我做错了什么吗?我尝试了一些builder.rs printlns,但我目前没有。
解决方案
好吧,我找到了...
我很确定问题出在-C link-arg=/lib/ld-musl-x86_64.so.1
国旗上。我认为这或多或少迫使一个动态可执行文件。删除它解决了问题:-)
# -*- 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
推荐阅读
- angular - Storybook 6 错误:ngrx no provider for Store 错误 - 如何修复?
- python - 访问由 opencensus 导出器发送的自定义指标时出现问题
- scala-native - 是否可以将 libcu++ 与 scala-native 一起用于 GPU 编程?
- php - PHP迁移问题
- java - Scrollview 是否最适合在一个 Activity 中保存多个视图?尝试创建 Tour 应用程序,所以我需要知道
- sql-server - .Net core api 2.2 请求插入到 MSSQL 数据库的 Coldfusion Api 字符问题
- reactjs - Next.js 与 SCSS 拆分为每个组件的文件
- javascript - 应用程序在 localhost 上正常工作,但在 heroku 上部署后,它不能正常工作
- python - 文本分类的训练和验证准确性和损失
- flutter - 在 Flutter 的会话期间使用 Provider 存储 JWT 是否安全?