3、理解Yocto目录结构:Poky目录解析、meta层结构、conf目录、recipes与bb文件、layer.conf的作用
说实话,我刚接触Yocto那会儿,第一反应就是——这目录结构也太复杂了吧?
Poky、meta层、conf、recipes、bb文件……一堆名词砸过来,很容易让人懵掉。但你别怕,这些东西说白了就是一套「搭积木」的规则。你搞懂了目录结构,就等于拿到了Yocto的地图。
今天我就带你把这地图上的关键节点,一个一个捋清楚。
3.1 Poky目录解析
Poky是什么?它是Yocto项目的参考构建系统。你可以把它理解成一个「样板间」——里面啥都有,但你要自己动手改。
我习惯把Poky目录比作一个工具箱。你打开它,会看到这些核心目录:
- bitbake/ —— 构建引擎。Yocto的灵魂,所有构建任务都靠它调度。
- meta/ —— 核心元数据层。包含最基础的recipes、类和配置。
- meta-poky/ —— Poky的发行版配置层。定义了默认的发行版策略。
- meta-yocto-bsp/ —— 参考板级支持包。给几个常见硬件平台用的。
- scripts/ —— 辅助脚本。比如检查环境、生成镜像的工具。
- build/ —— 构建输出目录。你执行bitbake后,所有产物都在这里。
嗯,这里要注意:build/目录默认是不存在的。你需要先运行oe-init-build-env脚本,它才会被创建出来。我第一次用的时候找了半天build目录,结果发现是自己忘了source环境……
3.2 meta层结构
meta层,说白了就是「一摞菜谱」。每个meta层都包含一组recipes、配置文件和类文件。Yocto的层机制,让你可以像搭积木一样组合功能。
一个典型的meta层长这样:
meta-mylayer/
├── conf/
│ ├── layer.conf
│ └── machine/
│ └── mymachine.conf
├── recipes-example/
│ └── hello/
│ ├── hello_1.0.bb
│ └── files/
│ └── hello.c
├── classes/
│ └── myclass.bbclass
└── COPYING.MIT
你看,结构其实很清晰:
- conf/ —— 层配置和机器配置
- recipes-xxx/ —— 按功能分类的菜谱目录
- classes/ —— 可复用的构建类
- files/ —— 补丁、源码等附加文件
我在项目中遇到过一个问题:两个meta层都定义了同一个recipe,结果构建时老是报冲突。后来才发现,Yocto是按照BBLAYERS中层的顺序来解析的,后面的层会覆盖前面的。所以层的顺序很重要,千万别乱排。
3.3 conf目录
conf目录是Yocto的「控制面板」。你所有的构建决策,几乎都在这里配置。
核心文件就这几个:
| 文件 | 作用 | 我常用的配置 |
|---|---|---|
local.conf |
本地构建配置,每个开发者自己改 | MACHINE、DL_DIR、SSTATE_DIR |
bblayers.conf |
声明要使用的meta层列表 | BBLAYERS += "path/to/mylayer" |
templateconf.cfg |
模板配置,很少动 | 默认就好 |
举个例子,local.conf里我经常这样配:
MACHINE = "qemuarm64"
DL_DIR = "/home/shared/downloads"
SSTATE_DIR = "/home/shared/sstate-cache"
PACKAGE_CLASSES = "package_rpm"
你想想看,DL_DIR和SSTATE_DIR如果放在网络共享路径上,团队里每个人都能复用下载好的源码和编译缓存。我第一次用Yocto时没配这个,结果每次clean后都要重新下载,那叫一个慢啊……
3.4 recipes与bb文件
recipes是Yocto的核心。每个.bb文件就是一个recipe,它告诉BitBake:你要从哪里下载源码、怎么编译、怎么安装。
一个简单的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里定义了:
- SUMMARY —— 一句话描述
- LICENSE —— 许可证,Yocto强制要求
- SRC_URI —— 源码来源,可以是本地文件、git仓库、tarball
- do_compile —— 编译步骤,你可以完全自定义
- do_install —— 安装步骤,把产物放到目标目录
我个人习惯把SRC_URI写成git://形式,这样能精确锁定commit。比如:
SRC_URI = "git://github.com/example/myapp.git;branch=main;protocol=https"
SRCREV = "a1b2c3d4e5f6..."
为什么推荐用git?因为你可以随时回退版本,而且SRCREV能保证构建的可重复性。我曾经用tarball方式,结果上游把旧版本删了,构建直接挂掉……从那以后,我尽量用git。
3.5 layer.conf的作用
每个meta层都必须有一个conf/layer.conf文件。它就像层的「身份证」,告诉BitBake这个层叫什么、包含哪些内容。
一个典型的layer.conf:
BBPATH .= ":${LAYERDIR}"
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"
BBFILE_COLLECTIONS += "mylayer"
BBFILE_PATTERN_mylayer = "^${LAYERDIR}/"
BBFILE_PRIORITY_mylayer = "6"
LAYERDEPENDS_mylayer = "core"
LAYERSERIES_COMPAT_mylayer = "kirkstone"
这里的关键变量:
- BBPATH —— 把层目录加入搜索路径
- BBFILES —— 声明哪些文件是recipe
- BBFILE_COLLECTIONS —— 注册层名称
- BBFILE_PATTERN —— 匹配该层下的文件
- BBFILE_PRIORITY —— 优先级,数字越大越优先
- LAYERDEPENDS —— 依赖的其他层
- LAYERSERIES_COMPAT —— 兼容的Yocto版本
嗯,这里有个坑:BBFILE_PRIORITY的默认值是5。如果你有两个层定义了同一个recipe,优先级高的会覆盖优先级低的。我遇到过一个问题:一个第三方层优先级设成了10,结果把我的自定义recipe全盖了,查了半天才发现是优先级搞的鬼。
好了,目录结构这块就聊到这儿。你把这些搞懂了,Yocto的骨架就搭起来了。下一章,我们聊聊怎么用BitBake跑第一个构建任务——到时候你会发现,理解了目录结构,跑起来顺手多了。