3. 交叉编译环境搭建

在全志 T113 平台进行 Linux 外设驱动开发,交叉编译环境是连接开发主机与目标硬件(T113 开发板)的桥梁。由于 T113 的 ARM Cortex-A7 内核与 x86 开发主机架构不同,必须在主机上安装交叉工具链,将源代码编译为 T113 可执行的 ARM 指令集二进制文件。本节将系统讲解交叉工具链的安装、环境变量配置、依赖库安装以及编译环境的验证方法。

核心概念:交叉编译(Cross Compilation)是指在一种架构(如 x86)上编译出另一种架构(如 ARM)可执行代码的过程。全志 T113 使用 ARMv7-A 架构,因此需要 arm-linux-gnueabihf 或 aarch64-linux-gnu 系列工具链(取决于内核配置)。
交叉编译环境整体架构 开发主机 (x86_64) Ubuntu 22.04 / 20.04 交叉工具链 + 依赖库 交叉编译 目标板 (ARM Cortex-A7) 全志 T113 开发板 运行编译后的内核/驱动 交叉工具链核心组件 arm-linux-gnueabihf- gcc / g++ / ld 内核头文件 linux-headers C 标准库 glibc / uclibc 调试工具 gdb / strace

3.1 交叉工具链安装

全志 T113 官方 SDK 通常基于 Linaro 或 ARM 官方提供的 GCC 交叉工具链。推荐使用 arm-linux-gnueabihf- 前缀的工具链(支持硬浮点运算),以匹配 T113 的 Cortex-A7 核心。以下是两种主流安装方式:

3.1.1 方法一:使用 Linaro 预编译工具链(推荐)

  1. 下载工具链:从 Linaro 官方仓库或全志 SDK 中获取 gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz。
  2. 解压到指定目录:
# 创建工具链安装目录
sudo mkdir -p /opt/toolchains
cd /opt/toolchains

# 解压工具链(以 7.5.0 版本为例)
sudo tar -xvf ~/Downloads/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz

# 解压后目录结构
ls /opt/toolchains/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/
# bin/  arm-linux-gnueabihf/  include/  lib/  libexec/  share/

3.1.2 方法二:使用全志 SDK 自带工具链

全志 T113 的 Tina Linux SDK 或 Longan SDK 中通常已包含适配好的交叉工具链,路径一般在 prebuilt/gcc/linux-x86/arm/toolchain-sunxi-musl/toolchain/ 下。直接使用 SDK 内的工具链可保证与内核版本、库文件的兼容性。

工具链来源 前缀 适用场景 浮点支持
Linaro 官方 arm-linux-gnueabihf- 通用驱动开发、独立内核编译 硬浮点 (hf)
全志 SDK 内置 arm-openwrt-linux-muslgnueabi- SDK 内完整构建、系统镜像编译 硬浮点 (hf)
ARM 官方 arm-none-linux-gnueabihf- 裸机或独立驱动模块 硬浮点 (hf)
版本匹配警告:交叉工具链的 GCC 版本应与目标内核编译时使用的版本接近。例如,Linux 4.9 内核推荐使用 GCC 7.x 系列;Linux 5.4/5.10 内核推荐使用 GCC 8.x 或 9.x。版本差异过大会导致内核模块加载失败或运行时异常。

3.2 环境变量配置

安装完工具链后,必须将工具链的 bin 目录添加到系统的 PATH 环境变量中,并设置交叉编译前缀变量,以便 Makefile 和构建脚本能够正确调用 ARM 编译器。

3.2.1 临时配置(当前终端有效)

# 设置工具链路径(根据实际安装路径调整)
export PATH=/opt/toolchains/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH

# 设置交叉编译前缀
export CROSS_COMPILE=arm-linux-gnueabihf-

# 设置目标架构
export ARCH=arm

3.2.2 永久配置(推荐写入用户配置文件)

# 编辑 ~/.bashrc 或 ~/.profile
echo 'export PATH=/opt/toolchains/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH' >> ~/.bashrc
echo 'export CROSS_COMPILE=arm-linux-gnueabihf-' >> ~/.bashrc
echo 'export ARCH=arm' >> ~/.bashrc

# 使配置生效
source ~/.bashrc

3.2.3 环境变量说明表

环境变量 作用 示例值
PATH 使系统能找到交叉编译器的可执行文件 /opt/toolchains/.../bin
CROSS_COMPILE 指定交叉编译工具链前缀,Makefile 自动拼接 arm-linux-gnueabihf-
ARCH 指定目标 CPU 架构,影响内核 Kconfig 和 Makefile arm
CC 显式指定 C 编译器(可选,部分项目需要) arm-linux-gnueabihf-gcc
LD 显式指定链接器(可选) arm-linux-gnueabihf-ld
环境变量配置流程 安装工具链 配置 PATH 设置 CROSS_COMPILE 验证 建议将配置写入 ~/.bashrc 或 ~/.profile,避免每次打开终端重复设置 多项目切换时,可使用 export 临时覆盖 CROSS_COMPILE 变量

3.3 依赖库安装

