3、开发环境搭建:主机要求、安装必要软件包、克隆Poky仓库、初始化构建环境、首次构建

好,咱们正式开始动手了。这一章我带你把整个开发环境搭起来。别小看这一步,我见过太多人卡在环境上,折腾一整天连个镜像都没编译出来。说白了,环境搭好了,后面的事就顺了。

3.1 主机要求:别让你的电脑太委屈

Yocto 是个吃资源的家伙。我刚开始用的时候,拿一台 4GB 内存的笔记本跑,结果编译到一半直接 OOM 了。嗯,从那以后我再也不敢轻视硬件要求。

我个人建议,至少满足以下配置:

硬件项 最低要求 推荐配置
CPU 4 核 x86_64 8 核或更多
内存 8 GB 16 GB 以上
磁盘 100 GB 空闲 250 GB SSD
操作系统 Ubuntu 20.04 / 22.04 Ubuntu 22.04 LTS
注意:千万别用虚拟机跑完整编译,除非你很有耐心。我在项目中试过,同样的代码,物理机 30 分钟搞定,虚拟机跑了 2 小时还没完。磁盘 I/O 是瓶颈。

操作系统方面,我个人偏爱 Ubuntu 22.04 LTS。CentOS 也行,但包管理方式不同,后面装依赖时容易踩坑。你想想看,Yocto 官方文档里测试最多的就是 Ubuntu,跟着大部队走总没错。

3.2 安装必要软件包:缺一不可

Yocto 依赖一堆系统工具。我曾经犯过一个低级错误——以为只装 gcc 就够了,结果编译到一半报错说缺 chrpath。嗯,这种错误最烦人,因为你要等很久才发现。

在 Ubuntu 22.04 上,我习惯这样装:

sudo apt update
sudo apt install gawk wget git diffstat unzip texinfo gcc build-essential \
  chrpath socat cpio python3 python3-pip python3-pexpect xz-utils \
  debianutils iputils-ping python3-git python3-jinja2 libegl1-mesa \
  libsdl1.2-dev xterm python3-subunit mesa-common-dev zstd liblz4-tool

这里有个细节:zstdliblz4-tool 是较新版本 Yocto 才需要的。如果你用老版本(比如 dunfell),可以跳过。但我建议统一装上,省得后面麻烦。

小技巧:装完后可以用 which chrpath 快速验证关键工具是否存在。我每次搭新环境都会跑一遍这个命令,心里踏实。

3.3 克隆 Poky 仓库:选对分支很重要

Poky 是 Yocto 的参考发行版,也是我们学习的起点。克隆它很简单:

git clone git://git.yoctoproject.org/poky
cd poky

但这里有个坑——分支选择。Yocto 每半年发一个大版本,每个版本有对应的稳定分支。我个人建议初学者用最新的 LTS 版本,比如当前是 scarthgap(对应 5.0 LTS)。

为什么?因为 LTS 版本维护周期长,社区支持好,遇到问题更容易搜到答案。我曾经图新鲜用开发分支,结果某个 recipe 的语法变了,文档还没更新,折腾了两天才搞定。

git checkout scarthgap

如果你不确定当前有哪些分支,可以看看:

git branch -a | grep remotes/origin/

嗯,这里要注意,master 分支是开发中的,不稳定,别用。

3.4 初始化构建环境:理解背后的逻辑

克隆完 Poky 后,我们需要初始化构建环境。这一步很多人只是机械地执行命令,不明白背后发生了什么。我刚开始也是,直到有一次环境变量乱了,才回头去研究。

初始化命令很简单:

source oe-init-build-env build

这条命令做了三件事:

  1. 创建 build 目录(如果不存在)
  2. build/conf 下生成 local.confbblayers.conf
  3. 设置一系列环境变量,比如 TEMPLATECONFBBPATH

我个人习惯在初始化后,先看一眼 local.conf

cat conf/local.conf | head -30

你会看到默认的 MACHINEqemux86-64DL_DIRSSTATE_DIR 都在 build 目录下。这些都可以改,但第一次构建我建议保持默认。

核心理解:每次打开新终端,都要重新 source oe-init-build-env。环境变量只在当前 shell 有效。我吃过这个亏——开了新窗口直接 bitbake,结果报错说找不到命令。

3.5 首次构建:耐心是美德

终于到了最激动人心的时刻。首次构建我建议选最小的目标——core-image-minimal。它只包含最基本的 Linux 系统,启动后就是一个 shell。为什么选它?因为编译快,出错容易排查。

bitbake core-image-minimal

然后,就是漫长的等待。我第一次构建时,看着屏幕上刷刷刷的日志,心里既兴奋又焦虑。兴奋的是终于跑起来了,焦虑的是不知道要等多久。

这里我分享几个经验:

  • 首次构建通常需要 1-2 小时,取决于你的网络和 CPU。大部分时间花在下载源码包和编译交叉工具链上。
  • 网络一定要稳。Yocto 会从多个上游仓库下载源码,如果中途断网,重来很痛苦。我建议用有线网络,别用 WiFi。
  • 留意 downloads 目录。所有下载的源码包都缓存在 build/downloads 下。如果某次构建失败,下次会复用已下载的文件。
避坑指南:我曾经在构建过程中按了 Ctrl+C,以为可以暂停。结果 BitBake 直接退出,下次重新编译时,部分临时文件损坏,不得不 rm -rf tmp 清空重来。所以,要么等它跑完,要么用 bitbake -k 跳过错误继续。

构建成功后,你会看到类似这样的输出:

NOTE: Tasks summary: Attempted 1234 tasks of which 0 didn't need to be rerun, all succeeded.

然后,你可以用 QEMU 启动它:

runqemu qemux86-64

看到登录提示符的那一刻,说实话,挺有成就感的。虽然只是一个最小的系统,但这是你亲手从源码构建出来的。

3.6 构建后的目录结构:心里有数

构建完成后,build 目录下会多出几个关键子目录。我简单说一下:

目录 作用
tmp 编译过程中的临时文件,包括目标文件、日志等
tmp/deploy/images 最终生成的镜像文件,比如 core-image-minimal-qemux86-64.rootfs.ext4
downloads 所有下载的源码包缓存
sstate-cache 共享状态缓存,加速后续构建

我个人习惯把 downloadssstate-cache 移到独立分区或外部硬盘。因为随着项目增多,这两个目录会变得非常大。我曾经见过一个团队,sstate-cache 占了 50 GB,全挤在系统盘上,最后磁盘满了。

3.7 常见问题与解决思路

首次构建很少一帆风顺。我整理了几个高频问题:

  • 下载超时:某些源码包托管在 SourceForge 或 GitHub,国内访问慢。解决方案是配置代理,或者用 PREMIRRORS 指向国内镜像。
  • 磁盘空间不足tmp 目录会膨胀到几十 GB。建议用 df -h 提前检查,预留至少 50 GB 空间。
  • 依赖缺失:如果报错说找不到某个库,先确认是否装了 3.2 节列出的所有包。我遇到过缺 libsdl1.2-dev 的情况,补上就好。
我的习惯:每次构建前,先跑 bitbake -s | grep core-image-minimal 确认目标存在。这能避免拼写错误导致的无效构建。

好了,环境搭好了,镜像也跑起来了。下一章我们深入 BitBake 的语法和任务调度机制。说实话,理解了 BitBake,Yocto 就学通了一半。