4. Poky源码获取:克隆Poky仓库、选择稳定分支、理解目录结构

好,咱们正式开始动手。上一章聊了Yocto的整体架构,你可能已经对Poky这个「参考发行版」有了概念。这一章,我们就把它拉到本地,看看里面到底装了些什么。

我个人习惯把Poky叫做「Yocto的样板间」。你想想看,一个空房子装修,总得有个参考吧?Poky就是那个已经装好水电、铺好地板的样板间。我们基于它改造,比从零开始搭积木要快得多。

4.1 克隆Poky仓库

先别急着敲命令,咱们得选对地方。我建议你在家目录下建一个专门的Yocto工作区,比如 ~/yocto。别把东西散得到处都是,后面维护起来会疯掉。

mkdir -p ~/yocto
cd ~/yocto
git clone git://git.yoctoproject.org/poky

这条命令会从Yocto的官方Git服务器拉取Poky仓库。嗯,这里要注意:如果你在公司内网,或者网络环境不太好,可能会卡住。我曾经在客户现场遇到过,git://协议被防火墙拦截了。这时候可以换成https协议:

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

克隆完成后,你会看到一个 poky 目录。进去看看:

cd poky
git branch -a

你会看到一大堆分支。别慌,我们只需要稳定分支。

4.2 选择稳定分支

Yocto每半年发布一个正式版本,比如 kirkstone、langdale、mickledore。每个版本都有对应的稳定分支,命名规则是 <代号>-<版本号>。

我个人建议:永远不要用master分支做产品开发。master是开发分支,今天能编译通过,明天可能就挂了。我在项目里吃过这个亏——早上拉的最新代码,下午构建到一半就报错,查了半天发现是某个recipe的依赖被改了。

那怎么选?看你的项目需求。比如我们做UEFI启动分区,需要稳定的构建环境,我推荐用 kirkstone 或 mickledore。这两个版本对UEFI的支持比较成熟。

# 查看所有远程分支
git branch -r

# 切换到kirkstone分支
git checkout -b kirkstone-4.0.12 origin/kirkstone-4.0.12

为什么我要指定完整版本号?因为分支名 kirkstone 可能指向最新的小版本,而 kirkstone-4.0.12 是固定的。你想想看,团队里五个人,如果每个人拉到的分支指向不同的小版本,构建出来的东西能一样吗?

我的小技巧: 每次开始新项目,我都会在 git checkout 之后,用 git log --oneline -1 确认一下当前HEAD的commit ID。把这个commit ID记在项目的README里,万一以后需要回退,直接 git checkout 这个commit就行,比记分支名靠谱。

4.3 理解目录结构

好,现在代码拉下来了,分支也切好了。咱们来看看Poky这个「样板间」里到底有什么。我用 tree -L 1 看一下顶层目录:

poky/
├── bitbake/        # 构建引擎,Yocto的心脏
├── build/          # 构建输出目录(初始为空)
├── contrib/        # 社区贡献的辅助脚本
├── documentation/  # 文档源码
├── meta/           # 核心元数据层
├── meta-poky/      # Poky发行版配置层
├── meta-selftest/  # 自测试用例
├── meta-skeleton/  # 空模板层,教你如何创建新层
├── meta-yocto-bsp/ # 参考BSP(板级支持包)
├── oe-init-build-env  # 初始化构建环境的脚本
├── README.hardware.txt
├── README.poky
└── README.qemu

别被这么多目录吓到。说白了,你日常打交道最多的就三个:bitbake、meta、meta-poky。其他的要么是辅助工具,要么是示例。

我画了一张图,帮你理清它们之间的关系:

Poky 目录结构核心关系图 Poky 根目录 bitbake/ meta/ meta-poky/ 解析器 任务调度器 recipes/ classes/ conf/ files/ 发行版配置 本地镜像源 说明: • bitbake/:构建引擎,负责解析recipe、调度任务、管理依赖。 • meta/:核心元数据层,包含所有基础recipe、class和配置文件。 • meta-poky/:Poky发行版特有的配置,比如默认的distro设置。 • 其他目录(meta-skeleton等)是辅助层,新手可以先忽略。

