原文:Yocto Project 5.0.13《Writing a New Recipe》,合并同版 Layers 与 SDK Toolchain 相关内容。原页未署个人作者;维护方为 Yocto Project。译编:未完纪。
本文范围:按照候选任务边界,完整展开“自建 layer、准备本地 C 文件、编写配方、构建、安装与拆包检查”。新配方源章已完整阅读;本文是按任务译编,不是整章逐段翻译,不展开 LZ4、GNU Hello、Meson、服务安装和预编译二进制等其他示例。补充命令及调整均在文中注明。

配方负责什么
配方是扩展名为 .bb 的文件,也是 Yocto Project 环境的基本组成部分。OpenEmbedded 构建系统构建的每个软件组件,都需要一份配方来定义。写新配方通常是反复构建、发现缺失信息、再补齐信息的过程。
你可以从零开始,也可以用 devtool add 创建配方及适合开发的环境,用 recipetool create 根据源文件生成基础配方,或寻找现有的类似配方。前两者采用相同的自动生成逻辑,但 devtool add 还为修改源码和补丁准备开发环境。现有配方可以在 OpenEmbedded Layer Index 查找;使用不熟悉的配方时,要检查是否带入无关功能或遗漏必要设置。本例只有一个本地 C 文件,直接写一份小配方即可。
1. 创建并启用自己的 layer
layer 用于将不同类型的定制分开。创建之前,先检查是否已有满足需求的 layer。自建目录通常使用 meta- 前缀,并应置于独立位置,例如官方 poky 仓库旁。
译注:以下命令串起同版官方步骤。假设已经准备好 Yocto Project 5.0.13 / Scarthgap 的 Poky 和受支持的 Linux 构建环境,当前位于 Poky 根目录。在普通构建用户的 shell 中载入环境,默认会进入 poky/build:
source oe-init-build-env
bitbake-layers create-layer ../../meta-localhello
bitbake-layers add-layer ../../meta-localhello
bitbake-layers show-layers
create-layer 根据当前源码树模板创建基础 layer,默认优先级为 6,包含 conf/layer.conf、示例配方、COPYING.MIT 和 README。需要改变优先级或示例名时可分别使用 --priority、--example-recipe-name,详细语法见 bitbake-layers create-layer --help。模板假定 layer 本身使用 MIT,不能据此推定其中每份软件源码的许可。
add-layer 将 layer 加入构建目录的 conf/bblayers.conf,show-layers 可核对实际启用结果。构建系统按 BBLAYERS 顺序读取每个 layer 的配置。若你使用了自定义构建目录,上面的相对路径必须随之调整。
版本修正:5.0.13 的 layer 章节仍保留了 LAYERSERIES_COMPAT_yoctobsp = "dunfell" 的历史示意配置。本流程使用 Scarthgap 环境的工具生成配置,再核对兼容声明,避免照搬旧示例。兼容声明不是兼容性测试结果,也不应仅为了绕过错误而随意改写。
配方的位置必须能被 layer.conf 中的 BBFILES 匹配。典型写法是:
BBFILES += "${LAYERDIR}/recipes-*/*/*.bb \
${LAYERDIR}/recipes-*/*/*.bbappend"
BBPATH 用于寻找类、配置和被 include / require 引入的文件。BBFILE_COLLECTIONS 标识 layer,BBFILE_PATTERN 定义匹配目录,BBFILE_PRIORITY 处理同名配方优先级,LAYERDEPENDS 声明其他 layer 依赖。自建类与配置文件宜使用不易冲突的名称。
2. 准备本地 C 源文件
在构建目录中创建本例目录:
mkdir -p ../../meta-localhello/recipes-examples/helloworld/files
meta-localhello/
├── conf/
│ └── layer.conf
└── recipes-examples/
└── helloworld/
├── helloworld_1.0.bb
└── files/
└── helloworld.c
配方采用 basename_version.bb 命名,因此本例基名为 helloworld,版本为 1.0。使用小写;除非确实表示对应用途,不要把 -native、-cross、-initial 或 -dev 等保留后缀随意用作名称的一部分。
新配方章节没有提供 helloworld.c 内容。这里补入同版 SDK 章节的完整 hello.c 示例,将文件名统一为 helloworld.c,只整理缩进,保留原函数写法与输出:
#include <stdio.h>
int main()
{
printf("Hello World!\n");
return 0;
}
许可证边界:该片段作为官方文档示例引用。文档中的程序并不自动给读者自己的 C 源码授予 MIT 许可。下节原配方的 LICENSE 和 LIC_FILES_CHKSUM 是 MIT 示例;实际打包前,必须让这两项与所用源代码的真实许可证及声明相符。文章转载授权、文档许可和软件源码许可应分别处理。
3. 写出完整单文件配方
以下保留官方示例的完整字段和任务,保存文件名为 helloworld_1.0.bb。MIT 字段的适用条件见上文:
SUMMARY = "Simple helloworld application"
SECTION = "examples"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://helloworld.c"
S = "${WORKDIR}"
do_compile() {
${CC} ${LDFLAGS} helloworld.c -o helloworld
}
do_install() {
install -d ${D}${bindir}
install -m 0755 helloworld ${D}${bindir}
}
SRC_URI 指定取源位置。file:// 表示本地文件,按 FILESPATH 查找;常见目录包括配方旁的 ${BP}、${BPN} 与 files。本例使用 files。没有压缩包内部的顶层源码目录,所以在 5.0.13 中将 S 设为 ${WORKDIR}。迁移其他 Yocto 版本前应重新核对该行为。
do_compile 使用构建系统提供的交叉编译器 ${CC} 和链接选项 ${LDFLAGS},不要替换成主机的普通 gcc。do_install 先建目录,再以 0755 权限安装程序。${D} 是安装暂存根目录,${bindir} 是目标可执行文件目录;这不是直接把文件写入构建主机的 /usr/bin。
译注:可选的编译任务调整。原例没有显式传入 CPPFLAGS 与 CFLAGS。为保留构建环境的预处理、优化和加固标志,可将编译任务替换为下面的版本。差异是增加这两个变量,并把链接标志放在源文件之后;该改动只经过静态审阅:
do_compile() {
${CC} ${CPPFLAGS} ${CFLAGS} helloworld.c ${LDFLAGS} -o helloworld
}
不要把 ${CC} 整体加成一个 shell 引号参数,因为它可能包含编译器及多个参数。若以后添加来自外部的任意值,则必须按实际用途验证和引用,避免把不可信内容拼接成 shell 命令。
4. 构建与定位工作目录
在已载入环境的构建目录执行:
bitbake helloworld
命令只接受这里所需的配方基名。构建系统为每份配方建立工作目录,保存源文件、任务日志、中间文件和打包结果。路径随架构、版本和上下文变化,应查询实际值:
bitbake -e helloworld | grep '^WORKDIR='
用输出定位工作目录,检查以下内容:
temp/log.do_fetch:源文件是否找到,配方引用与实际文件名是否一致。temp/log.do_compile:编译器、参数及错误,是否错误地使用主机的/usr/include或/usr/lib。temp/log.do_install与image:安装位置与权限是否符合预期。packages-split:文件最后进入哪个包,是否缺失、重复或被放错位置。
原文任务日志采用 log.taskname 命名,例如 log.do_configure、log.do_fetch、log.do_compile。构建没有报错并不等于软件包内容正确。
如果软件需要其他配方提供的库或头文件,应使用 DEPENDS 声明构建依赖。运行时依赖是按软件包设置的,主包写作 RDEPENDS:${PN}。部分共享库依赖会在打包阶段自动推导,仍不能省略准确的构建依赖。如果遇到找不到头文件或库,先检查依赖和 sysroot 路径;并行构建偶发失败则要检查构建规则的依赖关系,而不是把偶然成功当成解决。
5. 检查安装与拆包
do_install 把源目录、构建目录和工作目录的文件复制到 ${D},形成目标设备上的目录结构。手动安装先使用 install -d 建目录,再复制文件。若需要修改已安装文件里的路径,应复制后再修改目标副本,保证任务能够重新执行。
配方不应直接写入 sysroot。应先安装到 ${D} 的标准位置,再由 do_populate_sysroot 按目录规则填充 sysroot。构建系统通过清单跟踪这些文件,便于配方更改或移除后清理旧内容。
do_package 将产物拆成主程序、调试信息、开发文件等逻辑组件。原文列出默认的 helloworld、helloworld-dbg 和 helloworld-dev 包名;实际是否输出空包或非空包取决于规则与内容,必须检查 packages-split。即使只生成一个二进制,也可能需要单独的调试包。
insane 类参与打包 QA,发现运行时常见问题。出现文件归属问题时,检查 PACKAGES、FILES 与 do_install,不要仅关闭 QA 来掩盖问题。编译出的 C 二进制与目标架构有关,不应因为代码简单就使用 inherit allarch。
6. 在目标环境验证
配方的最后一步是确认程序可以正确运行。按现有镜像定制方式将构建出的软件包加入镜像,在目标设备或对应仿真环境中执行 helloworld。如果目标架构与构建主机不同,不能直接在主机执行该交叉编译产物。
示例源代码的预期输出是一行 Hello World!。这只是从源码确定的预期行为;本文没有运行 BitBake、生成镜像或启动目标设备。读者实际运行前仍应落实源代码许可、目标机配置和版本匹配。
来源、许可与审核范围
本文依据 Yocto Project 5.0.13 新配方章节的本地取源、命名、依赖、编译、安装、拆包、测试及单 C 文件示例,合并 layer 创建与启用和 SDK C 示例。其他构建系统与高级配方场景可沿原文继续阅读。
Yocto Project 文档按 CC BY-SA 2.0 UK: England & Wales 提供;本译编保留来源,文档译编部分沿用该许可。软件示例实际许可应另行核对。2026-10-05 的改动包括中文译编、统一源文件名、用当前环境生成 layer 配置、补充执行顺序和静态审核,并单列编译标志调整。没有执行原文或修订后的构建命令。












暂无评论内容