Rust交叉编译问题(mac to linux) 2023

Rust本身是支持跨平台编译的。看资料是只需要简单的跨平台编译命令就好了。

一、官方给出的资料是

rustup target add x86_64-unknown-linux-gnu
cargo build –release –target x86_64-unknown-linux-gnu

两条命令一出就 O 了。然后到了我这里并非如此。问题是一波接着一波,像个解俄罗斯套娃一样。

二、找到 medium 上一个博主的回到。他是在 mul 和 gnu 的 Rust跨平台编译方式 上做了一个比较,然后取舍。

不过我都试了。并不能解决问题。

三、在 stackoverflow 上有一条相同的问题,是通过安装

brew install x86_64-unknown-linux-gnu

去尝试解决的,但是在我这里。一些莫名的报错,比如:

fatal: not in a git directory

Error: Command failed with exit 128: git

我明明实在 cargo new 创建的目录下的。这个不在 git 目录内,是莫名其妙,暂且不表。

四、后来找到github上的处理方式 macos-cross-toolchains

还是不行的

➜ chatgpt git:(main) ✗ brew install [email protected]
[email protected] [email protected] is already installed but outdated (so it will be upgraded).
==> Fetching dependencies for [email protected] ==> Fetching dependencies for [email protected]: ca-certificates
==> Fetching ca-certificates
==> Downloading https://mirrors.ustc.edu.cn/homebrew-bottles/bottles/ca-certificates-2023-01-10.all.bottle.tar.gz
Already downloaded: /Users/c/Library/Caches/Homebrew/downloads/637587df586ffb04fbdb7243608f303e3e5f0da7c2d957ae45535261a60a6e7e–ca-certificates-2023-01-10.all.bottle.tar.gz
==> Fetching [email protected]
==> Downloading https://mirrors.ustc.edu.cn/homebrew-bottles/bottles/openssl%401.1-1.1.1t.ventura.bottle.tar.gz
Already downloaded: /Users/c/Library/Caches/Homebrew/downloads/c32771c573f21242ce5120be535a7dac87a38f7a6d64fb9c61210e7156c30106– [email protected]
==> Installing dependencies for [email protected] ==> Installing dependencies for [email protected]: ca-certificates
==> Installing [email protected] dependency: ca-certificates
fatal: not in a git directory
Error: Command failed with exit 128: git

还是没成功。

但似乎问题还没有解决。因为编译错误集中到 openssl-sys 的编译问题上了:

error: failed to run custom build command for `openssl-sys v0.9.80`
Caused by:
process didn’t exit successfully: `/Users/c/Apps/rust/chatgpt/target/release/build/openssl-sys-177bcdd9e5ad8e81/build-script-main` (exit status: 101)
— stdout
cargo:rustc-cfg=const_fn
cargo:rustc-cfg=openssl
cargo:rerun-if-env-changed=X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_LIB_DIR
X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_LIB_DIR unset
cargo:rerun-if-env-changed=OPENSSL_LIB_DIR
OPENSSL_LIB_DIR unset
cargo:rerun-if-env-changed=X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_INCLUDE_DIR
X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_INCLUDE_DIR unset
cargo:rerun-if-env-changed=OPENSSL_INCLUDE_DIR
OPENSSL_INCLUDE_DIR unset
cargo:rerun-if-env-changed=X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_DIR
X86_64_UNKNOWN_LINUX_MUSL_OPENSSL_DIR unset
cargo:rerun-if-env-changed=OPENSSL_DIR
OPENSSL_DIR unset
cargo:rerun-if-env-changed=OPENSSL_NO_PKG_CONFIG
cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_x86_64-unknown-linux-musl
cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS_x86_64_unknown_linux_musl
cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_ALLOW_CROSS
cargo:rerun-if-env-changed=PKG_CONFIG_ALLOW_CROSS
cargo:rerun-if-env-changed=PKG_CONFIG_x86_64-unknown-linux-musl
cargo:rerun-if-env-changed=PKG_CONFIG_x86_64_unknown_linux_musl
cargo:rerun-if-env-changed=TARGET_PKG_CONFIG
cargo:rerun-if-env-changed=PKG_CONFIG
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64-unknown-linux-musl
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR_x86_64_unknown_linux_musl
cargo:rerun-if-env-changed=TARGET_PKG_CONFIG_SYSROOT_DIR
cargo:rerun-if-env-changed=PKG_CONFIG_SYSROOT_DIR
run pkg_config fail: “pkg-config has not been configured to support cross-compilation.\n\nInstall a sysroot for the target platform and configure it via\nPKG_CONFIG_SYSROOT_DIR and PKG_CONFIG_PATH, or install a\ncross-compiling wrapper for pkg-config and set it via\nPKG_CONFIG environment variable.”
— stderr
thread ‘main’ panicked at ‘
Could not find directory of OpenSSL installation, and this `-sys` crate cannot
proceed without this knowledge. If OpenSSL is installed and this crate had
trouble finding it, you can set the `OPENSSL_DIR` environment variable for the
compilation process.
Make sure you also have the development packages of openssl installed.
For example, `libssl-dev` on Ubuntu or `openssl-devel` on Fedora.
If you’re in a situation where you think the directory *should* be found
automatically, please open a bug at https://github.com/sfackler/rust-openssl
and include information about your system as well as this message.
$HOST = x86_64-apple-darwin
$TARGET = x86_64-unknown-linux-musl
openssl-sys = 0.9.80
‘, /Users/c/. cargo/registry/src/github.com -1ecc6299db9ec823/openssl-sys-0.9.80/build/find_normal.rs:191:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
warning: build failed, waiting for other jobs to finish…

也就是说 OPENSSL_DIR unset 。所以解决好 OPENSSL_DIR 的环境变量应该是从Mac到Linux编译问题关键。

