-
引言
本文主要介绍yocto系统,通过本次学习,可以了解到yocto系统的目录结构,编译过程以及如何从零构造属于自己的yocto项目。
-
Yocto系统介绍
-
什么是Yocto
在嵌入式产品开发中,通常都会定制自己公司的Linux发行版,所谓发行版,即根据自家产品的功能和特性定制bootloader、kernel、rootfs,最后得到这三个的镜像文件。
定制Linux发行版是一件耗时耗力、技术含量比较高的一项大工程,对于很多公司来说,是没有这个人力和财力来做这件事的,所以大多数公司会选择现有的开源工具来定制自己家的 Linux 发行版。
Yocto,是一个开源社区。它通过提供模版、工具和方法帮助开发者创建基于linux内核的定制系统,支持ARM, PPC, MIPS, x86 (32 & 64 bit)硬件体系架构。
Yocto Projec是一个开源的协作软件,提供模板、工具和方法帮你创建定制的 Linux 系统和嵌入式产品,而无需关心硬件体系。适合嵌入式Linux开发人员使用。极大地简化你的开发过程,因为你不用再从头裁剪一个完整的Linux发布版本,后者通常包括许多你并不需要的软件。
Yocto项目通过Poky来构建一个系统,并提供了一个开放源码的开发环境,针对目标为ARM,MIPS,PowerPC和x86架构,而平台包括x86-64和模拟器。
Yocto兼容OpenEmbedded项目,你可以简单可靠地进行编译和开发.完全支持通过QEMU模拟器的广泛的硬件和设备的仿真。通过Yocto项目开发出来的映像可以在一个QEMU模拟器中进行引导,开发环境可以作为一个开发嵌入式软件的良好的测试平台。
Yocto/Poky/OpenEmbedded三者关系
Yocto: 是一个综合开源社区,包含大量的项目资源,是专门促进在嵌入式设备上使用Linux。
Poky: 认为是Yocto中一个组件,作为一个独立的开源项目开发yocto项目,多数作为一个参考项目(实际上我们下载的yocto project构建系统的时候,实际上就是下载一个poky的发行版)。
OpenEmbedded: OpenEmbeded是嵌入式Linux的构建框架,它提供了一个可用于交叉编译的方案,通过该方案开发者可以编译出用于嵌入式系统的Linux发行版。OpenEmbeded解决的痛点有以下的几个:
首先是嵌入式系统构建的交叉编译的问题,因为通常我们在x86的环境下做开发,但是目标对应的嵌入式硬件架构却可能是五花八门的;
其次是一个可用的Linux系统包含引导模块、内核、文件系统,以及很多必要的应用程序,如果手动编译上述的这些东西(LFS就是一个例子),需要花费很大的力气而且容易出错,而使用OpenEmbeded只需要几个简单的命令即可自动完成整个构建的过程。里面包含一组元数据和脚本,实现下载、解包,打补丁,编译等流程,bitbake是OE其中最核心的组件。
-
Yocto版本介绍
Yocto版本命名方式包含版本号和代号(codename),EOL代表停止维护
https://wiki.yoctoproject.org/wiki/Releases
版本查询:/meta-poky/conf/distro/poky.conf(本文用gatesgarth发行版来演示)
DISTRO = "poky"
DISTRO_NAME = "Poky (Yocto Project Reference Distro)"
DISTRO_VERSION = "3.2.4"
DISTRO_CODENAME = "gatesgarth"
-
Poky目录结构
总目录预览:
bitbake:属于OE一部分,我们在构建系统时使用的bitbake命令其实就是这里面的bitbake。该目录用来读取和解析meta目录的数据,并创建相应的任务来处理,通常bitbake出现问题不用去bitbake目录找原因,而是从meta等目录找原因。
meta:元数据,主要存放模拟目标(qemux86、qemuarm)的配方、通用类和机器通用配置。
recipes: 以bb为后缀的文件,配方文件,包含下载的源码的位置或者来源,补丁的使用以及如何编译源文件等等。
classes: 类文件,包含用于在配方文件之间共享的信息,类似于共享库的意思,一个例子就是autotools,如果该bb使用的是autotool来编译,那么在bb文件中需要包含该类字段“inherit autotools”。
conf: 配置文件,配置编译过程中的各种变量配置,如机器配置选项等。
meta-poky:是在meta目录之上的拓展,build目录中的conf目录就是从这个目录中的conf演变来。
meta-yocto-bsp:从文件名可以看出此目录是方便BSP开发人员开发的目录,提供了主流体系硬件平台的BSP模板。
build:该目录是source之后创建的,build目录包含用户配置文件和下载解压编译等结果都放在这里面,source过程除了创建build目录还设置的环境变量,具体感兴趣可以参考oe-init-build-env和scripts/oe-setup-builddir。
-
Yocto构建流程
构建流程预览
OpenEmbedded构建流程
OpenEmbedded是yocto project的构建系统,核心的任务执行器是bitbake,构建流程如下图所示:
配置文件:用户配置、元数据、机器配置、发行版本配置。
源文件:上游发行版,本地项目和SCM。
构建系统:源代码的获取、打补丁、编译、输出软件包和QA测试。
拓展软件包:输出的软件包目录集合。
生成的image或者SDK。
用户配置生成过程
配置文件的作用是告诉bitbake按照什么方式来构建image。
可以看出build/conf目录下有三个文件
bblayers.conf:里面存放poky默认编译的layer,如果需要添加自己的layer,需要在此后面直接添加。
temlateconf.cfg:存放该模板从何处生成。
local.conf:目标机器配置,发行配置以及包格式配置等,该文件配置是由meta-poky/conf 配置生成。
-
BitBake过程
BitBake是一个通用的任务执行引擎,它允许shell和Python任务在复杂的任务间依赖约束下高效并行地运行。
编译一个镜像需要用到如下task
-
BitBake获取源码
do_fetch任务:下载或者读取源文件
do_unpack任务:解压源文件到build/tmp/work响应的目录下
TMPDIR
OE构建系统执行的所有工作的基目录,默认是tmp目录,也就是TMPDIR变量定义的路径
TARGET_OS
当前目标操作系统,当前是Linux
PN
用于构建的recipe名称
PV
用于构建包的recipe版本
PR
用于构建包的recipe修订版本
S
指向build目录中的源代码或者源文件路径
BPN
一般可以看成PN
-
BitBake patch流程
源码下载完成和拆分之后,bitbake就需要应用patch文件,直接打到S变量指定的位置源码,对应的任务就是do_patch。
补丁的后缀名只能是.patch 和 .diff
当在SRC_URI指定补丁时,BitBake会按照指定的顺序在FILESPATH中搜索对应patch。
-
BitBake编译配置流程
在前面的下载,解压和应用补丁之后,接下来就是将recipe依赖的一些文件放到sysroot中,然后configure和编译阶段。
do_prepare_recipe_sysroot:
在工作目录下(一般为tmp/work/)创建两个sysroot目录,一个sysroot目录用于在交叉编译时存放在目标板上运行的软件所依赖的库,比如说glibc库。另一个sysroot目录(recipe-sysroot-native)存放的是本地编译所依赖的库文件。
do_configure:
该部分就类似于我们在手动编译项目时,手动输入的./configure 配置和cmake一样。
do_compile:
编译目录为B指向的路径,默认情况下B和S指向的目录是相同的。
do_install:
编译结束之后,bitbake执行do_install任务,将文件从B指向的目录copy到D所指向的目录,稍后在此目录进行文件打包。
-
BitBake打包流程
项目编译完成安装之后,下面就开始进行打包流程
将编译出来的包进行拆分,debug版本放到一个目录,release版本放到一个目录,例如image目录放的是debug版本,packages-split放的是release版本。
do_package/do_packagedata:对数据包进行拆分,分析创建包的元数据。
do_populate_sysroot:将do_install安装的目录文件拷贝到相应的sysroot中,这个目录最终会被放到共享区,其它任务构建就可以共享,具体哪些目标会被拷贝,取决于定义的sysroot相关的变量。
PKGD:
拆分包的目标目录。
PKGDESTWORK:
存放制作包的临时目录。
PKGDEST:
packages-split目录。
PKGDATA_DIR:
共享区,可以被其它任务所依赖
do_package_write_*:
根据包的类型,将包放到deploy目录下拓展软件包。
-
BitBake镜像文件的制作
一旦完成包的拆分并存储在package feeds,构建系统将使用bitbake生成系统镜像。
do_rootfs:
镜像的制作分为几个阶段,依赖于多个任务和变量,do_rootfs为镜像创建根文件系统。
IMAGE_INSTALL:
需要安装的软件包的集合,也就是包源位置,由于我们添加默认打包到镜像(参考第四章),所以演示目录也存在于该变量中。
PACKAGE_EXCLUDE:
用来指定不需要安装到image包中
IMAGE_ROOTFS:
指向文件系统创建过程中的目录。
IMAGE_MANIFEST:
文件清单,此文件列出已经安装的软件包。
IMAGE_FSTYPES:
指定文件系统的压缩类型。
-
从零构建Yocto系统
-
代码下载
本文演示下载gatesgarth版本的yocto
操作:git clone -b gatesgarth git://git.yoctoproject.org/poky
-
代码编译
source oe-init-build-env
source之后我们看到可以输入多个参数,有core-image-minimal,该镜像是没有上层应用程序的,本次测试用的是core-image-sato,这个是包含一个GUI。
bitbake core-image-sato
第一次编译的时候,可能会遇到各种各样的报错问题,大部分都是主机编译环境问题导致,只需耐心寻找解决办法即可。
-
镜像运行
runqemu qemux86-64
此时我们可以看到,image能够正常的运行,由于虚拟机比较卡顿,我们没有直接进入图形界面演示,而是直接进入命令行操作。
-
创建自己的meta
创建成功的layer里面含有一个recipe的例子和recipe配置文件,目的是能找到该目录下添加的所有的recipe。
通过前面的学习可以得知,此时默认整编是没有包含这个layer,需要我们手动执行bitbake-layers add-layer添加即可,或者通过前面的学习手动添加 到/metapoky/conf/bblayers.conf.sample。
-
添加自己的recipe
下面分别演示makefile、autotools和Cmake三种方式添加项目
makefile 方式添加项目
autotools 方式添加项目
在编译bb之前,我们先手动编译确保可以编译通过再使用bb文件编译
通过上述演示,可以看到手动能编译通过,接下来我们使用bb演示
Cmake 方式添加项目
手动编译通过之后,通过bb文件编译
-
验证
此时我们的修改还没有编到rootfs镜像中,我们可以追加IMAGE_INSTALL 安装到镜像中
最后如下图验证通过
单个调试的时候,可以通过eth0地址scp文件进到系统内部调试
-
QA
在构建recipe时,openembed构建系统对输出执行各种QA检查,以确保检测和报告常见问题。有时,当您创建一个新的配方来构建新的软件时,它会毫无问题地构建。但是情况并非如此,或者在构建软件时遇到QA问题,那么解决这些问题可能需要一些时间。尽管忽略QA消息甚至禁用QA检查很容易,但最好尝试并解决任何报告的QA问题。
具体的QA问题,可以官网说明
https://docs.yoctoproject.org/3.2/ref-manual/ref-qa-checks.html
至此,本文yocto系统介绍暂时告一段落,后面如何制作SDK等其它方面知识,请自行研究即可。
原文连接: