3. 交叉编译环境搭建
在全志 T113 平台进行 Linux 外设驱动开发,交叉编译环境是连接开发主机与目标硬件(T113 开发板)的桥梁。由于 T113 的 ARM Cortex-A7 内核与 x86 开发主机架构不同,必须在主机上安装交叉工具链,将源代码编译为 T113 可执行的 ARM 指令集二进制文件。本节将系统讲解交叉工具链的安装、环境变量配置、依赖库安装以及编译环境的验证方法。
核心概念:交叉编译(Cross Compilation)是指在一种架构(如 x86)上编译出另一种架构(如 ARM)可执行代码的过程。全志 T113 使用 ARMv7-A 架构,因此需要 arm-linux-gnueabihf 或 aarch64-linux-gnu 系列工具链(取决于内核配置)。
3.1 交叉工具链安装
全志 T113 官方 SDK 通常基于 Linaro 或 ARM 官方提供的 GCC 交叉工具链。推荐使用 arm-linux-gnueabihf- 前缀的工具链(支持硬浮点运算),以匹配 T113 的 Cortex-A7 核心。以下是两种主流安装方式:
3.1.1 方法一:使用 Linaro 预编译工具链(推荐)
- 下载工具链:从 Linaro 官方仓库或全志 SDK 中获取
gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz。 - 解压到指定目录:
# 创建工具链安装目录
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 |
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 文件
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 参数以便观察错误信息。