系列第 6 篇|从「使用 Linux」转向「制作 Linux」阅读顺序:为什么要构建 → Yocto 是什么 → 一张总图 → OE-Core 与 Poky → 源码目录 → Layer → Recipe → 构建时如何协作
到目前为止,我们做了两件事:
从本篇起,问题换成:
我不只想「使用」别人做好的 Linux,还想按自己的需求裁剪并生成一套 Linux 系统镜像。
本篇只建立概念,不要求你马上敲完整构建命令(那是第 7~8 篇)。建议按上面副标题的顺序读:先有总图,再分清 OE-Core 与 Poky,再进目录和文件,最后看它们在构建时怎么串起来。
完整发行版(例如桌面版 Ubuntu)适合日常开发:软件多、装包方便。但做产品、做演示镜像、或要体积与行为都可控时,常会碰到:
这时需要的是「按菜谱做饭」的构建系统,而不是永远从应用商店现吃。Yocto 就是工业界很常用的一种。
最常见的误会:
「Yocto 是不是和 Ubuntu 一样,也是一个 Linux 发行版?」
不是。更准确的说法是:
Yocto Project 是一套用来构建定制 Linux 系统的开源工程与工具 / 元数据生态。它帮你「做出发行版一样的东西」,但它本身不是你最终长期登录使用的那个 Ubuntu。
和常见方案怎么选:
结合第 5 篇记一句:
构建成功后,你通常会得到:内核与模块、rootfs、可写 U 盘 / 硬盘的镜像(如 wic、hddimg),有时还有 SDK。
先别急着看文件夹。用「厨房」把五个词一次记牢:
BitBake = 厨师(按菜谱一步步执行)Layer = 抽屉(一组相关菜谱和配置)Recipe(.bb) = 某一道菜的做法(某个软件怎么下载、编译、安装)Image = 这盒套餐叫什么、默认摆哪些菜(最终整套系统)Machine = 这锅饭为谁做(虚机 / 真机 PC 等)再补两个后面会见到的词:
构建时的大致顺序(细节第 7 篇再拆):
打开哪些抽屉(Layer) → 读清为谁做、加什么菜(Machine / local.conf) → 按每道菜的做法做菜(Recipe) → 按套餐装箱(Image) → 端到出餐口(deploy 目录里的镜像文件)入门最少记住三句:
有了这张图,下面先分清两个常被混为一谈的名字,再打开 clone 下来的目录。
clone 仓库时最常见的误会:
「Poky、Yocto、OpenEmbedded 是不是同一个东西?」
不是。四个名字叠在一起,职责不同:
Yocto Project = 整个工程与社区(发布、测试、文档、兼容性)OpenEmbedded = 构建系统这一套工作流与元数据生态OpenEmbedded-Core = 核心菜谱抽屉(仓库里通常叫 meta/)Poky = Yocto 官方入门组合:厨师 + 核心抽屉 + 默认口味 + 参考机型厨房里可以这样记:
poky 仓库 |
对照表:
meta/ | poky/(含 meta/ 以及其它层) | |
bitbake/ | ||
meta-poky,默认 DISTRO = "poky" | ||
meta-yocto-bsp(含本系列的 qemux86-64、genericx86-64) | ||
bitbake | ||
meta/;定制时尽量别改这里 | 动手入口 |
关系可以画成:
Poky ├── BitBake # 厨师 ├── OpenEmbedded-Core # meta/:核心菜谱 ├── meta-poky # Distro:Poky 这套口味 ├── meta-yocto-bsp # 参考机型 └── scripts / 文档 # 开工脚本与说明记三句即可:
meta/ 里。下一节打开目录时,把 meta/ 看成 OE-Core,把 meta-poky/ 看成口味策略,就不会混。
入门入口是 Poky:官方参考组合,里面已有 BitBake、OpenEmbedded-Core(meta/),以及可练手的机型配置。
git clone https://git.yoctoproject.org/poky.git -b scarthgap --depth=1cd poky(分支以官方当前推荐为准;本系列后续示例用 scarthgap。)
poky/├── bitbake/ # 厨师程序(BitBake)├── meta/ # OpenEmbedded-Core:核心软件、镜像配方、class├── meta-poky/ # Poky 这套发行策略(Distro 等)├── meta-yocto-bsp/ # 参考机型(含 qemux86-64、genericx86-64)├── meta-skeleton/ # 写自定义层时的骨架示例├── scripts/ # 辅助脚本├── documentation/ # 文档(可选读)└── oe-init-build-env # 初始化构建环境的入口bitbake/ | |
meta/ | |
meta-poky/meta-yocto-bsp/ | |
oe-init-build-env | |
meta-demo/ | 自己的抽屉 |
第一次执行 source oe-init-build-env build-xxx 后,会多出一个不属于 Poky 核心源码的工作目录。本系列约定两个:build-qemux86-64、build-genericx86-64。
build-qemux86-64/ # 示意;真机用 build-genericx86-64├── conf/│ ├── bblayers.conf # 打开哪些抽屉(Layer 列表)│ ├── local.conf # 这次为谁做、多加什么、打成什么盒│ └── templateconf.cfg # (若用模板)记录模板来源├── tmp/ # 中间产物、rootfs、日志(很大)└── cache/ # 解析缓存镜像多在:
build-*/tmp/deploy/images/<MACHINE>/BitBake 只扫描bblayers.conf 里列出的层。没列进去的目录,里面的 .bb 等于不存在。
自定义层最小形态(本系列的 meta-demo 同思路):
meta-demo/├── conf/│ └── layer.conf # 必有:本层叫什么、去哪找菜谱、优先级├── recipes-example/│ └── hello/│ ├── hello_1.0.bb # 一道菜│ └── files/hello.c└── conf/templates/ # (本系列)双 MACHINE 的 conf 模板,可选上游 meta/ 里目录更多,常见只是分类习惯:
recipes-core/recipes-* | |
classes/ | .bbclass |
conf/machine/ | qemux86-64.conf) |
conf/distro/ |
真正让 BitBake 找得到菜谱的,是 layer.conf 里的搜索路径,不是目录名字本身。
layer.conf 在干什么示意(完整文件一般由 bitbake-layers create-layer 生成):
# conf/layer.conf(示意)BBPATH .= ":${LAYERDIR}"BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \ ${LAYERDIR}/recipes-*/*/*.bbappend"BBFILE_COLLECTIONS += "demo"BBFILE_PATTERN_demo = "^${LAYERDIR}/"BBFILE_PRIORITY_demo = "6"BBFILES | .bb / .bbappend 的查找范围 |
COLLECTIONSPATTERN | |
PRIORITY |
meta # OE-Core:上游通用软件 + meta-poky # 发行策略(Poky 口味) + meta-yocto-bsp # 机型 + meta-demo # 你的定制bblayers.conf 就是「打开哪几只抽屉」的清单。厂商工程(如玄铁)再叠 meta-xxx-bsp,思路相同。
.bb 要回答四件事SRC_URI:网址、git、或本地 file://);DEPENDS / RDEPENDS 等);inherit 某个 class);IMAGE_INSTALL 选进去)。文件名惯例:名字_版本.bb,例如 hello_1.0.bb。
与第 8 篇 demo 同思路,先建立「该怎么写」的感觉:
# recipes-example/hello/hello_1.0.bbSUMMARY = "Simple hello world"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}/hello}/* files/hello.c */#include<stdio.h>intmain(void){puts("hello from yocto");return0;}SRC_URI | file:// |
S | |
do_compile | ${CC} 等由 BitBake 提供 |
do_install | ${D};${bindir} 一般是 /usr/bin |
LICENSE |
上游软件更常见的是继承现成流程,而不是手写全部任务:
inherit autotools# 或 inherit cmake / meson / ...core-image-base 也是一种 recipe,但目标不是编一个程序,而是规定:这盒系统默认装哪些包,再打成可启动镜像。
在 local.conf 里写:
IMAGE_INSTALL:append = " hello"意思是:在选定 Image 的基础上,额外把 hello 包装进 rootfs。
只有.bb不够;还要把包装进 Image(或IMAGE_INSTALL),最终系统里才会有这个命令。
meta/ 原文件换启动图、打小补丁时,在自己的层写 xxx_%.bbappend(% 匹配各版本)。第 9 篇改 psplash / GRUB 时会用到。
执行 bitbake core-image-base 时(流程细节见第 7 篇):
bblayers.conf → 打开哪些 Layerlayer.conf + 各 .bb → 收集菜谱、class、machinelocal.conf + Distro + Machine → 为谁构建、全局策略、额外装包Image 配方 → 套餐里有哪些包各软件 Recipe → fetch → unpack → patch → configure → compile → install → package组装 rootfs + 出镜像 → build-*/tmp/deploy/images/<MACHINE>/bblayers.conf | ||
local.conf | ||
layer.conf | ||
*.bb | IMAGE_INSTALL、没有 .bb → 仍然没有该软件 | |
*.bbappend | ||
IMAGE_INSTALL |
对照第 3 节总图:抽屉、菜谱、套餐、为谁做、厨师——到这里应能对上号。
国产 RISC-V 生态里,平头哥有面向玄铁的 Yocto 工程(常称 xuantie-yocto-project):在上游之上叠加 BSP 层,提供 machine 与参考镜像。读这类仓库时,优先找 meta-*、conf/machine、README 里的 bblayers / MACHINE——和本篇是同一套语言。
检索:xuantie-yocto-project、平头哥 玄铁 Yocto。
对初学者,先在自己的 PC / WSL2 上把「构建 → 启动 → 看到自己的程序」跑通,比同时学新板卡更重要:
qemux86-64(QEMU)与 genericx86-64(真机 PC) | |
runqemu;再用 U 盘做 Windows 双系统 | |
meta/ 是 OpenEmbedded-Core。build-* 是施工现场;定制放进自己的 Layer。IMAGE_INSTALL 决定包进不进最终系统。下一篇:真正使用 Yocto 时命令怎么敲、BitBake 如何推进,以及 demo 锁定哪些参数。