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

2023-05-16

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 openssl@1.1
openssl@1.1 openssl@1.1 is already installed but outdated (so it will be upgraded).
==> Fetching dependencies for openssl@1.1 ==> Fetching dependencies for openssl@1.1: 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 openssl@1.1
==> 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– openssl@1.1-1.1.1t.ventura.bottle.tar.gz
==> Installing dependencies for openssl@1.1 ==> Installing dependencies for openssl@1.1: ca-certificates
==> Installing openssl@1.1 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先实现一个版本了)

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rust交叉编译问题(mac to linux) 2023 的相关文章

  • 使用 gcc 理解共享库

    我试图理解 C 中共享库的以下行为 机器一 cat one c include
  • C++:Linux平台上的线程同步场景

    我正在为 Linux 平台实现多线程 C 程序 其中我需要类似于 WaitForMultipleObjects 的功能 在搜索解决方案时 我发现有一些文章描述了如何在 Linux 中实现 WaitForMultipleObjects 功能
  • 如何从远程 ssh 连接上运行的 tmux(复制模式)复制到本地剪贴板

    我通过 OS X 上的 VirtualBox 运行 Linux 我通过在无头状态下运行虚拟机 然后使用端口转发 sshing 到 Linux 机器来实现这一点 现在 无论复制到我的虚拟机上的剪贴板 我都可以粘贴到我的远程 ssh 会话上 但
  • 用于读取文件的 Bash 脚本

    不知道为什么最后一行没有从脚本中删除 bin bash FILENAME 1 while read line do cut d f2 echo line done lt FILENAME cat file 1 test 2 test 3 t
  • 如何在 Linux/OS X 上温和地终止 Firefox 进程

    我正在使用 Firefox 进行一些自动化操作 尽管我可以从 shell 打开 Firefox 窗口 但我无法正确终止它 如果我kill火狐进程与kill 3 or kill 2当我下次打开新的 Firefox 窗口时 命令会询问我是否要在
  • Python将文件从Linux复制到WIndows

    我正在构建一个网站 该网站有一个表单 可以捕获用户数据并在用户数据上运行一些cgi cgi 的第一步是需要将文件从 Linux Web 服务器复制到 Windows 计算机 服务器将使用 Active Directory 角色帐户作为复制凭
  • 使用c在linux上分块读写

    我有一个 ASCII 文件 其中每一行都包含一个可变长度的记录 例如 Record 1 15 characters Record 2 200 characters Record 3 500 characters Record n X cha
  • Rust 是否包含一种直接检查一个向量是否是另一个向量的“子串”的方法?

    你可以用String using contains它搜索一个模式 但是Vec contains是针对单个元素的 我能够做到这一点的唯一方法是直接实现某种子字符串函数 但我有点希望有一种内置的方法 let vec1 vec 1 2 3 4 5
  • Visual Studio - X11:缺少 DISPLAY 环境变量

    我正在使用 Visual Studio 2019 Enterprise 开发跨平台 Windows Linux x64 GUI 应用程序 在这个 2019 版本中 我们可以使用 Visual Studio调试平台 Windows 本机 和
  • 了解 Linux oom-killer 日志

    我的应用程序被 oom killer 杀死了 它是在实时 USB 上运行的 Ubuntu 11 10 无需交换 PC 具有 1 Gig 的 RAM 唯一运行的应用程序 除了所有内置的 Ubuntu 东西 是我的程序 flasherav 请注
  • 如何有条件地更改 Rust 宏的一小部分?

    我正在建造一个具有以下功能的板条箱foo 这个箱子有一个宏bar 根据是否做细微不同的事情foo is set 我可以复制整个宏 cfg feature foo macro rules bar Lots of rules A gt B cf
  • 如何使用 go1.6.2 构建 linux 32 位

    有没有任何组合GOARCH and GOOS我可以设置哪些值来构建 ELF 32 位二进制文 件 GOOS linux and GOARCH 386 更多示例 架构 32 bit gt GOARCH 386 64 bit gt GOARCH
  • 为什么这个 Rust 程序忽略不变性

    我有以下 Rust 程序 我希望它会导致编译错误 因为x稍后会重新分配 但它遵守并给出输出 为什么 fn main let x y 1 3 println X is and Y is x y let x i32 565 println No
  • 将 Option<&mut T> 转换为 *mut T

    我正在围绕 C 库编写一个 Rust 包装器 同时我试图利用中提到的 可空指针优化 The Book https doc rust lang org 1 30 0 book first edition ffi html the nullab
  • 异步任务中止时会发生什么?

    锈有async可以绑定到的方法Abortable https docs rs futures preview 0 3 0 alpha 19 futures future struct Abortable html期货 文档说 当中止时 未来
  • 由于 abi::cxx11 符号导致的链接问题?

    我们最近收到一份报告 因为GCC 5 1 libstdc 和双 ABI http gcc gnu org onlinedocs libstdc manual using dual abi html 它似乎Clang 不知道 GCC 内联名称
  • 如何使用 VSCode 调试 Linux 核心转储?

    我故意从我使用 VSCode 编写的 C 应用程序生成核心转储 我不知道如何调试核心转储 有没有人愿意分享这方面的经验 更新 我相信我现在已经可以使用了 我为核心文件创建了第二个调试配置 我需要添加指向生成的转储文件的 coreDumpPa
  • 如何按元素添加两个 Rust 数组?

    这绝对是一个初学者问题 但我搜索了半个小时后找不到任何有用的东西 我有 Rust 1 7 0 和这段代码 type coord i64 3 add two coordinates vectors pointwise that is if z
  • 如何通过从字母数字字符中采样来创建随机字符串?

    我尝试编译以下代码 extern crate rand 0 6 use rand Rng fn main rand thread rng gen ascii chars take 10 collect
  • 如何在 bash_profile 文件中添加导出语句?

    我正在尝试了解是否必须添加导出语句来在 bash profile 文件中设置变量 我该怎么做呢 例如 如果我必须添加 export AX name 那么我应该将其简单地写在文件末尾还是我还需要编写其他内容 简单写一下export AS na

随机推荐