咱们重点说说三个核心目录:

4.3.1 bitbake/ — 构建引擎

这是Yocto的心脏。说白了,bitbake就是一个专门为嵌入式构建优化的任务调度器。它读取recipe文件,解析依赖关系,然后决定先编译什么、后编译什么。

你不需要修改bitbake的代码,但得知道它怎么工作。比如,当你执行 bitbake core-image-minimal 时,bitbake会去 meta/ 里找 core-image-minimal 这个recipe,然后递归解析它的所有依赖。

4.3.2 meta/ — 核心元数据层

这是Poky里最大的目录,也是你以后最常打交道的地方。它包含了:

  • recipes/:各种软件的构建配方,比如glibc、gcc、busybox。每个recipe告诉bitbake去哪里下载源码、怎么打补丁、怎么编译、怎么安装。
  • classes/:可复用的构建逻辑。比如 autotools.bbclass 封装了autotools的构建流程,你写recipe时直接 inherit autotools 就行。
  • conf/:全局配置文件,比如 bitbake.conf 定义了所有recipe都能用的默认变量。
  • files/:一些通用的文件,比如许可协议文本。

4.3.3 meta-poky/ — 发行版配置层

这个目录定义了Poky这个「发行版」的默认行为。比如:

  • conf/distro/poky.conf:Poky发行版的配置文件,定义了版本号、维护者信息、默认的包管理器(rpm/ipk/deb)等。
  • conf/local.conf.sample:本地构建配置的模板。你执行 oe-init-build-env 后,这个文件会被复制到 build/conf/local.conf。
重点理解: meta/ 和 meta-poky/ 的关系。meta/ 是「通用零件库」,meta-poky/ 是「组装说明书」。你以后自己创建 meta-<你的项目> 层时,也是同样的思路——把通用零件放在基础层,把项目特有的配置放在上层。

4.4 初始化构建环境

好,目录结构看完了。咱们来实际初始化一下构建环境,看看效果:

cd ~/yocto/poky
source oe-init-build-env build

执行后,你会看到类似这样的输出:

You had no conf/local.conf file. This configuration file has therefore been
created for you with some default values. You may wish to edit it to use a
different MACHINE (target hardware) or enable parallel build options.

The Yocto Project has extensive documentation about OE including a reference
manual which can be found at:
    https://docs.yoctoproject.org

For more information about OpenEmbedded see their website:
    https://www.openembedded.org/

同时,当前目录会切换到 ~/yocto/poky/build。这个 build 目录就是你的构建工作区。里面有两个关键文件:

文件 作用 我常用的配置
conf/local.conf 本地构建配置,比如目标硬件、并行编译数、下载目录等 MACHINE = "qemux86-64"
BB_NUMBER_THREADS = "8"
conf/bblayers.conf 告诉bitbake去哪些层找recipe 默认包含 meta、meta-poky、meta-yocto-bsp
注意: 每次打开新终端,都要先执行 source oe-init-build-env build 才能使用bitbake命令。我刚开始学的时候经常忘记,然后直接敲 bitbake,结果提示「命令未找到」。后来我养成了一个习惯:在终端标题上写上「yocto-env」,提醒自己当前环境已初始化。

4.5 避坑指南

最后,分享几个我踩过的坑:

  • 磁盘空间:Poky仓库本身不大(约1GB),但构建产物会占用大量空间。我建议至少预留50GB给 build/ 目录。我曾经在只有20GB的虚拟机上构建,结果编译到一半磁盘满了,整个构建目录废掉,只能重来。
  • 网络问题:如果git clone慢,可以试试用 --depth 1 只拉取最新commit,减少数据量。但注意,这样你就没有完整的git历史了,以后想切分支会比较麻烦。
  • 分支一致性:团队协作时,确保所有人都用同一个commit ID。别问为什么——我见过两个人用同一个分支名,但拉取时间不同,导致构建出来的镜像sha256值不一样,排查了一整天。