2. Yocto基础回顾
在开始编写自定义 Layer 之前,必须先把 Yocto 项目里几个高频名词的“身份”和“关系”理清楚。很多初学者会把 BitBake、OpenEmbedded、Poky 混为一谈,结果在写 layer.conf、.bb、.bbclass 时不知道文件该放哪一层、由谁解析、被谁继承。本节用一张层次关系图,把构建系统、元数据、配方、类、配置文件的职责与依赖关系一次讲透。
一、核心原理:四个概念不是并列,而是分层
Yocto 项目本质上是一套“构建框架 + 元数据集合”。其中:
- BitBake:任务执行引擎,负责解析元数据、计算依赖、调度任务。它只认语法,不关心具体是哪个发行版。
- OpenEmbedded:元数据规范与配方集合,定义了
.bb、.bbclass、.inc、.conf的写法与继承机制,是“内容标准”。 - Poky:一个参考发行版,把 BitBake、OpenEmbedded-Core(oe-core)以及若干默认配置打包在一起,是官方推荐的入门起点。
- 元数据(Metadata):所有配置、配方、类、追加文件的总称,是 BitBake 的输入。
它们的关系可以概括为:BitBake 是引擎,OpenEmbedded 是规范,Poky 是参考实现,元数据是燃料。自定义 Layer 的本质,就是向这套元数据体系中追加自己的配方、类和配置,而不修改上游内容。
二、方法流程:一次构建中元数据如何被消费
理解层次之后,再看一次典型构建的解析顺序,就能明白自定义 Layer 应该“挂”在哪里:
- BitBake 启动,读取
conf/bblayers.conf,得到所有参与构建的 Layer 路径。 - 依次加载每个 Layer 的
conf/layer.conf,把该 Layer 的recipes-*目录加入BBPATH与BBFILES。 - 读取
local.conf,确定MACHINE、DISTRO、并行度、下载目录等全局变量。 - 根据目标配方名,在
BBFILES中匹配.bb与同名.bbappend,按 Layer 优先级合并变量。 - 解析配方中的
inherit,加载对应.bbclass,把类中的任务与变量注入当前配方。 - 计算任务依赖图,按
do_fetch → do_unpack → do_patch → do_configure → do_compile → do_install → do_package顺序执行。
layer.conf、配方和类,通过 bblayers.conf 注册即可参与构建。
三、案例/场景:给一个自定义 Layer 挂上配方与类
假设我们要新增 meta-myapp Layer,提供一个 hello-custom 配方,并复用自定义类 mybuild.bbclass。目录结构如下:
meta-myapp/
├── conf/
│ └── layer.conf
├── classes/
│ └── mybuild.bbclass
└── recipes-apps/
└── hello-custom/
├── hello-custom_1.0.bb
└── files/
└── hello.c
layer.conf 负责声明 Layer 身份与搜索路径:
BBPATH .= ":${LAYERDIR}"
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "myapp"
BBFILE_PATTERN_myapp = "^${LAYERDIR}/"
BBFILE_PRIORITY_myapp = "10"
LAYERVERSION_myapp = "1"
配方中通过 inherit 使用类,通过 require 复用 .inc:
SUMMARY = "Custom hello application"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://hello.c"
inherit mybuild
do_compile() {
${CC} ${CFLAGS} ${LDFLAGS} ${WORKDIR}/hello.c -o hello
}
do_install() {
install -d ${D}${bindir}
install -m 0755 hello ${D}${bindir}/hello
}
最后在 build/conf/bblayers.conf 中注册:
BBLAYERS ?= " \
/opt/poky/meta \
/opt/poky/meta-poky \
/opt/poky/meta-yocto-bsp \
${TOPDIR}/../meta-myapp \
"
执行 bitbake hello-custom 后,BitBake 会先加载 meta-myapp/conf/layer.conf,再匹配到配方,继承 mybuild.bbclass,最终完成编译与打包。
四、误区与复盘:常见混淆点对照
| 概念 | 本质 | 常见误区 | 正确理解 |
|---|---|---|---|
| BitBake | 任务调度引擎 | 以为它包含配方内容 | 它只解析和执行,配方来自元数据 |
| OpenEmbedded | 元数据规范与配方集合 | 与 Poky 混为一谈 | oe-core 是 Poky 的组成部分之一 |
| Poky | 参考发行版 | 认为必须用 Poky 才能构建 | 可用其他 distro 配置替换 meta-poky |
| .bb / .bbappend | 配方与追加 | 在 .bbappend 中重复定义全部变量 | 只写差异部分,保持与上游解耦 |
| .bbclass | 可复用构建逻辑 | 把类当普通配置文件 | 通过 inherit 注入任务与变量 |
| layer.conf | Layer 注册与路径声明 | 忘记设置 BBFILE_PRIORITY | 优先级决定同名配方覆盖顺序 |
bblayers.conf 是否注册、layer.conf 的 BBFILES 是否匹配到配方、BBFILE_PRIORITY 是否被其他 Layer 覆盖。多数“配方找不到”或“变量不生效”都源于这三步。
把 BitBake、OpenEmbedded、Poky、元数据、配方、类、配置文件放回同一张层次图里,就能看清:引擎负责执行,规范负责约束,Poky 负责示范,元数据负责描述,而自定义 Layer 负责扩展。后续编写 Layer 时,所有文件都应落在“元数据层”的正确位置,并通过 layer.conf 与 bblayers.conf 接入构建体系。