于是我就重新设置找到OPENSSL_DIR 的目录设置环境变量, 从 ~/.zshrc 文件增加这一行。

export OPENSSL_DIR=/usr/local/Cellar/openssl/1.1

然后 source ~/.zshrc 更新以下配置。

但是这会儿重新编译,又出现了 thread ‘main’ panicked at ‘OpenSSL include directory does not exist: /usr/local/Cellar/openssl/1.1/include’ 的问题。这说明除了要正确设置 OPENSSL_DIR 目录之外,还需要设置好 openssl 的 include 目录。

然后通过查找 openssl 的头文件信息时,我才恍然大悟。我整个 mac 系统默认的是 openssl 版本号是 openssl@3 。这才是编译时各种编译命令通不过的关键问题所在。

➜ chatgpt git:(main) ✗ brew –prefix openssl
/usr/local/opt/openssl@3

所以我需要先试着把 ~/.zshrc 中的 openssl 的环境变量先修正过来。

➜ chatgpt git:(main) ✗ bat ~/.zshrc |rg openssl
export OPENSSL_DIR=/usr/local/Cellar/openssl/1.1

改为

➜ chatgpt git:(main) ✗ bat ~/.zshrc |rg openssl
export OPENSSL_DIR=/usr/local/Cellar/openssl/3

然后这次编译就顺畅了,至少所有的包都走完了。不过依然还有问题:如果您用 [target.x86_64-unknown-linux-musl]

linker = “x86_64-linux-musl-gcc” 模式,那么可能也会像我一样在此时遇到:

= note: some `extern` functions couldn’t be found; some native libraries may need to be installed or have their path specified

= note: use the `-l` flag to specify native libraries to link

= note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)

横在面前的是一个儿 link 的问题。

换成 Cargo.toml 配置好

[target.x86_64-unknown-linux-gnu]

linker = “x86_64-unknown-linux-gnu-gcc”

然后运行
TARGET_CC=x86_64-unknown-linux-gnu cargo build –release –target x86_64-unknown-linux-gnu
WARN rustc_codegen_ssa::back::link Linker does not support -static-pie command line option. Retrying with -static instead.
error: linking with `cc` failed: exit status: 1

= note: some `extern` functions couldn’t be found; some native libraries may need to be installed or have their path specified
= note: use the `-l` flag to specify native libraries to link
= note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)
error: could not compile …

得了,也是 link 相关编译的错误。这说明链接器出现故障。

到这里,已经到了我的盲区了。我只能求助 chatGPT 了。把错误一贴,得到的回答是,Cargo.toml 里面加点料,

[target.x86_64-unknown-linux-gnu]

rustflags = [“-C”, “link-arg=-Wl,-z,relro,-z,now,-z,noexecstack,-z,defs”]

我信心十足的补充了,重新走发布编译,依然不行,就继续试试

export CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=/usr/local/bin/x86_64-linux-gnu-ld

继续冲,在编译的最后, Rust编译器轻描淡写的给出两句:

error: linker `/usr/local/bin/x86_64-linux-gnu-ld` not found

|

= note: No such file or directory (os error 2)

此时,已经从凌晨4点快来到6点了。我先直接把 target 目录 和 .git 目录忽略掉。打包先上传上去,从服务器上先发布代码了。

tar -Pzcvf chatgpt.tar.gz chatgpt –exclude=/Users/c/Apps/rust/chatgpt/target/*
rsync -av chatgpt.tar.gz username@myip:/path

要解决连接器问题。我最后找到 musl 的解决方式。那就是从 musl的官方文档 下载最新版本的 x86_64-linux-musl-gcc , 然后把下载的软件解压放到一个自己满意的目录下,并且将该目录的 bin 目录加到 ~/.zshrc 文件中的 PATH 用户系统变量内。

这个时候重新编译 cargo build –release –target x86_64-unknown-linux-musl 。

这时候发现链接器的问题已经解决了。不过这回出现了新的问题。

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

WARN rustc_codegen_ssa::back::link Linker does not support -static-pie command line option. Retrying with -static instead.
error: linking with `cc` failed: exit status: 1

= note: ld: unknown option: –as-needed
clang: error: linker command failed with exit code 1 (use -v to see invocation)

这个时候,还是找到 cross ,尝试使用 cross 来编译。

➜ chatgpt git:(main) ✗ RUST_BACKTRACE=1 cross build –target=x86_64-unknown-linux-gnu –release
Unable to find image ‘ghcr.io/cross-rs/x86_64-unknown-linux-gnu:0.2.5’ locally
0.2.5: Pulling from cross-rs/x86_64-unknown-linux-gnu
58690f9b18fc: Pull complete
b51569e7c507: Pull complete
da8ef40b9eca: Pull complete
fb15d46c38dc: Pull complete
7cd0932c59ac: Pull complete
b8099f45b9a5: Downloading [========> ] 32.39MB/180.4MB
640227c3e7fb: Download complete
b8099f45b9a5: Downloading [=========> ] 33.47MB/180.4MB
2bb7cc963f55: Download complete
69f3cca19ad2: Downloading [================> ] 15.14MB/45.37MB
9eae8e6ab0e2: Download complete
69f3cca19ad2: Downloading [=================> ] 16.06MB/45.37MB
e63c3aabe8fe: Download complete
f3f8758fddaa: Download complete
e8df8713a13e: Download complete
840b2ff81099: Download complete
e52d8b455ef1: Download complete

结果,这个镜像拉了非常久,还是没有 pull 完 。(这个问题未完... 我直接用golang先实现一个版本了)

文章原文来自我个人博客网站

你可能感兴趣的:(Rust,rust,macos,linux)