交叉编译环境除了工具链本身,还需要安装一系列主机端的依赖库,以支持内核配置、编译和模块构建。以下是在 Ubuntu 22.04/20.04 上安装必要依赖库的命令:

# 更新包列表
sudo apt update

# 安装基础编译工具和库
sudo apt install -y \
    build-essential \
    flex \
    bison \
    libncurses-dev \
    libssl-dev \
    libelf-dev \
    device-tree-compiler \
    u-boot-tools \
    bc \
    cpio \
    rsync \
    kmod \
    python3 \
    python3-dev \
    python3-pip \
    swig \
    libpython3-dev

# 安装 32 位兼容库(如果主机是 64 位,部分工具链需要 32 位库)
sudo apt install -y \
    libc6:i386 \
    libstdc++6:i386 \
    zlib1g:i386
依赖库/工具 用途 是否必需
build-essential 提供 gcc、g++、make 等基础编译工具 是
flex / bison 内核配置和 DTS 编译的词法/语法分析器 是
libncurses-dev 提供 make menuconfig 的图形界面支持 是
libssl-dev 内核模块签名和加密功能支持 是
libelf-dev ELF 文件处理,内核模块编译必需 是
device-tree-compiler 编译设备树文件 (.dts → .dtb) 是
u-boot-tools 生成 uImage 等引导镜像格式 按需
python3-dev / swig 部分内核脚本和工具需要 Python 绑定 推荐
经验提示:如果编译过程中遇到 fatal error: openssl/bio.h: No such file or directory 或 elf.h 相关错误,通常是因为缺少 libssl-dev 或 libelf-dev。使用 apt search <缺失头文件> 快速定位对应的开发包。

3.4 验证编译环境

完成工具链安装和环境变量配置后,必须进行验证,确保交叉编译器能正常工作,并且能够正确编译内核模块或简单测试程序。

3.4.1 验证工具链版本

# 检查交叉编译器版本
arm-linux-gnueabihf-gcc --version

# 预期输出示例:
# arm-linux-gnueabihf-gcc (Linaro GCC 7.5.0-2019.12) 7.5.0
# Copyright (C) 2017 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.

# 检查交叉编译工具链完整命令
arm-linux-gnueabihf-ld --version
arm-linux-gnueabihf-objdump --version
arm-linux-gnueabihf-strip --version

3.4.2 编译简单测试程序

# 编写一个简单的 C 测试文件
cat > hello_t113.c << 'EOF'
#include <stdio.h>

int main(void)
{
    printf("Hello from T113 cross compile!\n");
    return 0;
}
EOF

# 使用交叉编译器编译
arm-linux-gnueabihf-gcc -o hello_t113 hello_t113.c

# 查看生成文件的架构信息
file hello_t113

# 预期输出:
# hello_t113: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, not stripped

3.4.3 验证内核编译环境

# 进入内核源码目录(以 Linux 5.4 为例)
cd ~/t113_linux_kernel

# 清理之前编译产物
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean

# 加载默认配置(以 sun8i 系列为例)
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- sunxi_defconfig

# 编译内核(仅编译内核镜像,不编译模块,快速验证)
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j$(nproc) zImage

# 验证编译产物
ls -lh arch/arm/boot/zImage
# 预期输出:存在 zImage 文件,大小约 5-10 MB

3.4.4 验证设备树编译

# 编译设备树
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- dtbs

# 验证 T113 相关 dtb 文件
ls -lh arch/arm/boot/dts/sun8i-t113*.dtb
# 预期输出:存在 sun8i-t113-xxx.dtb 文件
编译环境验证流程 步骤 1 检查工具链版本 步骤 2 编译测试程序 步骤 3 编译内核镜像 步骤 4 编译 DTB 验证成功标志 ✅ 工具链版本输出正常,无 "command not found" 错误 ✅ hello_t113 文件类型显示为 ARM 架构 ELF ✅ arch/arm/boot/zImage 和 sun8i-t113*.dtb 文件生成成功

3.5 常见问题与排查

问题现象 可能原因 解决方案
arm-linux-gnueabihf-gcc: command not found PATH 未正确设置或工具链未安装 检查 export PATH 路径是否正确;确认工具链解压目录存在
fatal error: linux/xxx.h: No such file or directory 内核头文件路径未指定或缺失 编译内核模块时需设置 KERNELDIR 指向已编译的内核源码
relocation truncated to fit: R_ARM_THM_CALL 工具链版本与内核代码不兼容 尝试更换 GCC 版本(如从 9.x 降级到 7.x)
scripts/Makefile.host: No such file or directory 内核源码未配置或依赖库缺失 执行 make ARCH=arm defconfig;安装 flex、bison、libncurses-dev
编译出的模块在 T113 上加载报 Invalid module format 内核版本或配置不匹配 确保模块编译时使用的内核源码与目标板运行的内核版本完全一致
最佳实践:建议在开发主机上创建独立的交叉编译工作目录,将工具链、内核源码、根文件系统分开管理。使用 make -j$(nproc) 利用多核加速编译,但首次编译建议不加 -j 参数以便观察错误信息。