2. Yocto核心概念解析:Poky、BitBake、Metadata、Layer、Recipe、Class、Configuration文件
说实话,刚接触Yocto那会儿,我也被这一堆术语搞得头晕。Poky是什么?BitBake又是干嘛的?Layer和Recipe到底啥关系?
别急,这一章咱们就把这些概念一个一个掰开揉碎了讲。我保证,看完之后你心里会有一张清晰的地图。
2.1 核心概念全景图
先上一张图,让你对整体有个印象。Yocto的构建系统,本质上是一个分层驱动的代码生成工厂。
这张图你看懂了吗?从上到下,就是Yocto构建的完整逻辑链。咱们接下来一个一个拆解。
2.2 Poky —— 一切的起点
Poky 是什么?说白了,它是Yocto项目官方维护的一个参考发行版,也是一个元数据集合。
我刚开始学的时候,以为Poky就是Yocto本身。其实不是。Yocto是一个开源协作项目,而Poky是它提供的一个“样板间”。
- 它包含BitBake:任务执行引擎。
- 它包含Metadata:一堆Recipe、Class、Configuration文件。
- 它包含一个默认的构建环境:你
git clone下来,就能直接跑bitbake core-image-minimal。
kirkstone 或 dunfell)开始。不要从零开始写,那是给自己找麻烦。
2.3 BitBake —— 真正的“发动机”
BitBake 是一个任务调度引擎。你可以把它理解成一个“超级Makefile解析器”。
它负责:
- 解析Metadata:读取所有Recipe、Class、Configuration。
- 构建依赖树:搞清楚哪个包先编译,哪个后编译。
- 调度任务:比如
do_fetch、do_patch、do_compile、do_install。 - 执行任务:并行或串行,全看依赖关系。
BitBake 的核心语法是 Shell 函数 + Python 函数。你可以在Recipe里写Shell脚本,也可以用Python写更复杂的逻辑。
# 一个简单的BitBake任务示例
do_display_config() {
bbplain "当前机器类型: ${MACHINE}"
bbplain "目标架构: ${TUNE_ARCH}"
}
addtask display_config before do_build
local.conf,但忘了重新 source oe-init-build-env,结果BitBake一直用旧配置跑了两个小时。记住:修改配置后,最好重新source环境,或者至少 bitbake -c cleanall 一下。
2.4 Metadata —— 构建的“灵魂”
Metadata 是Yocto里所有“非代码”文件的统称。它告诉BitBake:要做什么、怎么做、用什么做。
Metadata 主要包含以下几类文件:
| 文件类型 | 扩展名 | 作用 | 类比 |
|---|---|---|---|
| Recipe | .bb |
描述一个软件包的来源、依赖、编译、安装方式 | 菜谱 |
| Class | .bbclass |
可复用的构建逻辑,被多个Recipe继承 | 模板函数 |
| Configuration | .conf |
定义全局变量、机器特性、发行版策略 | 配置文件 |
| Append | .bbappend |
在不修改原Recipe的前提下,追加或覆盖内容 | 补丁文件 |
2.5 Recipe —— 最核心的“菜谱”
Recipe 是Yocto里出现频率最高的文件。每个Recipe对应一个软件包(比如 openssl、busybox、linux-yocto)。
一个典型的Recipe长这样:
# hello_1.0.bb
SUMMARY = "A simple hello world program"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://hello.c"
S = "${WORKDIR}"
do_compile() {
${CC} ${CFLAGS} ${LDFLAGS} hello.c -o hello
}
do_install() {
install -d ${D}${bindir}
install -m 0755 hello ${D}${bindir}
}
你看,Recipe里定义了:
- 元信息:摘要、许可证。
- 源码来源:从哪里下载或获取源码。
- 编译方法:用什么编译器、什么参数。
- 安装方法:把编译产物放到哪个目录。
hello_1.0.bb 表示包名是 hello,版本是 1.0。BitBake会根据版本号自动选择最新版本。
2.6 Class —— 可复用的“模板”
你有没有想过,如果每个Recipe都要自己写 do_compile 和 do_install,那得多累?
Class 就是来解决这个问题的。它把通用的构建逻辑抽出来,让Recipe通过 inherit 关键字继承。
常用的Class有:
autotools.bbclass:处理./configure && make && make install流程。cmake.bbclass:处理 CMake 构建。kernel.bbclass:专门用于构建Linux内核。deploy.bbclass:把构建产物部署到输出目录。
# 使用Class的Recipe示例
inherit autotools
SRC_URI = "https://example.com/libfoo-${PV}.tar.gz"
# 不需要写do_compile和do_install了,autotools.bbclass已经帮你搞定
do_compile,结果跟 autotools.bbclass 冲突,排查了半天。
2.7 Configuration 文件 —— 全局“开关”
Configuration 文件用来设置全局变量。它们决定了整个构建系统的行为。
常见的Configuration文件:
| 文件 | 位置 | 作用 |
|---|---|---|
local.conf |
build/conf/ |
用户本地配置,比如并行编译数、下载目录、目标机器 |
bblayers.conf |
build/conf/ |
声明哪些Layer被包含在构建中 |
machine.conf |
meta-*/conf/machine/ |
定义特定硬件平台的特性(如串口、内核设备树) |
distro.conf |
meta-*/conf/distro/ |
定义发行版策略(如包管理器、C库选择) |
举个例子,local.conf 里你可能会看到:
MACHINE ?= "qemuarm"
DL_DIR ?= "${TOPDIR}/downloads"
BB_NUMBER_THREADS ?= "4"
PARALLEL_MAKE ?= "-j 4"
layer.conf → machine.conf → distro.conf → local.conf 的顺序加载。后面的会覆盖前面的变量。
2.8 Layer —— 组织的“文件夹”
Layer 是Yocto里组织Metadata的基本单位。一个Layer就是一个有特定目录结构的文件夹。
典型的Layer结构:
meta-mylayer/
├── conf/
│ ├── layer.conf # Layer自身的配置
│ └── machine/
│ └── myboard.conf # 机器配置
├── recipes-example/
│ └── hello/
│ ├── hello_1.0.bb # Recipe
│ └── files/
│ └── hello.c # 源码文件
├── classes/
│ └── my-custom.bbclass # 自定义Class
└── README
为什么要用Layer?
- 模块化:BSP相关的东西放
meta-my-bsp,应用层的东西放meta-my-app。 - 可复用:换项目时,直接把Layer搬过去就行。
- 优先级控制:通过
bblayers.conf里的Layer顺序,控制谁覆盖谁。
1. 底层:
meta(Poky官方)、meta-yocto-bsp(官方BSP)。2. 中间层:
meta-my-bsp(板级支持包)、meta-my-vendor(芯片厂商提供)。3. 应用层:
meta-my-product(产品特有配置和软件)。这样分层,后期维护起来特别清爽。
2.9 小结:它们是怎么协同工作的?
咱们来捋一遍整个流程:
- 你执行
bitbake core-image-minimal。 - BitBake 读取
bblayers.conf,知道要加载哪些Layer。 - BitBake 解析每个Layer里的
.conf文件,设置全局变量(比如MACHINE、DISTRO)。 - BitBake 找到
core-image-minimal这个Recipe,解析它。 - Recipe 通过
inherit引入Class,获得通用的构建函数。 - BitBake 构建依赖树,按顺序执行
do_fetch、do_patch、do_compile、do_install、do_package等任务。 - 最终生成镜像文件、IPK包或SDK。
你看,从Poky到BitBake,再到Metadata、Layer、Recipe、Class、Configuration,每个概念都有自己的位置和职责。理解了它们,你就掌握了Yocto的“语法”。