第一个Recipe:Hello World

说实话,每次带新人入门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出现在列表里,就说明加成功了。

我的小习惯:Layer的名字最好用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会做这些事情:

  1. 解析所有Layer,找到hello_1.0.bb
  2. 获取源码(从本地files/目录)
  3. 执行do_compile,编译hello.c
  4. 执行do_install,把hello安装到临时目录
  5. 打包成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,就能看到输出了。

核心要点:Recipe的本质就是一个自动化脚本。它告诉BitBake:源码在哪、怎么编译、怎么安装。理解了Hello World,你就理解了Yocto Recipe的80%。

知识体系图

下面这张图展示了本章的核心逻辑:

第一个Recipe:Hello World 核心流程 1. 创建Layer bitbake-layers create-layer 2. 编写Recipe hello_1.0.bb + hello.c 3. BitBake构建 bitbake hello 4. 验证输出 运行 hello 程序 5. 集成到镜像 IMAGE_INSTALL:append = " hello" 6. 构建镜像 bitbake core-image-minimal 整个流程从创建Layer开始,到最终在目标系统上运行Hello World程序 每个步骤都依赖前一步,缺一不可

这张图把整个流程串起来了。你想想看,从创建Layer到最终在目标系统上运行Hello World,每一步都是环环相扣的。我在项目里见过有人跳过验证步骤,直接把程序集成到镜像里,结果镜像刷到板子上才发现程序跑不起来——白白浪费了半天时间。

好了,第一个Recipe就到这里。记住:动手做一遍,比看十遍教程都管用。

可可精品资料库