2. 环境准备:搭建交叉编译环境,下载 Busybox 源码
好,咱们正式开始动手。这一章的目标很明确——把交叉编译环境搭好,再把 Busybox 源码拉下来。别小看这一步,我在项目里见过太多人因为环境没配好,后面折腾一整天。说白了,地基没打牢,楼盖得再高也得塌。
2.1 什么是交叉编译?为什么需要它?
你平时在 PC 上写代码,gcc 编译出来的程序是给 x86 架构用的。但嵌入式设备通常是 ARM、MIPS、RISC-V 这些架构。你想想看,一个 ARM 开发板根本跑不了 x86 的可执行文件。怎么办?
交叉编译就是答案——在 x86 的宿主机上,用专门的工具链编译出目标架构(比如 ARM)的二进制文件。我刚开始做嵌入式时,总觉得这步很麻烦,后来有一次在项目里直接拿 x86 编译的 busybox 扔到 ARM 板子上,结果跑不起来,嗯,从那以后我再也不敢跳过交叉编译环境的搭建了。
核心概念:宿主机(Host)是你正在用的 PC(x86_64),目标机(Target)是你要部署的嵌入式设备(比如 ARM Cortex-A7)。交叉编译工具链运行在宿主机上,生成目标机可执行的代码。
2.2 交叉编译工具链的选择
工具链的选择其实挺多的。我个人习惯用 Linaro GCC,因为它对 ARM 架构的支持最成熟,社区活跃,更新也及时。当然,你也可以用 Buildroot 或 Yocto 自己编译一套,但那太费时间了。咱们做课程,讲究效率。
下面是我常用的几个选择:
| 工具链 | 适用架构 | 特点 | 推荐场景 |
|---|---|---|---|
| Linaro GCC | ARM (armv7/armv8) | 官方维护,稳定,预编译 | 快速原型、课程实验 |
| Buildroot 工具链 | 多架构 | 可定制,但编译耗时 | 生产环境、定制化需求 |
| Yocto SDK | 多架构 | 功能全面,学习曲线陡 | 大型项目、商业产品 |
| crosstool-NG | 多架构 | 高度灵活,自己搓工具链 | 深度定制、特殊架构 |
咱们这次选 Linaro GCC,省心。你直接去 releases.linaro.org 下载对应版本就行。我建议选 gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf 这个版本,经过我多次验证,兼容性最好。
小技巧:下载后记得校验 sha256sum,我吃过亏,下载到损坏的压缩包,编译时各种诡异报错,排查了半天才发现是文件坏了。
2.3 安装交叉编译工具链
下载完成后,解压到固定目录。我个人习惯放在 /opt/toolchains/ 下,这样好管理。
# 创建工具链目录
sudo mkdir -p /opt/toolchains
cd /opt/toolchains
# 解压(假设下载的文件在 ~/Downloads 下)
sudo tar xf ~/Downloads/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
# 重命名,方便后续引用
sudo mv gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf arm-linux-gnueabihf
# 验证安装
/opt/toolchains/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc --version
看到版本信息输出,就说明装好了。如果提示找不到命令,检查一下路径对不对,或者是不是解压不完整。
注意:不要直接把工具链的 bin 目录加到全局 PATH 里。我建议只在需要的时候临时添加,或者写个脚本。全局 PATH 容易跟系统自带的 gcc 冲突,我曾经因为这个折腾了一下午。
2.4 配置环境变量
每次编译前都要设置环境变量,挺烦的。我习惯写一个 setenv.sh 脚本,放在项目根目录下,每次 source 一下就行。
#!/bin/bash
# 交叉编译环境变量设置脚本
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
export PATH=/opt/toolchains/arm-linux-gnueabihf/bin:$PATH
echo "交叉编译环境已设置"
echo "ARCH: $ARCH"
echo "CROSS_COMPILE: $CROSS_COMPILE"
使用时:
source setenv.sh
为什么要用 source?因为直接执行脚本的话,环境变量只在子进程里生效,退出就没了。source 是在当前 shell 里执行,变量会保留。这个坑我踩过不止一次。
2.5 下载 Busybox 源码
环境搭好了,接下来拿源码。Busybox 的官方仓库在 git.busybox.net,也可以用 GitHub 镜像。我个人习惯用 git 克隆,方便后续切换分支和查看历史。
# 创建项目目录
mkdir -p ~/busybox-course
cd ~/busybox-course
# 克隆 Busybox 源码(稳定版)
git clone git://git.busybox.net/busybox
cd busybox
# 查看所有标签,选一个稳定版本
git tag | grep -E '^1_3[0-9]' | sort -V
# 我推荐用 1_36_1 这个版本,功能完整,bug 少
git checkout 1_36_1
如果你不想装 git,也可以直接下载 tar 包:
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
tar xf busybox-1.36.1.tar.bz2
cd busybox-1.36.1
建议:用 git 克隆,这样你随时可以 git diff 查看自己改了哪些配置,方便复盘。我在项目里经常靠这个找回改错的配置。
2.6 验证源码完整性
源码下载后,先看看目录结构,心里有个数。
ls -l
你会看到这些关键目录:
- applets/ —— Busybox 的主入口,每个命令的 main 函数都在这里
- coreutils/ —— 基础命令,比如 cat、cp、mv
- networking/ —— 网络相关命令,比如 ping、ifconfig
- util-linux/ —— Linux 工具,比如 mount、fdisk
- shell/ —— shell 实现,比如 ash、hush
- Config.in —— 配置菜单的 Kconfig 文件
- Makefile —— 主 Makefile,编译入口
嗯,看到这些目录,你就知道 Busybox 为什么叫“瑞士军刀”了——它把几百个命令塞进了一个可执行文件里。
2.7 整体流程一览
为了让你更直观地理解这一章的内容,我画了一张流程图。它展示了从宿主机环境到最终交叉编译 Busybox 的完整链路。
这张图把咱们这一章做的事串起来了。从宿主机出发,选工具链、下载、解压、配环境,最后拿到 Busybox 源码。每一步都环环相扣,缺一不可。
2.8 验证交叉编译环境
源码下载完了,别急着编译。先写个简单的 C 程序,验证一下交叉编译工具链能不能正常工作。
# 写一个测试程序
cat > hello.c << 'EOF'
#include <stdio.h>
int main(void)
{
printf("Hello from Busybox course!\n");
return 0;
}
EOF
# 用交叉编译器编译
arm-linux-gnueabihf-gcc -o hello hello.c
# 查看生成的文件类型
file hello
如果输出类似下面这样,说明环境没问题:
hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, not stripped
看到 ARM 这个关键字了吗?这就对了。你是在 x86 的机器上,编译出了 ARM 架构的可执行文件。交叉编译,就是这么回事。
常见问题:如果提示 arm-linux-gnueabihf-gcc: command not found,说明 PATH 没设置对。检查一下 setenv.sh 里的路径是否跟实际解压路径一致。我曾经因为路径里多了一个斜杠,排查了十分钟。
2.9 本章小结
这一章我们做了三件事:
- 理解了交叉编译的必要性——说白了就是“在 x86 上编译,给 ARM 用”
- 下载并安装了 Linaro GCC 交叉编译工具链
- 下载了 Busybox 1.36.1 源码,并验证了环境