Rust探索之旅——交叉编译指南

Rust探索之旅——交叉编译指南

Rust 交叉编译指南

Rust 支持跨平台编译,允许在一个平台上编译生成另一个平台的可执行文件。以下是实现交叉编译的详细步骤,最后提供了一个自动编译批处理脚本,通过脚本命令可直接编译目标文件,缺少环境可以自动安装

1.基本概念

交叉编译指在一种计算机平台上生成另一种平台可执行代码的过程。开发主机(Host)与目标机(Target)的处理器架构或操作系统不同,需通过特定工具链实现跨平台编译。

2.运行机制

交叉编译器在执行时会做两件核心工作:

  • 生成目标平台的机器码

    • 编译器后端负责把中间代码翻译成目标平台的 CPU 指令(如 ARM、MIPS、RISC-V)。

    • 与宿主平台(Host)的 CPU 指令不同。

  • ** 链接目标平台的系统库 **

    • 交叉编译工具链包含针对目标平台的 libc / libstdc++ / 动态库、编译器、链接器等工具,而不是宿主机的库。

    • 通常通过 --sysroot 或 -I、-L 指定目标库和头文件路径,确保链接正确的库版本。

3.交叉编译器

交叉编译器其实是一套专门的 工具链(Toolchain),它包含:

组件 作用
g*** / g++(交叉编译器) 把源码编译成目标平台的机器码
as(汇编器) 把汇编代码转为目标平台机器码
ld(链接器) 把多个目标文件链接成可执行程序
ar / ranlib(静态库工具) 打包或索引库文件
strip / objdump / nm 查看或精简目标二进制文件
sysroot(目标系统库和头文件) 提供编译时的依赖环境(如 libc、头文件等)

这些工具被称为一整套交叉编译工具链,通常以目标平台命名:

  • aarch64-apple-darwin
  • x86_64-apple-darwin
  • x86_64-unknown-linux-gnu
  • x86_64-pc-windows-gnu
  • arm-linux-gnueabihf-g***
  • aarch64-linux-gnu-g***

4.典型的安装工作流程

1).安装目标平台的工具链

查看所有支持的目标平台:

rustup target list

使用 rustup target add 命令安装目标平台的工具链。例如,编译到 x86_64-unknown-linux-gnu

rustup target add x86_64-unknown-linux-gnu
2).配置链接器

某些目标平台需要额外的链接器配置。在 ~/.cargo/config 中添加目标平台的链接器路径。例如,为 x86_64-unknown-linux-gnu 配置:

[target.x86_64-unknown-linux-gnu]
linker = "x86_64-unknown-linux-gnu-g***"
ar = "x86_64-unknown-linux-gnu-g***-ar"

ar = archiver,是一个用来把多个目标文件 (.o) 打包成一个静态库 (.a) 的工具。
Rust 编译时,如果你的依赖包含 静态库,或者用 build.rs 生成 .a 文件,就会调用 ar。因为你正在交叉编译到 x86_64-unknown-linux-gnu,如果你不指定,Rust 可能会用系统默认的 ar(Mac 的 ar),结果生成的 .a 库是 macOS 格式,链接 Linux 可执行文件时就报错。

3).验证目标链接器
❯ x86_64-linux-gnu-g*** --version
x86_64-linux-gnu-g*** (G***) 13.3.0
Copyright (C) 2023 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

❯ x86_64-linux-gnu-g***-ar --version
GNU ar (GNU Binutils) 2.40
Copyright (C) 2023 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) any later version.
This program has absolutely no warranty.
4).编译代码

使用 --target 参数指定目标平台:

cargo build --target x86_64-linux-gnu-g***
5).验证输出文件

编译完后,用 file 命令检查生成的二进制是否正确:

file target/x86_64-unknown-linux-gnu/debug/your_binary

你应该看到

ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=e64cf75762a2b16f7775a7f30985bf4699eca987, for GNU/Linux 2.6.16, not stripped

通过以上步骤,可以实现 Rust 项目的交叉编译。

5.自动脚本

这里准备了一个自动脚本,可以自动检测要编译的目标平台,如果工具没有安装会自动安装

1).先配置config.toml
# ~/.cargo/config.toml
# 统一配置不同平台的 linker 和 ar

# ======================
# macOS (Apple Silicon)
# ======================
[target.aarch64-apple-darwin]
linker = "clang"
ar = "llvm-ar"

# ======================
# macOS (Intel Mac)
# ======================
[target.x86_64-apple-darwin]
linker = "clang"
ar = "llvm-ar"

