4、首次构建:初始化构建环境、配置local.conf、运行bitbake、构建过程全解析

好,咱们现在开始动手。说实话,很多初学者在Yocto面前容易懵——命令那么多,配置那么复杂,到底先干嘛后干嘛?别急,我带你一步步走一遍。这一章,咱们就完成第一次构建。

4.1 初始化构建环境

先说说环境初始化。这一步说白了就是告诉系统:我要在哪个目录里干活。

我个人习惯把构建目录放在源码树外面,这样方便管理。但Yocto默认的做法是在源码树内部创建build目录。咱们先按默认来。

cd poky
source oe-init-build-env build

执行完这条命令,你会看到终端提示符变了,前面多了个 build 字样。这说明你已经进入了构建环境。

小提示: 我建议你每次打开新终端时都执行一下 source oe-init-build-env。不执行的话,bitbake命令是找不到的。我在项目里吃过这个亏,折腾了半天才发现是环境没加载。

这个脚本做了几件事:

  • 设置 TEMPLATECONFOEROOT 等环境变量
  • 创建 build/conf 目录(如果不存在)
  • 从模板复制 local.confbblayers.conf
  • bitbakescripts 目录加入 PATH

嗯,这里要注意:每次构建前都要先source一下。这不是一次性的操作。

4.2 配置local.conf

初始化完成后,你会看到 build/conf/local.conf 这个文件。这是Yocto构建的核心配置文件。说白了,你告诉系统:我要编译什么、给谁用、怎么编译。

我第一次打开这个文件时,里面密密麻麻的注释,看得我头大。但其实你只需要关注几个关键参数:

参数 说明 我的建议值
MACHINE 目标硬件平台 qemux86-64(初学者首选)
DL_DIR 源码下载缓存目录 建议设到共享目录,避免重复下载
SSTATE_DIR 共享状态缓存目录 同样建议共享,加速后续构建
BB_NUMBER_THREADS 并行任务数 CPU核心数 + 1 或 2
PARALLEL_MAKE make并行数 CPU核心数

举个例子,我常用的配置是这样的:

MACHINE = "qemux86-64"
DL_DIR = "/opt/yocto/downloads"
SSTATE_DIR = "/opt/yocto/sstate-cache"
BB_NUMBER_THREADS = "8"
PARALLEL_MAKE = "-j 8"
注意: 我曾经把 BB_NUMBER_THREADS 设成32,结果服务器直接卡死。别贪心,根据你的机器配置来。4核8线程的机器,设成6就差不多了。

还有一个参数我特别想提——PACKAGE_CLASSES。默认是 package_rpm,但我个人习惯改成 package_ipk。为什么?因为ipk包体积小,安装快,调试时方便。当然,这纯属个人偏好。

4.3 运行bitbake

配置好了,咱们开始构建。最简单的命令就是:

bitbake core-image-minimal

core-image-minimal 是最小化的系统镜像。它只包含最基本的组件——内核、根文件系统、busybox。说白了,就是能启动的最小Linux系统。

我第一次跑这个命令时,等了将近两个小时。你想想看,Yocto要从头编译gcc、glibc、内核……所有东西。所以第一次构建特别慢。

运行过程中,你会看到类似这样的输出:

Loading cache: 100% |################################| Time: 0:00:01
Loaded 0 entries from dependency cache.
Parsing recipes: 100% |##############################| Time: 0:00:15
Parsing of 1234 .bb files complete. 0 cached, 1234 parsed.
NOTE: Resolving any missing task queue dependencies
NOTE: Preparing RunQueue
NOTE: Executing RunQueue
Currently  1 running tasks (1 of 1234):
0: gcc-cross-x86_64-11.3.0-r0 do_fetch - 0s

看到 do_fetch 了吗?这是第一步——下载源码。Yocto会从网上拉取所有需要的源码包。如果网络不好,这一步可能会卡很久。

避坑指南: 我曾经在客户现场构建,网络被防火墙限制了。结果 do_fetch 一直失败。后来我提前把所有源码包下载好,放到 DL_DIR 里,才解决了问题。如果你也遇到类似情况,可以试试这个办法。

4.4 构建过程全解析

Yocto的构建过程,说白了就是一套流水线。每个软件包(recipe)都要经过几个阶段:

  1. do_fetch:下载源码
  2. do_unpack:解压源码
  3. do_patch:打补丁
  4. do_configure:配置(比如运行./configure)
  5. do_compile:编译
  6. do_install:安装到临时目录
  7. do_package:打包成ipk/rpm/deb
  8. do_rootfs:生成根文件系统
  9. do_image:生成最终镜像

你可能会问:为什么Yocto要分这么多步骤?

嗯,这样设计的好处是——每个步骤都可以独立缓存。比如你改了配置,只需要重新执行 do_configure 之后的步骤,前面的 do_fetchdo_unpack 直接用缓存。这就是Yocto的增量构建机制。

我记得有一次,我只改了一个内核配置选项。重新构建时,Yocto只花了3分钟就完成了。因为它跳过了所有不需要重新执行的步骤。这就是分步构建的魅力。

如果你想看某个recipe的详细构建过程,可以用:

bitbake -c listtasks core-image-minimal

这条命令会列出所有可执行的任务。如果你想单独执行某个任务,比如只下载源码:

bitbake -c fetch core-image-minimal
核心要点: 构建过程中,tmp/work 目录是核心。每个recipe的构建产物都在这里。如果你遇到构建失败,第一件事就是去 tmp/work/<recipe>/<version>/temp/log.do_* 看日志。这是我最常用的调试方法。

4.5 构建完成后的产物

构建成功后,你会看到类似这样的输出:

NOTE: Tasks Summary: Attempted 1234 tasks of which 0 didn't need to be rerun and all succeeded.

然后去 build/tmp/deploy/images/qemux86-64/ 目录下,你会看到:

  • core-image-minimal-qemux86-64.rootfs.ext4 —— 根文件系统镜像
  • core-image-minimal-qemux86-64.rootfs.tar.bz2 —— 根文件系统压缩包
  • bzImage —— 内核镜像
  • modules-*.tgz —— 内核模块

用QEMU启动试试:

runqemu qemux86-64

看到登录提示符了吗?默认用户名是 root,没有密码。恭喜你,你的第一个Yocto系统跑起来了!

说实话,第一次看到自己构建的系统启动时,我还是挺有成就感的。虽然只是一个最小系统,但每一步都是自己亲手配置的。这种感觉,你试试就知道了。

下一章,咱们聊聊如何定制自己的镜像——往里面加软件包、改启动脚本、调内核参数。准备好了吗?