如何编译具有本机依赖项的 Rust 项目的静态 musl 二进制文件? [英] How to compile a static musl binary of a Rust project with native dependencies?

查看:88
本文介绍了如何编译具有本机依赖项的 Rust 项目的静态 musl 二进制文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个依赖于 Hyper 和 Diesel 的项目,因此,依赖于本机库 OpenSSL 和 libpq.该项目基于夜间 Rust 构建,因为它使用编译器插件.

I have a project with dependencies on Hyper and Diesel, and because of that, on native libraries OpenSSL and libpq. The project builds on nightly Rust because it uses compiler plugins.

我目前的尝试是在 Docker 容器上构建.我有 MUSL libc 和库 make'd 并安装了前缀 /usr/local/musl.我使用以下命令运行 cargo :(不确定某些选项是否多余,我不太熟悉编译器链,甚至不确定它们是否最终到达链接器,但我必须尝试,对.)

My current attempt is to build on a Docker container. I have the MUSL libc and the libraries make'd and installed with prefix /usr/local/musl. I run cargo with the following command: (Not sure if some of the options are redundant, I'm not too well-versed with the compiler chain, and not even sure if they end up to the linker, but I have to try, right.)

LDFLAGS="-static -L/usr/local/musl/lib" \
LD_LIBRARY_PATH=/usr/local/musl/lib:$LD_LIBRARY_PATH \
CFLAGS="-I/usr/local/musl/include" \
PKG_CONFIG_PATH=/usr/local/musl/lib/pkgconfig \
cargo build --release --target=x86_64-unknown-linux-musl

当我 ldd 结果文件时,它显示:

When I ldd the resulting file, it reveals this:

$ ldd server
linux-vdso.so.1 (0x00007fffb878e000)
libpq.so.5 => /usr/local/musl/lib/libpq.so.5 (0x00007f4d730e7000)
libssl.so.1.0.0 => /usr/lib/x86_64-linux-gnu/libssl.so.1.0.0 (0x00007f4d72e82000)
libcrypto.so.1.0.0 => /usr/lib/x86_64-linux-gnu/libcrypto.so.1.0.0 (0x00007f4d72a85000)
libc.so => /usr/local/musl/lib/libc.so (0x00007f4d727f6000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f4d725f2000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4d72246000)
/lib/ld64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x000055e2124a2000)

有所有动态链接的东西,有些甚至带有x86_64-linux-gnu"链!出了什么问题?

There's all that dynamically linked stuff, and some even with the "x86_64-linux-gnu" chain! What went wrong?

我可以毫无问题地制作静态链接的、简单的纯 Rust 项目.ldd 表示它们是静态链接的,并且它们运行没有问题,这与我遇到问题的可执行文件不同.

I can make statically linked, simple pure-Rust projects without problems. ldd says that they are statically linked, and they run without problems, unlike the executable I have problems with.

当我在 Cargo 中使用 --verbose 时,我得到了以下 rustc 命令来实际构建可执行文件:http://pastebin.com/ywv0zNBK(糟糕,那个有一个自定义的 outdir-Z print-link-args,由我添加)添加 print-link-args 标志后,我得到以下链接器命令:http://pastebin.com/Aw43qd7h

When I used --verbose with Cargo, I got the following rustc command that actually builds the executable: http://pastebin.com/ywv0zNBK (Oops, that one had a custom outdir and -Z print-link-args, added by me) Adding the print-link-args flag, I got the following linker command: http://pastebin.com/Aw43qd7h

如何让 cargorustc 相信我想要一个静态二进制文件?

How do I get cargo or rustc to believe that I want a static binary?

推荐答案

问题在于,对于每个提供本机依赖项(例如 OpenSSL)的 crate,都存在 build.rs 构建脚本负责将构建和链接选项传达给 Cargo 和 rustc.(例如:他们打印出类似 cargo:rustc-link-lib=static=ssl 的内容,然后 Cargo 读取并采取相应的行动.)

The problem was that for each crate providing a native dependency – say OpenSSL – there is the build.rs build script that is in charge of communicating the build and linking options to Cargo and to rustc. (For example: they print out something like cargo:rustc-link-lib=static=ssl which Cargo then reads and acts accordingly.)

因此,仅设置标准"GCC 环境变量几乎不会产生任何影响.您必须分别检查每个 build.rs 以了解如何强制该确切的板条箱传送货物其选项.对于 OpenSSL,其环境变量如 OPENSSL_DIROPENSSL_STATIC

So just setting the "standard" GCC environmental variables is hardly going to have any effect. You must check each and every build.rs separately to know how to coerce that exact crate to convey cargo its options. For OpenSSL, its env vars like OPENSSL_DIR, OPENSSL_STATIC etc.

另一个障碍是,如果您使用编译器插件,它们也可能与目标三元组一起编译(至少是 docker_codegen).另一方面,它们在编译过程中是动态链接的.这意味着不仅必须正确链接静态库,还必须拥有 target 宿主种类的动态库,例如 Musl libc.so 到位,并正确设置 (LD_LIBRARY_PATH 等).

Another hurdle is that if you use compiler plugins, they might be compiled with the target triplet too (at least docker_codegen). On the other hand, they are linked dynamically during the compiling process. This mean that not only must static libraries be linked correctly, you must also have dynamic libraries of the target host variety, like Musl libc.so in place, and correctly set (LD_LIBRARY_PATH etc.).

我制作了一个完整注释的 Dockerfile,它使用一些本机依赖项静态构建我的项目.它可能对其他人也有帮助.

I made a thoroughly commented Dockerfile that builds my project statically with some native dependencies. It might be of help for others too.

https://gitlab.com/rust_musl_docker/image

这篇关于如何编译具有本机依赖项的 Rust 项目的静态 musl 二进制文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