第4章:Yocto项目结构——Poky目录结构、元数据层结构

说实话,刚接触Yocto那会儿,我对着Poky目录愣了半天。这玩意儿怎么这么多文件夹?每个文件夹是干嘛的?今天我就带你把这些目录结构掰开揉碎,讲清楚。

4.1 Poky目录结构——Yocto的骨架

Poky说白了就是Yocto的一个参考发行版。你从GitHub上clone下来的poky仓库,里面包含了构建嵌入式Linux所需的核心组件。我个人习惯把Poky比作一个乐高套装——零件都在里面,怎么搭看你自己。

典型的Poky目录长这样:

poky/
├── bitbake/          # BitBake构建引擎
├── meta/             # 核心元数据层
├── meta-poky/        # Poky参考发行版配置
├── meta-yocto-bsp/   # 参考BSP支持
├── scripts/          # 辅助脚本
├── oe-init-build-env # 环境初始化脚本
└── README            # 你懂的

这里我重点说几个目录:

  • bitbake/:构建系统的核心引擎。你写的recipe最终都由它解析执行。我在项目中遇到过bitbake版本不匹配导致解析失败的情况,所以建议你保持bitbake版本和meta层一致。
  • meta/:核心元数据层。所有基础recipe、类文件、配置文件都在这里。这是Yocto的根基,千万别乱改。
  • meta-poky/:Poky发行版的默认配置。包括distro配置文件、默认的local.conf示例等。
  • meta-yocto-bsp/:参考板级支持包。提供了一些常见开发板的配置,比如qemu模拟器用的机器配置。
我的小技巧:刚上手时,别急着改meta/里的东西。先在meta-poky或自己新建的层里做配置修改。这样出了问题,回退也方便。

4.2 元数据层结构——分层设计的思想

Yocto的元数据层结构,说白了就是「分层叠加」的思想。每一层提供一部分功能,层与层之间通过优先级叠加。你想想看,这跟Linux内核的设备树叠加层是不是一个道理?

一个典型的元数据层目录结构:

meta-custom/
├── conf/
│   ├── layer.conf          # 层配置文件
│   └── machine/            # 机器配置文件
├── recipes-*/              # 各种recipe目录
├── classes/                # 自定义类文件
├── files/                  # 补丁、配置文件等
└── COPYING                 # 许可证信息

每个层必须有一个conf/layer.conf文件,告诉bitbake这个层叫什么、依赖哪些层、优先级是多少。我曾经因为忘记设置层优先级,导致两个层里的同名recipe互相覆盖,编译出来功能不对——排查了整整两天。

层优先级(BBFILE_PRIORITY):数值越大,优先级越高。默认是6。如果你想让自己的层覆盖poky里的recipe,把优先级设到7或更高就行。

4.3 meta/conf/machine/目录——机器配置的藏宝图

这个目录存放的是各种机器的配置文件。每个.conf文件定义了一款硬件平台。比如qemux86-64.conf、beaglebone-yocto.conf等。

一个典型的机器配置文件包含:

配置项 说明 示例
TUNE_FEATURES CPU架构特性 tune-corei7-64
MACHINE_FEATURES 硬件特性 wifi, bluetooth, screen
PREFERRED_PROVIDER 首选提供者 virtual/kernel
SERIAL_CONSOLES 串口控制台 115200;ttyS0

嗯,这里要注意:机器配置文件里定义的变量,会影响整个构建过程。比如你定义了MACHINE_FEATURES += "wifi",那系统就会自动把Wi-Fi相关的包加进来。我在项目中就遇到过因为忘记加bluetooth特性,导致蓝牙驱动没编译进去的尴尬。

4.4 meta/recipes-*/目录——配方的分类仓库

这个目录是按功能分类的recipe集合。常见的子目录有:

  • recipes-core/:核心系统组件,比如init系统、busybox、glibc等
  • recipes-bsp/:板级支持包,包括bootloader、设备树、固件等
  • recipes-kernel/:Linux内核相关,包括内核源码、模块、设备树编译
  • recipes-devtools/:开发工具,比如gcc、gdb、make等
  • recipes-connectivity/:网络连接相关,比如wpa_supplicant、dhcpcd等
  • recipes-graphics/:图形相关,比如X11、Wayland、GPU驱动等

每个recipe目录里通常包含:

recipes-example/example/
├── example_1.0.bb          # 主recipe文件
├── example_1.0.bbappend    # 追加文件(可选)
├── files/                  # 补丁、配置文件
│   ├── 0001-fix-bug.patch
│   └── example.conf
└── example.inc             # 公共包含文件(可选)

说白了,每个recipe就是一个软件的「安装说明书」。bitbake根据这个说明书去下载源码、打补丁、配置、编译、安装。我刚开始写recipe时,经常搞混SRC_URI和S变量的关系——SRC_URI告诉bitbake去哪里下载,S告诉它源码解压到哪个目录。

避坑指南:我曾经在recipes-kernel里直接修改了内核的recipe文件,结果下次同步poky时被覆盖了。正确的做法是:在自己的meta层里创建同名目录,用bbappend文件来追加修改。

4.5 构建输出目录tmp/——构建的成果与垃圾

当你运行bitbake core-image-minimal后,所有构建产物都会放在tmp/目录下。这个目录的结构如下:

tmp/
├── deploy/          # 最终产物(镜像、内核、设备树等)
│   ├── images/      # 可烧录的镜像文件
│   └── licenses/    # 许可证信息
├── work/            # 每个recipe的工作目录
│   └── core2-64-poky-linux/
│       ├── linux-yocto/
│       └── busybox/
├── stamps/          # 构建状态标记
├── log/             # 构建日志
└── cache/           # 解析缓存

这里我重点说几个:

  • deploy/images/:你最终要烧录到板子上的文件都在这里。比如core-image-minimal-qemux86-64.rootfs.ext4、bzImage、*.dtb等。
  • work/:每个recipe的编译工作目录。里面包含了源码、编译中间文件、安装后的文件。如果你要调试某个包的编译问题,来这里翻日志最直接。
  • stamps/:记录每个任务的完成状态。bitbake靠这些文件来判断哪些任务需要重新执行。

tmp/目录有个特点:它占空间特别大。一个完整的构建下来,轻松几十GB。我建议你在local.conf里设置INHERIT += "rm_work",这样构建完成后会自动清理工作目录,能省不少空间。

核心逻辑总结:Poky是骨架,meta层是血肉,machine配置是骨骼,recipe是器官,tmp/是构建过程的「手术室」。理解了这个结构,你就能在Yocto的世界里游刃有余。

Yocto项目结构知识体系 Poky(参考发行版) bitbake/ 构建引擎 meta/ 核心元数据 meta-poky/ 发行版配置 meta-yocto-bsp/ BSP conf/machine/ 机器配置 recipes-*/ 配方目录 classes/ 类文件 recipes-core/ recipes-kernel/ recipes-bsp/ recipes-devtools/ tmp/ 构建输出目录 deploy/ | work/ | stamps/ | log/ | cache/ Poky核心 一级目录 元数据层 Recipe分类 构建输出

这张图把整个Yocto项目结构串起来了。从Poky出发,分出四个核心目录,然后meta/内部又分出机器配置、配方目录、类文件,配方目录再按功能细分,最终所有构建产物汇聚到tmp/。你想想看,这个结构是不是很清晰?

可可精品资料库