4、第一个配方:创建简单的Hello World配方、理解SRC_URI和do_compile

好,咱们终于要动手写第一个配方了。

说实话,我当年刚接触Yocto时,最头疼的就是不知道一个配方到底长什么样。文档里讲了一堆变量、任务、继承关系,但就是没人给我一个能跑起来的例子。所以这一章,咱们就直接从零开始,写一个最简单的Hello World配方。

4.1 配方文件长什么样?

一个Yocto配方,本质上就是一个.bb文件。它告诉BitBake三件事:

  • 从哪里下载源码(SRC_URI)
  • 怎么编译(do_compile)
  • 怎么安装(do_install)

嗯,其实就这三步。你想想看,这不就跟咱们平时手动编译软件一样吗?下载源码包、解压、make、make install。Yocto只是把这个过程自动化了。

核心要点:配方 = 元数据 + 任务函数。元数据描述「是什么」,任务函数描述「怎么做」。

4.2 创建我们的第一个配方

先建个目录。我个人习惯把自定义配方放在meta-custom/recipes-example/hello/下面。这样一眼就能看出来是实验用的例子。

mkdir -p meta-custom/recipes-example/hello
cd meta-custom/recipes-example/hello
touch hello_1.0.bb

文件名hello_1.0.bb,1.0是版本号。Yocto会从文件名里自动解析出包名和版本,所以命名要规范。

打开这个文件,写入以下内容:

SUMMARY = "A simple Hello World program"
DESCRIPTION = "This recipe demonstrates the minimal Yocto recipe structure"
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}
}

别急着复制粘贴,咱们一行一行拆开看。

4.3 理解SRC_URI:源码从哪来?

SRC_URI是配方的灵魂。它告诉BitBake:「嘿,去这里拿源码!」

常见的SRC_URI写法有几种:

协议 示例 说明
本地文件 file://hello.c 从配方同目录或FILESPATH中找
HTTP下载 http://example.com/hello.tar.gz 自动下载并解压
Git仓库 git://github.com/xxx/hello.git;branch=main 克隆Git仓库

咱们这里用的是file://hello.c,意思是「在配方文件旁边找hello.c」。所以你还得创建一个hello.c文件放在同一个目录下。

小技巧:如果你用file://协议,Yocto默认会在${WORKDIR}里找到这些文件。但前提是它们必须放在配方的「files」子目录里,或者跟配方同级。我刚开始就栽在这个坑里——文件放错位置,编译时死活找不到。

创建hello.c:

#include <stdio.h>

int main() {
    printf("Hello, Yocto!\n");
    return 0;
}

简单吧?就一个打印语句。但别小看它,这个例子能帮你理解整个Yocto的构建流程。

4.4 理解do_compile:编译到底干了啥?

咱们再看do_compile()函数:

do_compile() {
    ${CC} ${CFLAGS} ${LDFLAGS} hello.c -o hello
}

这里用了几个变量:

  • ${CC}:交叉编译器,比如arm-poky-linux-gnueabi-gcc
  • ${CFLAGS}:编译选项,包含目标架构的优化参数
  • ${LDFLAGS}:链接选项,确保链接正确的运行时库

说白了,Yocto帮你封装好了交叉编译环境。你不需要手动指定-march=armv7-a之类的参数,Yocto会根据你选的机器(MACHINE)自动配置。

注意:千万不要在do_compile里写死gcc!要用${CC}。我曾经见过有人直接写gcc hello.c -o hello,结果编译出来的是x86的二进制,放到ARM板上直接Segmentation Fault。血的教训。

4.5 知识体系图

下面这张图展示了本章的核心逻辑:一个配方从源码到安装的完整流程。

配方构建流程 SRC_URI 获取源码 do_compile 编译源码 do_install 安装到目标 SRC_URI 常见形式 • file:// 本地文件 • http:// 网络下载 • git:// Git仓库 • ftp:// FTP服务器 do_compile 关键变量 • ${CC} 交叉编译器 • ${CFLAGS} 编译选项 • ${LDFLAGS} 链接选项 • ${WORKDIR} 工作目录 do_install 关键变量 • ${D} 目标根目录 • ${bindir} 二进制目录 • install -d 创建目录 • install -m 设置权限 配方 = SRC_URI(获取) + do_compile(编译) + do_install(安装) 每个阶段都可以通过变量和函数进行定制

4.6 避坑指南:我踩过的三个坑

写第一个配方时,有几个地方特别容易出错。我当年都踩过,分享给你:

  1. 文件路径问题:file://hello.c这个文件必须放在配方同目录,或者files/子目录下。我第一次写的时候把hello.c放到了meta-custom/根目录,结果BitBake报错说找不到文件。
  2. 权限问题:do_install里一定要用install -m 0755设置可执行权限。我刚开始直接用了cp命令,结果编译出来的二进制没有执行权限,在目标板上跑不了。
  3. 变量拼写:${CC}、${CFLAGS}这些变量名是大小写敏感的。我见过有人写成${cc},结果编译时用的还是宿主机的gcc,交叉编译完全没生效。

记住:Yocto的配方不是普通的Makefile。它运行在交叉编译环境下,所有路径、编译器、库都是为目标板定制的。写配方时,时刻问自己:「这个变量在目标板上会展开成什么?」

4.7 验证你的配方

配方写好了,怎么验证?用bitbake命令:

bitbake hello

如果一切顺利,你会看到BitBake依次执行do_fetch、do_unpack、do_compile、do_install、do_package等任务。最后在tmp/deploy/目录下生成hello的IPK或RPM包。

你也可以单独执行某个任务:

bitbake hello -c compile   # 只编译
bitbake hello -c install   # 只安装
bitbake hello -c clean     # 清理

这个调试技巧很实用。我排查问题时,经常只跑-c compile,省得每次都从头开始。

好了,第一个配方就到这里。你亲手写了一个完整的Yocto配方,理解了SRC_URI怎么指定源码,do_compile怎么编译。这些基础打牢了,后面学复杂的配方就会轻松很多。

额外提示:如果你在编译时遇到ERROR: Nothing PROVIDES 'hello',八成是配方文件没被解析到。检查一下bblayers.conf里有没有添加meta-custom层。这个坑我见过不下十次了。

可可精品资料库