# ======================
# Linux (x86_64)
# 安装:
#   brew tap messense/macos-cross-toolchains
#   brew install x86_64-unknown-linux-gnu
[target.x86_64-unknown-linux-gnu]
linker = "x86_64-unknown-linux-gnu-g***"
ar = "x86_64-unknown-linux-gnu-g***-ar"

# ======================
# Windows (x86_64, GNU toolchain)
# 安装:
#   brew install mingw-w64
[target.x86_64-pc-windows-gnu]
linker = "x86_64-w64-mingw32-g***"
ar = "x86_64-w64-mingw32-g***-ar"

# ======================
# 通用构建优化
# ======================
[build]
# 默认开启并行编译(也可以手动用 -j 覆盖)
# jobs = 0

# 可选:默认用 release 构建
# default-run = "release"
2).自动编译脚本build.sh
#!/usr/bin/env bash
set -e
set -u

TARGET=""
MODE="debug"
PROJECT_DIR="."

detect_default_target() {
  if [[ "$(uname)" == "Darwin" ]]; then
    ARCH=$(uname -m)
    if [[ "$ARCH" == "arm64" ]]; then
      echo "aarch64-apple-darwin"
    else
      echo "x86_64-apple-darwin"
    fi
  else
    echo ""
  fi
}

show_usage() {
  echo "用法: $0 [mac-arm|mac-x86|linux-x86|win-x86] [release] [--project /path/to/project]"
  echo "不传目标会自动检测 macOS 架构。"
  exit 1
}

# 解析参数
while [[ $# -gt 0 ]]; do
  case "$1" in
    mac-arm|mac-x86|linux-x86|win-x86)
      TARGET="$1"
      shift
      ;;
    release)
      MODE="release"
      shift
      ;;
    --project)
      PROJECT_DIR="$2"
      shift 2
      ;;
    *)
      echo "未知参数: $1"
      show_usage
      ;;
  esac
done

# 如果没指定 TARGET,自动检测
if [[ -z "$TARGET" ]]; then
  TARGET=$(detect_default_target)
  if [[ -z "$TARGET" ]]; then
    echo "无法自动检测目标,请手动指定。"
    show_usage
  fi
fi

# 映射 TARGET 到 Rust triple
case "$TARGET" in
  mac-arm)  TARGET_TRIPLE="aarch64-apple-darwin" ;;
  mac-x86)  TARGET_TRIPLE="x86_64-apple-darwin" ;;
  linux-x86) TARGET_TRIPLE="x86_64-unknown-linux-gnu" ;;
  win-x86)  TARGET_TRIPLE="x86_64-pc-windows-gnu" ;;
esac

# 安装目标
if ! rustup target list | grep -q "${TARGET_TRIPLE} (installed)"; then
  echo "目标 ${TARGET_TRIPLE} 未安装,正在安装..."
  rustup target add $TARGET_TRIPLE
fi

# Windows 特殊配置
if [ "$TARGET_TRIPLE" = "x86_64-pc-windows-gnu" ]; then
  if ! ***mand -v x86_64-w64-mingw32-g*** &>/dev/null; then
    echo "⚠️  Windows 交叉编译需要 MinGW-w64 工具链,正在安装..."
    brew install mingw-w64
  fi
  export RUSTFLAGS=""
fi

# 开始编译
echo "🚀 编译项目: $PROJECT_DIR"
echo "目标: $TARGET_TRIPLE [$MODE]"

if [ "$MODE" = "release" ]; then
  cargo build --manifest-path "$PROJECT_DIR/Cargo.toml" --target $TARGET_TRIPLE --release -j $(sysctl -n hw.logicalcpu)
else
  cargo build --manifest-path "$PROJECT_DIR/Cargo.toml" --target $TARGET_TRIPLE -j $(sysctl -n hw.logicalcpu)
fi

echo "✅ 编译完成: $PROJECT_DIR/target/$TARGET_TRIPLE/$MODE/"

3).使用build.sh编译项目

将build.sh放在项目或工作空间的根目录下

  • 编译当前目录项目
  # 不指定参数,则根据默认参数detect_default_target中的设置进行编译
  ./build.sh 
  ./build.sh mac-arm
  ./build.sh mac-arm release
  • 编译指定项目
  ./build.sh mac-arm release --project /path/to/project
转载请说明出处内容投诉
CSS教程网 » Rust探索之旅——交叉编译指南

发表评论

欢迎 访客 发表评论

一个令你着迷的主题!

查看演示 官网购买