4、第一个Yocto构建:初始化构建环境、配置本地构建(local.conf)、运行BitBake构建最小镜像(core-image-minimal)
好,到了真正动手的时候了。
前面几章我们把Yocto的体系结构、术语、下载都捋了一遍。现在,我们要做第一个真正的构建——用BitBake编译出一个core-image-minimal。这个镜像很小,但五脏俱全,是验证你的Yocto环境是否正常工作的最佳起点。
我个人习惯把这一步叫做“点火测试”。如果这一步能跑通,后面移植BSP、添加软件包就只是时间问题了。
4.1 初始化构建环境
还记得我们之前用git clone拉下来的Poky仓库吗?里面有个脚本叫oe-init-build-env,它就是整个构建环境的入口。
核心命令:
cd ~/yocto/poky
source oe-init-build-env build
执行完这条命令,会发生几件事:
- 在当前目录下创建一个
build文件夹(如果不存在的话) - 自动
cd进这个build目录 - 设置一系列环境变量,比如
TEMPLATECONF、BBPATH、BUILDDIR - 从
meta-poky/conf复制默认的local.conf和bblayers.conf到build/conf
嗯,这里要注意:source这个操作不是一次性的。你每次打开新终端想用BitBake,都得先跑一遍source oe-init-build-env。我刚开始学的时候经常忘记,然后直接敲bitbake core-image-minimal,结果报错“command not found”。
小技巧: 我习惯在~/.bashrc里加一个别名:
alias yocto='cd ~/yocto/poky && source oe-init-build-env build'
这样每次只需要敲yocto三个字母,环境就准备好了。
4.2 理解构建目录结构
初始化完成后,你的build目录下会生成这些关键文件:
| 文件/目录 | 作用 |
|---|---|
conf/local.conf |
本地构建配置,定义目标机器、并行任务数、下载目录等 |
conf/bblayers.conf |
层配置文件,告诉BitBake去哪里找meta-*层 |
tmp/ |
构建过程中的临时文件、工作目录、最终镜像输出 |
downloads/ |
所有源码包的缓存目录,避免重复下载 |
sstate-cache/ |
共享状态缓存,加速后续构建 |
说白了,build目录就是你的“施工现场”。所有原材料(源码)、半成品(编译中间产物)、成品(镜像文件)都在这里。
4.3 配置local.conf——最关键的一步
默认生成的local.conf有很多注释掉的选项。我们需要根据实际硬件平台修改几个关键参数。我以qemuarm64为例,这是最通用的模拟器目标。
避坑指南: 我曾经在一个项目里直接用了默认的local.conf,结果编译出来的镜像在目标板上起不来。查了两天才发现是MACHINE变量没改,编译的是qemux86-64的镜像。所以第一步,先确认你的目标机器。
4.3.1 设置MACHINE变量
# 找到这一行,去掉注释并修改
MACHINE ?= "qemuarm64"
这个变量决定了BitBake为哪个硬件平台编译。常见的值有:
qemuarm64—— ARMv8 64位模拟器qemux86-64—— x86_64模拟器raspberrypi4-64—— 树莓派4B(需要额外meta-raspberrypi层)beaglebone-yocto—— BeagleBone Black
4.3.2 设置并行编译数
# 根据你的CPU核心数调整
BB_NUMBER_THREADS = "8"
PARALLEL_MAKE = "-j 8"
这两个参数控制并行编译的力度。我建议设置为CPU物理核心数的1.5到2倍。比如4核8线程的CPU,设成-j 8比较合理。设太大反而会因为IO瓶颈变慢。
4.3.3 设置下载目录和缓存目录
# 共享下载目录,避免每个构建目录都下载一遍
DL_DIR ?= "/home/你的用户名/yocto/downloads"
# 共享状态缓存目录
SSTATE_DIR ?= "/home/你的用户名/yocto/sstate-cache"
我个人强烈建议把DL_DIR和SSTATE_DIR放到构建目录外面。为什么?因为如果你删掉build目录重新构建,之前下载的几百兆源码包和编译缓存就全没了。放在外面可以跨项目复用。
4.3.4 其他常用配置
# 设置目标系统的包管理器格式(rpm/deb/ipk)
PACKAGE_CLASSES ?= "package_rpm"
# 设置rootfs的额外空间(单位MB)
IMAGE_ROOTFS_EXTRA_SPACE = "1048576"
# 开启用户态网络(用于QEMU)
QB_NETWORK_DEVICE ?= "-netdev user,id=net0,hostfwd=tcp::2222-:22"
我的经验: 第一次构建时,建议把BB_NUMBER_THREADS设小一点(比如4),等确认环境没问题再调大。因为如果某个recipe编译失败,并行任务太多会导致日志混乱,很难定位问题。
4.4 运行BitBake构建最小镜像
配置好local.conf,就可以开始构建了。确保你已经source了环境,然后在build目录下执行:
bitbake core-image-minimal
这个命令会触发一系列动作:
- BitBake解析所有
.bb和.bbappend文件 - 生成依赖关系树
- 按照依赖顺序依次执行
fetch、unpack、patch、configure、compile、install、package、image等任务 - 最终在
tmp/deploy/images/qemuarm64/下生成镜像文件
第一次构建时间会比较长,通常30分钟到2小时不等,取决于你的网络速度和CPU性能。BitBake会在终端实时打印进度,像这样:
Parsing recipes: 100% |####################################| Time: 0:00:15
Initialising tasks: 100% |#################################| Time: 0:00:02
Loading cache: 100% |######################################| Time: 0:00:01
Checking sstate mirror object: 100% |######################| Time: 0:00:01
Executing Tasks (1 of 187): linux-yocto_6.6.bb:do_fetch 0%
常见问题: 如果构建过程中断(比如网络超时、磁盘空间不足),不要慌。重新执行bitbake core-image-minimal,BitBake会从断点继续,不会从头开始。这是Yocto最人性化的设计之一。
4.5 构建成功后的产物
构建完成后,在tmp/deploy/images/qemuarm64/目录下你会看到:
| 文件 | 说明 |
|---|---|
core-image-minimal-qemuarm64.rootfs.ext4 |
根文件系统镜像(ext4格式) |
core-image-minimal-qemuarm64.rootfs.tar.bz2 |
根文件系统的压缩包 |
core-image-minimal-qemuarm64.qemuboot.conf |
QEMU启动配置文件 |
zImage--6.6.21+git0+...r0-qemuarm64-...bin |
Linux内核镜像 |
Image--6.6.21+git0+...r0-qemuarm64-...bin |
ARM64内核镜像(如果目标支持) |
你可以用QEMU直接启动这个镜像验证:
runqemu qemuarm64 nographic
看到登录提示符后,输入root(默认无密码),你就成功进入了自己构建的嵌入式Linux系统。
4.6 本章知识结构图
下面这张图总结了从初始化环境到构建成功的完整流程:
4.7 常见问题与排查
第一次构建很少一帆风顺。我整理了几个高频问题:
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
do_fetch失败 |
网络不通或源码地址变更 | 检查代理设置,或手动下载源码放到DL_DIR |
do_compile报错 |
缺少系统依赖包 | 安装gcc、make、flex、bison等 |
| 磁盘空间不足 | tmp目录占用过大 |
清理tmp或挂载大容量分区到build |
| QEMU启动黑屏 | 缺少图形库或终端配置错误 | 使用nographic模式,或安装sdl库 |
我的排查习惯: 遇到错误先看最后几行日志,找到ERROR:开头的行。然后去tmp/work/对应recipe的工作目录下看temp/log.do_*文件,那里有完整的编译输出。别在终端里翻几千行日志,效率太低。
好了,到这里你已经完成了第一个Yocto构建。虽然只是最小镜像,但整个流程——初始化、配置、构建、验证——和后面移植BSP、定制发行版是完全一致的。这个基础打牢了,后面的路就好走了。