我们使用yocto编译镜像的时候,第一步是要配置编译环境,第二步就是使用bitbake工具编译出我们需要的镜像。这里我们就来分析一下使用yocto进行bitbake的过程吧。
现在我们尝试一下分析bitbake一个包和一个镜像的过程。使用的是NXP官方的imx8mp的yocto。点击这里可以访问开发版资料,下载用户手册,根据用户手册搭建yocto环境,编译yocto。
我们使用以下命令列出bitbake一个包和一个镜像过程可以的执行的任务:
jian@ubuntu:~/imx-yocto-bsp/build2$ bitbake iozone3 -c listtasks
Loading cache: 100% |#################################################################################################################################################| Time: 0:00:00
Loaded 4737 entries from dependency cache.
Parsing recipes: 100% |###############################################################################################################################################| Time: 0:00:03
Parsing of 3188 .bb files complete (3187 cached, 1 parsed). 4738 targets, 283 skipped, 5 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies
Build Configuration:
BB_VERSION = "2.0.0"
BUILD_SYS = "x86_64-linux"
NATIVELSBSTRING = "universal"
TARGET_SYS = "aarch64-poky-linux"
MACHINE = "imx8mp-lpddr4-evk"
DISTRO = "fsl-imx-xwayland"
DISTRO_VERSION = "5.15-kirkstone"
TUNE_FEATURES = "aarch64 armv8a crc crypto"
TARGET_FPU = ""
meta
meta-poky = "HEAD:27de52e402ae000dfa502d52908cd6e6aef923ec"
meta-oe
meta-multimedia
meta-python = "HEAD:5357c7a40eaf8d1bcf7ff58edbba8e9527e40c7d"
meta-freescale = "HEAD:2fb1ce365338126aad365012ebb913b3e4a9f1be"
meta-freescale-3rdparty = "HEAD:de0eb1408150d77f9cce97c559f9a5a3c71e5d6c"
meta-freescale-distro = "HEAD:fc15f5003043da23212596be7366ae2547c308ad"
meta-bsp
meta-sdk
meta-ml
meta-v2x = "HEAD:5bc708f56575a878da17f2148e959c95d06cf8db"
meta-nxp-demo-experience = "HEAD:8fade3993b832ecd823771644f2a7b731f8f4527"
meta-chromium = "HEAD:d25d8ee98a656b2534d0eec6138ef264529fab4f"
meta-clang = "HEAD:85d956d95401479ca666139e31f662f60c156d5f"
meta-gnome
meta-networking
meta-filesystems = "HEAD:5357c7a40eaf8d1bcf7ff58edbba8e9527e40c7d"
meta-qt6 = "HEAD:b2894aad5c1aaa85f2f5c7b94391b7c51c39e555"
meta-virtualization = "HEAD:973c8d0964c6f40338857efe5b8009b2f647d485"
Initialising tasks: 100% |############################################################################################################################################| Time: 0:00:02
Sstate summary: Wanted 0 Local 0 Mirrors 0 Missed 0 Current 0 (0% match, 0% complete)
NOTE: No setscene tasks
NOTE: Executing Tasks
do_build Default task for a recipe - depends on all other normal tasks required to 'build' a recipe
do_checkuri Validates the SRC_URI value
do_clean Removes all output files for a target
do_cleanall Removes all output files, shared state cache, and downloaded source files for a target
do_cleansstate Removes all output files and shared state cache for a target
do_compile Compiles the source in the compilation directory
do_configure Configures the source by enabling and disabling any build-time and configuration options for the software being built
do_deploy_source_date_epoch
do_deploy_source_date_epoch_setscene (setscene version)
do_devshell Starts a shell with the environment set up for development/debugging
do_fetch Fetches the source code
do_install Copies files from the compilation directory to a holding area
do_listtasks Lists all defined tasks for a target
do_package Analyzes the content of the holding area and splits it into subsets based on available packages and files
do_package_qa Runs QA checks on packaged files
do_package_qa_setscene Runs QA checks on packaged files (setscene version)
do_package_setscene Analyzes the content of the holding area and splits it into subsets based on available packages and files (setscene version)
do_package_write_deb Creates the actual DEB packages and places them in the Package Feed area
do_package_write_deb_setscene Creates the actual DEB packages and places them in the Package Feed area (setscene version)
do_packagedata Creates package metadata used by the build system to generate the final packages
do_packagedata_setscene Creates package metadata used by the build system to generate the final packages (setscene version)
do_patch Locates patch files and applies them to the source code
do_populate_lic Writes license information for the recipe that is collected later when the image is constructed
do_populate_lic_setscene Writes license information for the recipe that is collected later when the image is constructed (setscene version)
do_populate_sysroot Copies a subset of files installed by do_install into the sysroot in order to make them available to other recipes
do_populate_sysroot_setscene Copies a subset of files installed by do_install into the sysroot in order to make them available to other recipes (setscene version)
do_prepare_recipe_sysroot
do_pydevshell Starts an interactive Python shell for development/debugging
do_unpack Unpacks the source code into a working directory
NOTE: Tasks Summary: Attempted 1 tasks of which 0 didn't need to be rerun and all succeeded.
上面是bitbake iozone3可以执行的全部任务,当然我们在bitbake iozone3的时候并不会执行全部任务,比如:do_clean、do_cleanall 、do_cleansstate 。
这些任务分别是移除目标的所有输出文件、移除目标的所有输出文件、共享状态缓存和下载的源文件、移除目标的所有输出文件和共享状态缓存。一般是我们重新编译之前使用的,正常bitbake是不会运行到的。
我们可以使用debug功能把bitbake运行的全部任务列出来:
bitbake iozone3 -D
...
(/home/jian/imx-yocto-bsp/sources/meta-openembedded/meta-oe/recipes-benchmark/iozone3/iozone3_492.bb:do_fetch)
(/home/jian/imx-yocto-bsp/sources/meta-openembedded/meta-oe/recipes-benchmark/iozone3/iozone3_492.bb:do_unpack)
(/home/jian/imx-yocto-bsp/sources/meta-openembedded/meta-oe/recipes-benchmark/iozone3/iozone3_492.bb:do_prepare_recipe_sysroot)
(/home/jian/imx-yocto-bsp/sources/meta-openembedded/meta-oe/recipes-benchmark/iozone3/iozone3_492.bb:do_patch)
(/home/jian/imx-yocto-bsp/sources/meta-openembedded/meta-oe/recipes-benchmark/iozone3/iozone3_492.bb:do_deploy_source_date_epoch)
(/home/jian/imx-yocto-bsp/sources/meta-openembedded/meta-oe/recipes-benchmark/iozone3/iozone3_492.bb:do_populate_lic)
(/home/jian/imx-yocto-bsp/sources/meta-openembedded/meta-oe/recipes-benchmark/iozone3/iozone3_492.bb:do_configure)
(/home/jian/imx-yocto-bsp/sources/meta-openembedded/meta-oe/recipes-benchmark/iozone3/iozone3_492.bb:do_compile)
(/home/jian/imx-yocto-bsp/sources/meta-openembedded/meta-oe/recipes-benchmark/iozone3/iozone3_492.bb:do_install)
(/home/jian/imx-yocto-bsp/sources/meta-openembedded/meta-oe/recipes-benchmark/iozone3/iozone3_492.bb:do_package)
(/home/jian/imx-yocto-bsp/sources/meta-openembedded/meta-oe/recipes-benchmark/iozone3/iozone3_492.bb:do_populate_sysroot)
(/home/jian/imx-yocto-bsp/sources/meta-openembedded/meta-oe/recipes-benchmark/iozone3/iozone3_492.bb:do_packagedata)
(/home/jian/imx-yocto-bsp/sources/meta-openembedded/meta-oe/recipes-benchmark/iozone3/iozone3_492.bb:do_package_write_deb)
(/home/jian/imx-yocto-bsp/sources/meta-openembedded/meta-oe/recipes-benchmark/iozone3/iozone3_492.bb:do_package_qa)
(/home/jian/imx-yocto-bsp/sources/meta-openembedded/meta-oe/recipes-benchmark/iozone3/iozone3_492.bb:do_build)
bitbake imx-image-multimedia-jian -D
(/home/jian/imx-yocto-bsp/sources/meta-imx/meta-sdk/recipes-fsl/images/imx-image-multimedia-jian.bb:do_fetch)
(/home/jian/imx-yocto-bsp/sources/meta-imx/meta-sdk/recipes-fsl/images/imx-image-multimedia-jian.bb:do_prepare_recipe_sysroot)
(/home/jian/imx-yocto-bsp/sources/meta-imx/meta-sdk/recipes-fsl/images/imx-image-multimedia-jian.bb:do_rootfs)
(/home/jian/imx-yocto-bsp/sources/meta-imx/meta-sdk/recipes-fsl/images/imx-image-multimedia-jian.bb:do_flush_pseudodb)
(/home/jian/imx-yocto-bsp/sources/meta-imx/meta-sdk/recipes-fsl/images/imx-image-multimedia-jian.bb:do_image_qa)
(/home/jian/imx-yocto-bsp/sources/meta-imx/meta-sdk/recipes-fsl/images/imx-image-multimedia-jian.bb:do_image)
(/home/jian/imx-yocto-bsp/sources/meta-imx/meta-sdk/recipes-fsl/images/imx-image-multimedia-jian.bb:do_write_wks_template)
(/home/jian/imx-yocto-bsp/sources/meta-imx/meta-sdk/recipes-fsl/images/imx-image-multimedia-jian.bb:do_rootfs_wicenv)
(/home/jian/imx-yocto-bsp/sources/meta-imx/meta-sdk/recipes-fsl/images/imx-image-multimedia-jian.bb:do_image_tar)
(/home/jian/imx-yocto-bsp/sources/meta-imx/meta-sdk/recipes-fsl/images/imx-image-multimedia-jian.bb:do_image_wic)
(/home/jian/imx-yocto-bsp/sources/meta-imx/meta-sdk/recipes-fsl/images/imx-image-multimedia-jian.bb:do_image_complete)
(/home/jian/imx-yocto-bsp/sources/meta-imx/meta-sdk/recipes-fsl/images/imx-image-multimedia-jian.bb:do_populate_lic_deploy)
(/home/jian/imx-yocto-bsp/sources/meta-imx/meta-sdk/recipes-fsl/images/imx-image-multimedia-jian.bb:do_build)
经过过滤,可以看到bitbake的全部过程。在此之前,系统会自动bitbake依赖的其他包,这部分我们就不仔细分析了,接下来我们逐个分析bitbake的过程吧,由于这些任务是并行的,我这里会修改一下任务顺序,方便大家理解。
0.准备任务
解析配方文件,bitbake本配方所依赖的文件。
1.do_fetch
根据配置文件中SRC_URI变量所指定的方式(git管理、本地获取、上游开源项目)获取源代码。
SRC_URI变量主要有以下几种:
- file://-从本地机器 获取文件。
- bzr://-从 Bazaar 版本控制存储库中获取文件。
- git://-从 Git 版本控制存储库中获取文件。
- svn://-从 Subversion (svn) 版本控制存储库中获取文件。
- http://-使用http。
- https://-使用https。
2.do_unpack
用于解压源文件,到build/tmp/work/相应的目录下,构建系统执行所有工作的基目录。默认的目录是tmp目录。
3.do_patch
如果对开源项目进行了修改,则这个任务可以为解压后的源码打补丁,比如对linux开源内核源码进行了修改。
4.do_prepare_recipe_sysroot
do_prepare_recipe_sysroot与do_populate_sysroot是staging.bbclass类中关键任务,用于共享配方之间成果物!比如一个配方B需要使用配方A的成果物(比如头文件、动态/静态链接库、配置文件),yocto为了解决这种问题,提供了一套配方成果物共享机制,该机制分为两阶段:
- 第一阶段在A配方构建时完成。A配方在构建时,需要在do_install 任务中将需要共享的文件安装至{D}目录,后续执行的do_populate_sysroot任务将自动拷贝{D}目录下部分子目录到{SYSROOT_DESTDIR},而{SYSROOT_DESTDIR}目录最终会放置到共享区(默认为build/tmp/sysroots-components)暂存,其他配方构建时就可以从共享区拷贝。
- 第二阶段在B配方构建时完成。B配方中添加DEPENDS += “A”,便可使用A配方的成果物了。bitbake执行构建任务时会保证B配方的do_prepare_recipe_sysroot任务执行前,A配方的成果物已位于build/tmp/sysroots-components中。
第一阶段的{D}目录下子会被自动拷贝的目录由三个变量指定,分别为SYSROOT_DIRS(目标设备需要保存的子目录)、SYSROOT_DIRS_BLACKLIST(目标设备不需要保存的子目录)、SYSROOT_DIRS_NATIVE(本机设备需要保存的目录)。
第二阶段的do_prepare_recipe_sysroot任务会在{WORKDIR}目录中创建两个sysroot目录并填充(所有依赖拷贝到其中),这两个目录名分别为"recipe-sysroot"和"recipe-sysroot-native"(本机),其中"recipe-sysroot"给目标设备使用,A配方生成的成果物就在里面,另一个"recipe-sysroot-native"是给本机设备使用的。
5.do_configure
此任务用于完成编译源码前的配置,配置可以来自配方本身,也可以来自继承的类,一般情况我们都会使用autotools(配方中使用inherit autotools)、cmake类(配方中使用inherit cmake)或默认的make(不需要额外配置)。该任务运行时将当前工作目录设置为${B}(一般与{S}相同),该任务有个默认行为,即如果找到一个makefile (makefile, makefile,或GNUmakefile)并且CLEANBROKEN没有设置为“1”,则运行oe_runmake clean。
- 基于autotools的软件包编译,则do_configure任务就如同手动执行./configure ${EXTRA_OECONF} ${PACKAGECONFIG_CONFARGS}一样。
- 基于cmake的软件包编译,则do_configure任务就如同手动执行mkdir build/ && cd build/ && cmake ${EXTRA_OECMAKE}一样。
- 基于make的软件包编译,则do_configure任务相当于只做默认行为。
6.do_compile
编译源代码。该任务运行时将当前工作目录设置为{B}(一般与{S}相同),该任务有个默认行为,即如果找到一个makefile (makefile, makefile,或GNUmakefile),则运行oe_runmake,若未找到此类文件将不执行任何操作。
如果在执行oe_runmake时需要传入额外编译选项或链接库,则可以使用在配方中以下变量:
- CFLAGS += “-I${WORKDIR}/recipe-sysroot/usr/include/xxx -DBMCW=ON” #gcc的编译选项,增加额外头文件检索路径,定义BMCW宏
- CXXFLAGS = " -fPIC" #g++的编译选项,告诉编译器产生位置无关代码
- LDFLAGS += “-L${WORKDIR}/recipe-sysroot/usr/lib -yyy” #编译器链接选项
7.do_install
文件或成果物的安装任务。该任务会将编译目录{B}中需要打包的文件(放到目标设备中去的及其他配方依赖的)复制到保存区{D}中。
例如:
do_install() {
oe_runmake DESTDIR=${D}${libdir} install #执行Makefile中安装任务(安装.so),传入安装目录
install -m 0644 -d ${D}${includedir}/api #创建头文件目录
install -m 0644 ${S}/api_common.h ${D}${includedir}/api #安装头文件
}
8.do_package
任务分析在{D}目录中找到的文件,并根据可用的包和文件将它们分成子集。分析处理过程包括以下内容:去除调试符号,查看包之间的共享库依赖关系,以及查看包之间的关系。
9.do_packagedata
任务根据分析创建包元数据放置Package Feeds(即PKGDATA_DIR指定目录)中,这样构建系统就可以从拿到包生成最终的image。
10.do_populate_sysroot
任务在之前已经介绍过。该任务将自动拷贝{D}目录下部分子目录到{SYSROOT_DESTDIR},并将{SYSROOT_DESTDIR}目录内容暂存至共享区(默认为build/tmp/sysroots-components)。自动拷贝的子目录由三个变量指定,分别为SYSROOT_DIRS(目标设备需要保存的子目录)、 SYSROOT_DIRS_BLACKLIST(目标设备不需要保存的子目录)、SYSROOT_DIRS_NATIVE(本机设备需要保存的目录)。
11.do_package_write_deb
该任务由于配置了yocto的包管理模式为deb,会在这里把安装好的文件或成果物打包成deb文件。
12.do_package_qa
任务会对打包的文件运行QA检查。
13.do_rootfs
任务将创建目标设备的根文件系统(将需要打包至目标设备的程序、库、文件等都放置到根文件系统中),这个根文件系统最终打包到rootfs中。
14.do_flush_pseudodb
该任务使用类root权限把rootfs整理对齐。在fake root环境中运行任务的能力被称为“fakeroot”,它是从BitBake关键字/变量标志派生出来的,该标志为任务请求一个fake root环境。在OpenEmbedded 构建系统中,实现fakeroot的程序称为Pseudo。Pseudo通过使用环境变量LD_PRELOAD重写系统调用,这会导致以root用户身份运行的错觉。
15.do_image_qa
任务会对打包的镜像运行QA检查。
16.do_image
do_image 任务会通过 IMAGE_PREPROCESS_COMMAND 对image进行预处理,主要是优化image大小。
根据需要动态生成支持的 do_image_* 任务,生成的任务类型取决于IMAGE_FSTYPES变量。do_image_* 任务将所有内容转换为一个image文件或一组image文件,并且可以压缩根文件系统image大小,以减小最终烧写到目标设备的image整体大小。用于根文件系统的格式取决于 IMAGE_FSTYPES变量,压缩取决于格式是否支持压缩。
17.do_rootfs_wicenv
任务将配置wic镜像的环境。
18.do_image_tar
任务将roofs打包成tar包。
19.do_image_wic
任务将roofs打包成wic镜像。
20.do_image_complete
该任务将通过IMAGE_POSTPROCESS_COMMAND完成image的后续处理,默认情况IMAGE_POSTPROCESS_COMMAND为空,
21.do_build
取决于“构建”一个配方所需的所有其他正常任务。
bitbake过程就讲到这里了。
参考资料:
项目概述和概念手册:https://docs.yoctoproject.org/overview-manual/index.html
项目参考手册:https://docs.yoctoproject.org/ref-manual/index.html