背景

正在使用windows11作为开发,但是编译出来的rust程序是exe,只能在windows上运行。不能在linux服务器上运行。

这时候要想在windows上编译linux服务器上能运行的程序,就要交叉编译

之前安装过rust,rust直接装在了D盘根目录下。

结论

鉴于 MSYS2 主要设计用于提供 Windows 下的 Unix 风格开发环境,并不直接适用于进行复杂的交叉编译任务,推荐使用 WSL 或 Docker 作为进行交叉编译的环境。这些方法能提供更一致的 Linux 环境,简化交叉编译的过程。

下面的步骤不用看了,最终失败了,这些步骤都是临时性的记录。

步骤

目标平台(CentOS 8 使用的 Linux 版本)添加对应的工具链

1
rustup target add x86_64-unknown-linux-gnu

添加toml文件

1
2
[target.x86_64-unknown-linux-gnu]
linker = "x86_64-w64-mingw32-gcc"

编译的时候输入指令:

1
cargo build --target x86_64-unknown-linux-gnu --release

但是报错了:

1
2
3
4
5
error: linker `cc` not found
|
= note: program not found

error: could not compile `core-rust-axum` (bin "core-rust-axum") due to 1 previous error

可能是因为没有安装 MinGW-w64

使用 MSYS2 安装 MinGW-w64

MSYS2 是一个软件包管理系统,提供了一个类似于 Unix 的命令行环境,它可以让你方便地安装和管理 MinGW-w64 工具链和其他 Unix 工具。

下载 MSYS2 安装器: 访问 MSYS2 的官方网站 msys2.org 并下载安装器

下载过程还是非常慢的

下载好之后出来个窗口。居然像一个小小的linux虚拟机。

在 MSYS2 MSYS 终端,输入以下命令更新系统

1
pacman -Syu

输入完成后会关闭,需要手动重新打开。

输入下面的指令继续更新

1
pacman -Su

安装工具链

1
pacman -S mingw-w64-x86_64-toolchain

