4. 第一个Recipe
说实话,每次带新人入门Yocto,我都会让他们从Hello World开始。为什么?因为Recipe的编写逻辑、Layer的组织方式、BitBake的构建流程,全都能在这个最简单的例子里体现出来。我自己当年踩过的坑,十有八九都是因为基础没打牢。
好,咱们直接动手。
创建自定义Layer
先别急着写Recipe。你得有个自己的Layer,就像做菜前得先有个厨房。
Yocto里有个工具叫bitbake-layers,专门用来创建和管理Layer。我个人习惯用这个命令:
cd <你的poky目录>
source oe-init-build-env
bitbake-layers create-layer ../meta-mylayer
执行完,你会看到meta-mylayer目录下自动生成了这些文件:
conf/layer.conf—— Layer的配置文件COPYING.MIT—— 许可证文件README—— 说明文档
嗯,这里要注意:layer.conf里有个关键变量叫BBFILE_COLLECTIONS,它告诉BitBake这个Layer叫什么名字。我见过有人手抖写错了,结果BitBake死活不认这个Layer,排查了半天。
接下来,把Layer加到构建环境里:
bitbake-layers add-layer ../meta-mylayer
你可以用bitbake-layers show-layers确认一下。看到meta-mylayer出现在列表里,就说明加成功了。
meta-开头。这不是强制要求,但Yocto社区都这么干,你想想看,别人一看就知道这是个Layer,多省事。
编写简单的Recipe
现在来写Recipe。在meta-mylayer下创建recipes-example/hello/hello_1.0.bb:
SUMMARY = "A simple Hello World recipe"
DESCRIPTION = "This recipe demonstrates the basic structure of a Yocto recipe"
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.c源文件。在同一个目录下创建files/hello.c:
#include <stdio.h>
int main() {
printf("Hello from Yocto!\n");
return 0;
}
这里有几个关键点,我当年可是吃过亏的:
- LIC_FILES_CHKSUM —— 这个MD5值必须和实际文件一致。我建议你复制
poky/meta/files/common-licenses/MIT这个文件,然后自己算一下MD5。 - S = "${WORKDIR}" —— 告诉BitBake源码在哪个目录。如果不设,默认是
${WORKDIR}/${BPN}-${PV},那你的hello.c就找不到了。 - do_install —— 记得用
install -d创建目录,用install -m 0755设置权限。直接cp的话,权限可能会不对。
do_install,结果BitBake构建成功了,但生成的镜像里根本没有hello程序。查了半天才发现,Recipe只编译了代码,没把二进制文件装进去。
使用BitBake构建
Recipe写好了,咱们来构建它:
bitbake hello
BitBake会做这些事情:
- 解析所有Layer,找到
hello_1.0.bb - 获取源码(从本地
files/目录) - 执行
do_compile,编译hello.c - 执行
do_install,把hello安装到临时目录 - 打包成
hello-1.0-r0.ipk(或.rpm/.deb,取决于你的配置)
构建过程中,你会看到类似这样的输出:
NOTE: Executing Tasks
NOTE: Tasks Summary: Attempted 4 tasks of which 0 didn't need to be rerun and all succeeded.
看到all succeeded,心里就踏实了。
验证输出
构建完了,怎么验证?我一般用两种方法:
方法一:直接运行
find tmp/deploy -name "hello*"
# 输出类似:tmp/deploy/ipk/core2-64/hello_1.0-r0_core2-64.ipk
你可以把这个ipk包解压,或者直接用qemu启动一个镜像来测试。不过最直接的方法是用bitbake -c devshell hello进入开发环境,然后手动运行:
./hello
# 输出:Hello from Yocto!
方法二:集成到镜像里
如果你想把这个程序放到目标系统的镜像里,在local.conf里加上:
IMAGE_INSTALL:append = " hello"
然后构建镜像:
bitbake core-image-minimal
启动镜像后,运行hello,就能看到输出了。
知识体系图
下面这张图展示了本章的核心逻辑:
这张图把整个流程串起来了。你想想看,从创建Layer到最终在目标系统上运行Hello World,每一步都是环环相扣的。我在项目里见过有人跳过验证步骤,直接把程序集成到镜像里,结果镜像刷到板子上才发现程序跑不起来——白白浪费了半天时间。
好了,第一个Recipe就到这里。记住:动手做一遍,比看十遍教程都管用。