3. 交叉编译环境搭建:工具链安装、环境变量与内核初次编译验证
交叉编译环境是嵌入式 Linux 开发的基石。在宿主机(x86_64)上编译出能在 ARM/MIPS/RISC-V 等目标架构上运行的二进制文件,必须依赖交叉编译工具链。本章将完整演示工具链的安装、环境变量配置,并通过 defconfig 与 menuconfig 完成内核源码的初次编译验证。
核心目标:在宿主机上建立一套可重复、可验证的交叉编译环境,确保内核源码能够正确配置并生成目标架构的
zImage 与 dtbs。
3.1 交叉编译工具链安装
工具链的选择取决于目标 SoC 架构。以下以 ARM Cortex-A7/A53 为例,使用 Linaro 提供的 gcc-arm-linux-gnueabihf 工具链。
| 组件 | 版本/路径 | 说明 |
|---|---|---|
| gcc | 7.5.0-2019.12 | ARM hard-float 交叉编译器 |
| binutils | 2.31.1 | 链接器、汇编器、反汇编工具 |
| glibc | 2.28 | C 运行时库(目标系统使用) |
| linux-headers | 4.19 | 内核头文件,用于编译用户态程序 |
3.1.1 下载与解压
# 创建工作目录
mkdir -p ~/x-tools && cd ~/x-tools
# 下载 Linaro 预编译工具链(约 200MB)
wget https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
# 解压到当前目录
tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
# 验证解压后的目录结构
ls -l gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/
3.1.2 验证工具链完整性
# 检查编译器版本
~/x-tools/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc --version
# 输出示例:
# arm-linux-gnueabihf-gcc (Linaro GCC 7.5-2019.12) 7.5.0
# Copyright (C) 2017 Free Software Foundation, Inc.
常见错误:如果提示
No such file or directory,请检查宿主系统是否缺少 32 位兼容库。Ubuntu/Debian 执行 sudo apt install libc6:i386 lib32stdc++6 即可解决。
3.2 环境变量配置
为简化后续编译命令,需将工具链路径加入 PATH,并设置 CROSS_COMPILE 与 ARCH 变量。推荐写入 ~/.bashrc 或 ~/.profile 实现持久化。
# 编辑 ~/.bashrc
echo 'export PATH=$HOME/x-tools/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
# 验证环境变量
echo $ARCH # 应输出 arm
echo $CROSS_COMPILE # 应输出 arm-linux-gnueabihf-
which ${CROSS_COMPILE}gcc # 应显示工具链完整路径
最佳实践:建议为每个项目单独创建
envsetup.sh 脚本,避免多项目间变量冲突。例如:source ~/project/envsetup.sh。
3.3 内核源码的初次编译验证
编译验证分为两步:配置(生成 .config)与 编译(生成内核镜像与设备树)。
3.3.1 使用 defconfig 生成默认配置
内核源码树中为各开发板预置了大量 defconfig 文件,位于 arch/arm/configs/ 目录下。以 vexpress 开发板为例:
# 进入内核源码根目录
cd ~/linux-5.10
# 使用 vexpress 默认配置
make vexpress_defconfig
# 查看生成的 .config 文件
wc -l .config # 通常包含 6000~8000 行配置项
3.3.2 使用 menuconfig 进行可视化裁剪
menuconfig 基于 ncurses 库提供交互式配置界面,适合对默认配置进行模块化裁剪与定制。
# 安装 ncurses 开发库(Ubuntu/Debian)
sudo apt install libncurses5-dev
# 启动 menuconfig 界面
make menuconfig
在 menuconfig 界面中,常用操作键如下:
| 按键 | 功能 |
|---|---|
↑ ↓ |
上下移动光标 |
Enter |
进入子菜单 / 选中条目 |
Y |
将模块编译进内核(*) |
M |
编译为可加载模块(M) |
N |
不编译( ) |
? |
查看帮助信息 |
/ |
搜索配置项 |
裁剪建议:对于 WiFi 与蓝牙模块移植,建议在
menuconfig 中依次检查:Device Drivers → Network device support → Wireless LAN 以及 Networking support → Bluetooth subsystem support。
3.3.3 执行编译并验证输出
# 清理之前的编译产物(首次编译可跳过)
make clean
# 启动并行编译(-jN 中的 N 建议设为 CPU 核心数 × 1.5)
make -j4 zImage dtbs
# 编译完成后检查输出
ls -lh arch/arm/boot/zImage
ls -lh arch/arm/boot/dts/vexpress-v2p-ca9.dtb
成功输出 zImage(约 4~6 MB)与 dtb 文件,即代表交叉编译环境搭建正确,内核源码可正常编译。
3.4 交叉编译流程总览
下图展示了从工具链安装到内核镜像生成的完整数据流与依赖关系:
3.5 常见问题与排查
| 问题现象 | 根本原因 | 解决方案 |
|---|---|---|
arm-linux-gnueabihf-gcc: command not found |
PATH 未包含工具链路径 | 检查 ~/.bashrc 中的 export 语句,重新 source |
ncurses.h: No such file or directory |
缺少 ncurses 开发库 | sudo apt install libncurses5-dev |
arch/arm/boot/zImage: No such file |
编译未成功或配置错误 | 检查 make 输出中的 error 信息,确认 .config 存在 |
Kernel: arch/arm/boot/zImage is ready 但 dtb 缺失 |
未指定 dtbs 目标 |
执行 make dtbs 单独编译设备树 |
效率提升:建议将
make -j4 zImage dtbs 写入 Makefile 或 build.sh 脚本,避免每次手动输入。同时使用 ccache 可大幅加速重复编译。