2. 编译环境搭建:交叉编译工具链安装、下载Busybox源码、配置编译选项
说实话,很多初学者一上来就卡在环境搭建这一步。我见过不少朋友,源码下载好了,make 一敲,满屏报错,然后就放弃了。其实没那么玄乎,咱们一步步来。
2.1 交叉编译工具链——为什么需要它?
你平时在 PC 上写 C 代码,gcc 编译出来的程序是给 x86 架构用的。但嵌入式设备通常是 ARM、MIPS、RISC-V 这些架构。PC 上编译出来的二进制,放到 ARM 板子上根本跑不起来。
交叉编译工具链,说白了就是一套能在 PC 上生成目标架构机器码的工具集。它包括编译器、链接器、库文件、头文件等。我刚开始做嵌入式时,总觉得装个工具链很麻烦,后来发现其实就几条命令的事。
核心概念:交叉编译 = 在宿主机(PC)上编译,生成目标机(嵌入式设备)可执行的代码。
2.2 安装交叉编译工具链
我个人习惯用 Linaro 提供的预编译工具链,稳定且社区活跃。当然你也可以用 Buildroot 或 Yocto 自己编译,但那是后话了。这里我以 ARM 架构为例。
2.2.1 下载与解压
# 下载 ARM 交叉编译工具链(以 gcc-arm-10.3-2021.07 为例)
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 -xf gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf.tar.xz -C /opt
# 重命名(方便后续操作)
sudo mv /opt/gcc-arm-10.3-2021.07-x86_64-arm-none-linux-gnueabihf /opt/arm-gcc
2.2.2 配置环境变量
每次编译都写绝对路径太麻烦。我建议把它加到 PATH 里。
# 编辑 ~/.bashrc 或 ~/.zshrc
export PATH=/opt/arm-gcc/bin:$PATH
export ARCH=arm
export CROSS_COMPILE=arm-none-linux-gnueabihf-
# 使配置生效
source ~/.bashrc
小提示:设置 CROSS_COMPILE 环境变量时,后面的横线不能丢。Busybox 的 Makefile 会自动拼接这个前缀来调用对应的编译器。
2.2.3 验证安装
arm-none-linux-gnueabihf-gcc --version
# 输出类似:
# arm-none-linux-gnueabihf-gcc (GNU Toolchain for the A-profile Architecture 10.3-2021.07) 10.3.1 20210621
# Copyright (C) 2020 Free Software Foundation, Inc.
看到版本信息,说明工具链装好了。我曾经遇到过一次,明明装了却提示找不到命令,后来发现是 PATH 没写对,少了个 /bin 路径。嗯,这种细节最容易坑人。
2.3 下载 Busybox 源码
Busybox 的源码托管在 git 上。我建议直接克隆官方仓库,方便后续切换版本。
# 克隆最新稳定版
git clone git://busybox.net/busybox.git
# 或者下载指定版本的 tarball(更稳定)
wget https://busybox.net/downloads/busybox-1.36.1.tar.bz2
tar -xf busybox-1.36.1.tar.bz2
cd busybox-1.36.1
注意:生产环境建议用 tarball 版本,git 上的 master 分支可能包含未稳定测试的代码。我踩过这个坑,编译出来某个命令行为异常,查了半天才发现是开发分支的 bug。
2.4 配置编译选项——make menuconfig
这是最核心的一步。Busybox 提供了类似 Linux 内核的配置界面,你可以选择要编译哪些命令、启用哪些特性。
2.4.1 启动配置界面
make menuconfig
执行后,你会看到一个蓝底白字的菜单界面。第一次看到可能会有点懵,其实操作很简单:方向键移动,回车进入子菜单,空格或 Y 选中,N 取消。
2.4.2 关键配置项
我个人习惯先做这几项基础配置:
| 配置路径 | 选项 | 说明 |
|---|---|---|
| Settings → Build Options | Build static binary (no shared libs) | 静态编译,避免目标板上缺少动态库 |
| Settings → Build Options | Cross compiler prefix | 填入 arm-none-linux-gnueabihf- |
| Settings → General Configuration | Enable support for long options | 启用长选项支持,比如 --help |
| Settings → General Configuration | Don't use /usr | 避免安装时污染宿主系统 |
| Linux Module Utilities | 按需选择模块工具 | 如果目标板需要 insmod、rmmod 等 |
关键点:静态编译(static binary)是我强烈推荐的。嵌入式目标板上可能没有 glibc 或 musl,动态链接会导致程序无法运行。静态编译把所有依赖都打包进二进制,省心很多。
2.4.3 配置界面操作速查
| 按键 | 功能 |
|---|---|
| ↑ ↓ | 移动光标 |
| Enter | 进入子菜单 / 确认 |
| Y / 空格 | 选中(编译进 Busybox) |
| N | 取消选中 |
| M | 编译为模块(Busybox 中较少用) |
| ? | 查看帮助 |
| / | 搜索配置项 |
| Esc + Esc | 退出当前菜单 |
2.4.4 保存配置
配置完成后,选择 Save,默认保存为 .config 文件。你也可以指定其他文件名,比如 config_arm,方便以后复用。
# 保存后,.config 文件内容类似这样:
CONFIG_STATIC=y
CONFIG_CROSS_COMPILER_PREFIX="arm-none-linux-gnueabihf-"
CONFIG_FEATURE_LONG_OPTIONS=y
CONFIG_INSTALL_NO_USR=y
2.5 整体流程一览
我把整个环境搭建的流程画了张图,方便你对照操作:
2.6 常见问题与避坑
- 工具链版本不匹配:我曾经用过一个太老的 gcc 4.8 编译 Busybox 1.36,结果报了一堆语法错误。建议工具链版本不低于 gcc 8.x。
- PATH 没生效:配置完环境变量后,记得
source ~/.bashrc或者重新登录终端。我见过有人配了但忘了 source,然后跑来问我为什么找不到编译器。 - menuconfig 缺少 ncurses:如果执行
make menuconfig报错,通常是缺少 libncurses-dev。安装一下就好:sudo apt install libncurses-dev。 - 静态编译导致体积过大:静态编译确实会让 Busybox 变大,但嵌入式设备通常有几 MB 的 flash 空间,完全够用。如果实在空间紧张,可以考虑用 musl 替代 glibc 进行静态编译,体积能小不少。
我的习惯:每次配置完,我都会把 .config 文件备份一份,命名为 config_arm_v1 之类的。这样下次重新编译时,直接 cp config_arm_v1 .config 就能复用,不用再进 menuconfig 重新选一遍。