跳转到内容
实战指南toolchain

为 Raspberry Pi 交叉编译最小程序

使用已安装且来源可信的 Linux 交叉工具链生成最小 ELF,并核对目标、架构和动态加载器。

状态
已审阅
难度
进阶
风险
会改变系统
平台
linux · raspberry-pi · raspberry-pi-os

在 Linux 构建主机上使用已有交叉编译器生成最小程序,并在复制到 Raspberry Pi 前核对编译器目标、ELF 架构和动态加载器。

  • 已从可信来源安装面向 Raspberry Pi Linux 用户空间的 GCC 交叉工具链和 Binutils。
  • 已根据目标 Raspberry Pi OS 确认 64 位或 32 位用户空间;不能只凭处理器型号判断。
  • 工具链包含匹配目标 ABI 的 sysroot、C 库和动态加载器。
  • 本指南不提供通用安装命令,因为工具链包名、版本和目标 ABI 取决于构建主机与目标系统。

以下示例假设工具链入口确实为 aarch64-linux-gnu-gcc。32 位系统或自定义工具链应使用其官方文档给出的实际入口,不要只替换文件名前缀后盲目执行。

  1. 选择已安装的编译器,并先核对它:

    Terminal window
    CC='aarch64-linux-gnu-gcc'
    command -v "$CC"
    "$CC" --version
    "$CC" -dumpmachine
    "$CC" -print-sysroot

    command -v 必须返回预期路径,-dumpmachine 应与目标用户空间匹配。-print-sysroot 为空时,应先查工具链说明,不要随意拼接目标机目录。

  2. 在独立目录创建最小程序:

    Terminal window
    WORK_DIR="$(mktemp -d "${TMPDIR:-/tmp}/llog-cross-demo.XXXXXX")" &&
    cd "$WORK_DIR" &&
    printf '%s\n' \
    '#include <stdio.h>' \
    'int main(void) { puts("hello from target"); return 0; }' \
    > hello.c
  3. 编译并链接:

    Terminal window
    "$CC" -std=c17 -Wall -Wextra -Wpedantic -O2 \
    -o hello-rpi hello.c

检查 ELF 头;不要在架构不同的构建主机上直接执行产物:

Terminal window
readelf -h hello-rpi | sed -n \
-e '/Class:/p' -e '/Data:/p' -e '/Type:/p' -e '/Machine:/p'
readelf -l hello-rpi | sed -n '/interpreter/p'

64 位 Raspberry Pi Linux 产物通常应显示 ELF64AArch64;32 位 Arm 产物应显示相应的 32 位类别和 Arm 机器类型。若存在 interpreter,还必须确认该路径在目标 rootfs 中存在。最终部署前,应在隔离的目标设备或兼容测试环境中运行验证。

只清理本指南由 mktemp 创建的目录;保护条件不匹配时拒绝删除:

Terminal window
if [[ -n "${WORK_DIR:-}" && -d "$WORK_DIR" && "$(basename "$WORK_DIR")" == llog-cross-demo.* ]]; then
cd -- / &&
rm -f -- "$WORK_DIR/hello.c" "$WORK_DIR/hello-rpi" &&
rmdir -- "$WORK_DIR"
else
printf '%s\n' '目录保护检查未通过,拒绝删除' >&2
fi
现象 检查 处理
command not found command -v "$CC" 回到工具链提供者文档确认真实入口;不要猜包名或下载陌生二进制。
找不到头文件或库 "$CC" -print-sysroot 使用与目标发行版、架构和 ABI 配套的 sysroot。
ELF 架构不符 "$CC" -dumpmachinereadelf -h 选择正确工具链,并检查是否传入了改变架构或多库的选项。
目标机提示加载器不存在 readelf -l 的 interpreter 让工具链 ABI、动态加载器和目标 rootfs 保持一致。