2. 编译环境搭建:交叉编译工具链安装、环境变量配置、源码下载与解压

好,咱们正式开始动手。上一章聊完了 BusyBox 是什么、能干什么,这一章就得把「家伙事儿」备齐了。

说白了,嵌入式开发跟 PC 开发最大的区别就是——你写的代码不是在当前电脑上跑的。你在一台 x86 的 Linux 机器上写代码,编译出来的东西却要扔到 ARM、MIPS 或者 RISC-V 的板子上跑。这就需要一个「翻译官」:交叉编译工具链。

我个人习惯把搭建环境分成三步走:
1. 拿到合适的工具链
2. 配好环境变量,让系统能找到它
3. 下载 BusyBox 源码,解压待命

咱们一步一步来。嗯,这里要注意,每一步踩坑了后面都得返工,所以别急。

2.1 交叉编译工具链的安装

什么是交叉编译工具链?我换个说法你就懂了:它是一整套工具,包括编译器(gcc)、链接器(ld)、库文件、头文件等等。只不过这套工具生成的目标代码是给别的 CPU 架构用的。

我在项目中遇到过好几次,新手直接拿 PC 上的 gcc 去编译嵌入式程序,结果放到板子上跑不起来。为什么会这样?因为指令集都不一样,根本没法执行。

工具链的获取方式,常见的有三种:

方式 说明 推荐指数
芯片厂商提供 比如 ARM 官方、ST、NXP 等厂家提供的 SDK 里自带 ⭐⭐⭐⭐⭐
Linaro 预编译版 针对 ARM 架构,社区维护,更新快 ⭐⭐⭐⭐
Buildroot / Yocto 自编译 自己从源码编译工具链,灵活但耗时 ⭐⭐⭐

我个人建议,初学者直接用 Linaro 的预编译版本。省时间,也稳定。以 ARM 为例,下载命令如下:

# 下载 ARM 交叉编译工具链(以 gcc-arm-10.3 为例)
wget https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf.tar.xz

# 解压到 /opt 目录
sudo tar -xvf gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf.tar.xz -C /opt/

解压完之后,你会得到一个文件夹,里面就是完整的工具链。你可以进去看看:

ls /opt/gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf/bin/

你会看到一堆以 arm-none-linux-gnueabihf- 开头的文件,比如 arm-none-linux-gnueabihf-gcc、arm-none-linux-gnueabihf-ld 等等。这些就是我们要用的交叉编译工具。

注意: 工具链的命名规则里藏着信息。比如 arm-none-linux-gnueabihf 表示:目标架构是 ARM,没有操作系统(none),目标系统是 Linux,使用 GNU 库,支持硬浮点(hf)。选错了,编译出来的东西可能跑不起来。

2.2 环境变量配置

工具链装好了,但系统还不知道它在哪。你得告诉系统:「嘿,以后我敲 arm-linux-gcc 的时候,你去这个目录找。」

配置环境变量,说白了就是把工具链的 bin 目录加到 PATH 里。我个人习惯把它写到 ~/.bashrc 里,这样每次打开终端自动生效。

# 编辑 ~/.bashrc
vim ~/.bashrc

# 在文件末尾添加以下内容
export PATH=$PATH:/opt/gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf/bin
export CROSS_COMPILE=arm-none-linux-gnueabihf-
export ARCH=arm

# 保存退出后,使配置生效
source ~/.bashrc

这里我多配了两个变量:CROSS_COMPILE 和 ARCH。这两个在编译 BusyBox 和 Linux 内核时会用到。提前配好,后面省事。

验证一下工具链是否生效:

arm-none-linux-gnueabihf-gcc --version

如果能看到版本信息,说明环境变量配对了。我曾经见过有人配了路径但没 source,然后跑来问我为什么找不到命令……嗯,这种坑踩过一次就记住了。

小技巧: 如果你同时维护多个项目,需要不同版本的工具链,建议写一个 setenv.sh 脚本,每个项目单独 source。别一股脑全塞到 .bashrc 里,不然版本冲突的时候你会很头疼。

2.3 源码下载与解压

工具链就位了,接下来去拿 BusyBox 的源码。BusyBox 的官方地址是 https://busybox.net/,你可以直接下载最新的稳定版。

我个人习惯用 wget 下载,然后解压到工作目录:

# 下载 BusyBox 1.36.1 稳定版
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2

# 解压
tar -xvf busybox-1.36.1.tar.bz2

# 进入源码目录
cd busybox-1.36.1/

解压完之后,你会看到一堆文件和目录。别慌,核心的就几个:

  • Makefile:编译入口,所有编译规则都在这里
  • Config.in:配置菜单的描述文件,类似内核的 Kconfig
  • applets/:各个命令的源码,比如 ls、cp、mv 都在这里
  • libbb/:BusyBox 自己的公共库函数
  • include/:头文件

你可以先看看目录结构,心里有个数。后面我们做裁剪的时候,大部分时间都在跟 Config.in 和 applets/ 打交道。

核心要点: 源码下载后,建议先不要急着编译。先看看 README 和 INSTALL 文件,里面有很多有用的信息。我每次拿到一个新项目,第一件事就是读 README,能省掉很多弯路。

2.4 本章知识体系一览

为了让你更直观地理解这一章的内容,我画了一张流程图。它把整个环境搭建的脉络串起来了:

编译环境搭建流程 1. 获取交叉工具链 2. 解压到指定目录 3. 配置环境变量 4. 验证工具链 5. 下载 BusyBox 源码 6. 解压并查看目录结构 ✅ 环境搭建完成 蓝色:工具链相关 | 橙色:源码相关 | 绿色:完成状态

这张图把整个流程分成了两大块:工具链部分和源码部分。你跟着箭头走,一步做完再做下一步,基本不会出错。

2.5 常见问题与避坑

最后,我分享几个实际项目中踩过的坑:

  • 路径带空格: 我曾经把工具链解压到了 /opt/my tools/ 目录下,结果编译时各种报错。后来才发现是路径里的空格惹的祸。记住,嵌入式开发的所有路径,不要有空格,不要有中文。
  • 32位库缺失: 有些老版本的工具链是 32 位的,在 64 位系统上跑需要安装 32 位兼容库。报错信息通常是 No such file or directory,但文件明明存在。这时候执行 sudo apt install lib32z1 lib32ncurses5 就能解决。
  • 版本不匹配: 工具链的 glibc 版本如果太老,编译出来的 BusyBox 可能在新系统上跑不了。反过来,工具链太新,老内核可能不支持。我一般选 Linaro 的 LTS 版本,稳。

好了,环境搭好了,源码也准备好了。下一章咱们就开始配置 BusyBox,做第一次裁剪。到时候你会看到,原来一个「ls」命令背后也有这么多门道。


可可精品资料库