上面的过程可能最好开一下vpn,要不然会报错。就像下面:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
:: Retrieving packages...
wget-1.24.5-1-x86_64 772.4 KiB 74.5 KiB/s 00:10 [###############################] 100%
curl-8.6.0-1-x86_64 716.3 KiB 132 KiB/s 00:05 [###############################] 100%
libgnutls-3.8.3-1-x86_64 1386.0 KiB 80.2 KiB/s 00:17 [###############################] 100%
libopenssl-3.2.1-1-x86_64 1790.2 KiB 23.8 KiB/s 01:15 [###############################] 100%
xz-5.6.1-1-x86_64 541.5 KiB 102 KiB/s 00:05 [###############################] 100%
libsqlite-3.45.1-1-x86_64 678.1 KiB 10.4 KiB/s 01:05 [###############################] 100%
libxml2-2.12.6-1-x86_64 508.8 KiB 21.3 KiB/s 00:24 [###############################] 100%
openssl-3.2.1-1-x86_64 625.6 KiB 10.1 KiB/s 01:02 [###############################] 100%
pacman-contrib-1.10.5-1-x86_64 4.6 MiB 39.2 KiB/s 02:01 [###############################] 100%
gnupg-2.4.5-1-x86_64 2.5 MiB 19.2 KiB/s 02:13 [###############################] 100%
Total (10/25) 16.1 MiB 124 KiB/s 02:13 [###############################] 100%
error: failed retrieving file 'libgnutls-3.8.3-1-x86_64.pkg.tar.zst' from mirror.msys2.org : SSL connection timeout
error: failed retrieving file 'libgnutls-3.8.3-1-x86_64.pkg.tar.zst' from repo.msys2.org : Operation too slow. Less than 1 bytes/sec transferred the last 10 seconds
error: failed retrieving file 'libsqlite-3.45.1-1-x86_64.pkg.tar.zst.sig' from mirrors.ustc.edu.cn : Operation too slow. Less than 1 bytes/sec transferred the last 10 seconds
warning: failed to retrieve some files
error: failed to commit transaction (unexpected error)
Errors occurred, no packages were upgraded.

还是出现了一些报错:

1
2
3
4
5
6
7
8
9
error: failed retrieving file 'mingw-w64-x86_64-zstd-1.5.5-1-any.pkg.tar.zst' from mirror.msys2.org : Operation too slow. Less than 1 bytes/sec transferred the last 10 seconds
error: failed retrieving file 'mingw-w64-x86_64-sqlite3-3.45.2-1-any.pkg.tar.zst.sig' from mirrors.bfsu.edu.cn : Operation too slow. Less than 1 bytes/sec transferred the last 10 seconds
error: failed retrieving file 'mingw-w64-x86_64-zstd-1.5.5-1-any.pkg.tar.zst' from repo.msys2.org : Operation too slow. Less than 1 bytes/sec transferred the last 10 seconds
error: failed retrieving file 'mingw-w64-x86_64-binutils-2.42-1-any.pkg.tar.zst.sig' from mirrors.bfsu.edu.cn : Operation too slow. Less than 1 bytes/sec transferred the last 10 seconds
error: failed retrieving file 'mingw-w64-x86_64-gdb-multiarch-14.2-1-any.pkg.tar.zst.sig' from mirrors.bfsu.edu.cn : Operation too slow. Less than 1 bytes/sec transferred the last 10 seconds
warning: too many errors from mirrors.bfsu.edu.cn, skipping for the remainder of this transaction
warning: failed to retrieve some files
error: failed to commit transaction (unexpected error)
Errors occurred, no packages were upgraded.

在MSYS2 MSYS 终端里安装好了MinGW-w64 工具链,如何编译rust项目?

实际上这个终端里连rust环境都没有,所以要安装一个rust。

1
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

结果安装的时候卡住了,可以这样:

先下载安装脚本:

1
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs -o rustup-init.sh

然后再执行安装脚本

1
2
chmod +x rustup-init.sh
./rustup-init.sh

安装过程中,遇到第一个选择:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Rust Visual C++ prerequisites

Rust requires a linker and Windows API libraries but they don't seem to be
available.

These components can be acquired through a Visual Studio installer.

1) Quick install via the Visual Studio Community installer
(free for individuals, academic uses, and open source).

2) Manually install the prerequisites
(for enterprise and advanced users).

3) Don't install the prerequisites
(if you're targeting the GNU ABI).

选3

又遇到一个选择:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Rust Visual C++ prerequisites
D:/Rust/cargo_home/bin

This path will then be added to your PATH environment variable by
modifying the HKEY_CURRENT_USER/Environment/PATH registry key.

You can uninstall at any time with rustup self uninstall and
these changes will be reverted.

Current installation options:


default host triple: x86_64-pc-windows-msvc
default toolchain: stable (default)
profile: default
modify PATH variable: yes

1) Proceed with standard installation (default - just press enter)
2) Customize installation
3) Cancel installation

选1

然后就进入了漫长的等待。

1
2
error: component download failed for rust-docs-x86_64-pc-windows-gnu: error decoding response body: operation timed out

安装docs的失败了

再重新来。然后又是缓慢的安装过程,等了快一个小时了。终于装好了

出现了新的问题:

明明rust已经在MSYS2 MSYS 终端里安装好了,但是输入 cargo -v 显示

-bash: cargo: command not found

下面是AI给出的解决步骤:

解决步骤

1. 手动检查和添加 Rust 的路径到 MSYS2 MSYS 的 PATH

  1. 首先确认 Rust 的安装路径。根据你的选择,cargo 应该安装在了 D:/Rust/cargo_home/bin

  2. **在 MSYS2 MSYS 终端中添加 Rust 的路径到 PATH**。你可以通过在 MSYS2 MSYS 终端中执行下面的命令来临时添加 Rust 的安装路径到 PATH

    1
    export PATH=$PATH:/d/Rust/cargo_home/bin

    注意:MSYS2 MSYS 终端中的路径使用 POSIX 风格,所以 Windows 路径 D:/Rust/cargo_home/bin 在 MSYS2 中应当写作 /d/Rust/cargo_home/bin

  3. 验证 rustupcargo 是否现在可用

    1
    2
    rustup -V
    cargo -V

2. 永久添加 Rust 的路径到 MSYS2 MSYS 的 PATH

为了使这一变更永久生效,你应该将上述 export PATH... 命令添加到你的 ~/.bashrc~/.bash_profile 文件中。

其中波浪号代表当前用户主目录的快捷表示 ~/.bashrc 代指 /home/用户名/.bashrc

  1. 打开 ~/.bashrc~/.bash_profile 文件,如果文件不存在,你可以创建一个。

  2. 在文件末尾添加以下行:

    1
    export PATH=$PATH:/d/Rust/cargo_home/bin
  3. 保存并关闭文件。

  4. 具体操作如下

    1
    2
    3
    4
    5
    6
    # 创建文件
    echo 'export PATH=$PATH:/d/Rust/cargo_home/bin' > ~/.bashrc
    # 验证看里面的内容是否已经写入
    cat ~/.bashrc
    # 使更改生效
    source ~/.bashrc

这时候关掉这个控制台工具再打开,就能看到 cargo命令依然永久生效了。

这时候确认一下:

1
rustup target add x86_64-unknown-linux-gnu

结果是

1
info: component 'rust-std' for target 'x86_64-unknown-linux-gnu' is up to date

说明已经好了

安装交叉编译工具链

1
pacman -S mingw-w64-x86_64-gcc

在项目中的toml文件添加内容:

1
2
[target.x86_64-unknown-linux-gnu]
linker = "x86_64-linux-gnu-gcc"

运行

1
cargo build --target=x86_64-unknown-linux-gnu --release

最终居然报了和最开始同样的错误

1
2
3
4
error: linker `cc` not found
|
= note: program not found

去网上搜了搜,搜到一个文章

Rust编译Linux通用可执行文件 · 零壹軒·笔记 (qidong.name)

先安装

1
rustup target add x86_64-unknown-linux-musl

好像又等了快10分钟

然后编译

1
cargo build -r --target=x86_64-unknown-linux-musl

还是不行

直接搜报错结果信息,

又搜到一个文章

使用cargo将rust项目从windows交叉编译到linux时出现错误:”linker ‘cc‘not found“。-腾讯云开发者社区-腾讯云 (tencent.com)

试了,还是一样。

之后又搜了其他方法,还是不成功。已经耗费了好几个小时了。

后续的尝试方法:

WSL

在Docker容器中编译

搞个虚拟机。