yocto开发(1)----bitbake的全流程分析
1.do_fetch
从指定的源获取源码、补丁和其他资源。它从网络或本地源(如 Git 仓库、FTP 服务器、HTTP 地址等)下载源代码文件。do_fetch
是构建流程的第一个任务,它保证了构建所需的源文件或源代码被获取到本地。
如果源代码已经下载过并且没有变化,BitBake 会跳过这个任务,直接使用本地缓存的文件。否则,它会重新从指定的位置下载源代码。
SRC_URI
:指定源代码的下载地址,可以是 Git 仓库、HTTP URL、FTP 等。它是一个重要的变量,决定了源代码的来源。
SRC_URI = "git://git.yoctoproject.org/poky;branch=master"
2.do_unpack
解压缩或解包下载的源文件。这一步通常发生在 do_fetch
任务完成之后。它会解压从远程服务器或本地源获取的源代码包,如 .tar .gz or .zip
等格式。
如果下载的文件是压缩包,do_unpack
会解压到指定的目录(通常是 ${WORKDIR},
WORKDIR
:工作目录,是源代码解包后的存放位置),然后接下来的步骤会在该目录上执行。
解压安装包:SRC_URI = "file://mypackage-1.0.tar.gz"
解压后路径为:${WORKDIR}/mypackage-1.0从git clone,并且选择main分支,确保后续操作是在main的分支上进行
SRC_URI = "git://git.example.com/myrepo.git;branch=main"
3.do_patch
将补丁应用到解压后的源代码中。补丁通常用于修复源码中的问题,添加功能或对源码进行修改。BitBake 在执行 do_patch
时,会自动将所有指定的补丁文件应用到源码目录中。因为源码不能同时支持每个平台,设备,通过这样可以解决设备的多样性问题和适配性,这也是yocto的一大特点。
本地补丁:将补丁文件作为本地文件添加到配方中,然后使用 file:// 协议引用这些文件
SRC_URI = "file://mypatch.patch"外部补丁:补丁也可以通过网络下载。你可以将补丁文件放置在一个 HTTP 或 FTP 服务器上,并通过 URL 获取。
SRC_URI = "http://example.com/mypatch.patch"git补丁:通过 Git 来管理补丁。你可以将补丁提交为 Git 补丁,然后通过 git 命令来应用补丁
SRC_URI = "git://git.example.com/myrepo.git;branch=master;patch=1"do_patch 会使用 git am 或 git apply 命令将该补丁应用到源码中。
do_patch() {cd ${S}git am ${WORKDIR}/mypatch.patch
}
4.do_prepare_recipe_sysroot
do_prepare_recipe_sysroot
和 do_populate_sysroot
是关键的任务,用于实现配方之间的成果物共享机制
配方成果物共享机制概述:
第一阶段:A 配方构建时
在构建 A 配方时,A 配方的成果物需要在 do_install
任务中安装到 ${D}
目录。这个目录通常是 BitBake 构建系统中每个配方的安装目录。然后,执行 do_populate_sysroot
任务时,会把 ${D}
目录中的部分子目录自动拷贝到 ${SYSROOT_DESTDIR}
目录,而 ${SYSROOT_DESTDIR}
会被放到一个共享区中,通常这个共享区的位置是:
build/tmp/sysroots-components/
第二阶段:B 配方构建时
在 B 配方构建时,我们可以通过在 B 配方中添加 DEPENDS += "A"
来声明 B 配方依赖 A 配方。BitBake 会确保 A 配方的成果物已存在于 ${SYSROOT_DESTDIR}
中,并且 B 配方在构建时能够访问到这些成果物。
do_prepare_recipe_sysroot
任务的操作:
do_prepare_recipe_sysroot
任务会在 B 配方的工作目录(${WORKDIR}
)下创建两个 sysroot 目录:recipe-sysroot
:这是针对目标设备的 sysroot 目录,A 配方生成的成果物会被放在这里,供目标设备使用。recipe-sysroot-native
:这是针对本机设备的 sysroot 目录,A 配方的本机相关成果物(如编译工具、开发库等)会放在这个目录中。
BitBake 会根据 A 配方生成的成果物,自动将其拷贝到 B 配方的
recipe-sysroot
和recipe-sysroot-native
目录中,确保 B 配方在构建时能够找到 A 配方的头文件、库文件等成果物。
5.do_configure
do_configure
任务会根据源代码的构建系统要求,执行必要的配置操作,许多开源软件包在编译之前需要配置系统来生成适合目标平台的构建文件,常见的包括 Makefile
、CMakeLists.txt
、config.h
do_configure
是 在源代码下载、解包、补丁应用 等任务之后执行的,它为 编译(do_compile
) 阶段做好准备。
常见的构建do_configure的方式:
1.Autotools 构建系统:do_configure
会自动执行 ./configure
命令,这个命令会检查系统环境并生成适合目标系统的 Makefile。
inherit autotools # 继承 autotools 类
2.CMake 构建系统:do_configure
任务会调用 cmake
命令,并将必要的工具链文件和路径传递给它。CMake 会检查目标系统和交叉编译工具链,生成适合目标平台的构建文件(通常是 Makefile
或 Ninja
构建文件)。
inherit cmake # 继承 cmake 类
6.do_compile【正式编译】
do_compile
的任务是编译源代码。这个任务会根据之前 do_configure
生成的构建文件(如 Makefile
或 ninja
文件)来执行实际的编译命令。do_compile
会使用交叉编译工具链来编译代码。它会根据目标平台的工具链(如交叉编译器)来进行编译。
对于使用 Autotools 的项目,通常会运行
make
命令。do_compile() {# 使用 make 命令编译源代码oe_runmake }
对于使用 CMake 的项目,
do_compile
会运行cmake --build
命令do_compile() {# 使用 cmake 构建工具进行编译cmake --build ${B} -- -j ${PARALLEL_MAKE} }
7.do_install
do_install
将构建过程中生成的文件(如可执行文件、库文件、头文件、配置文件等)从构建目录(通常是 ${WORKDIR}
)复制到目标目录。
# 重载 do_compile 任务进行编译
do_compile() {${CC} ${LDFLAGS} helloworld.c -o helloworld
}# 重载 do_install 任务进行安装
do_install() {# 创建目标目录 /usr/bininstall -d ${D}${bindir}# 将编译后的 'helloworld' 安装到 /usr/bin 目录下 权限设置为755install -m 0755 helloworld ${D}${bindir}
}
8.do_package_data
用来将已安装的文件从 ${D}
(安装根目录)中提取并准备打包,为下面的do_package打辅助。
9.do_package
将已编译和安装到目标文件系统的文件打包成安装包或镜像,以便部署到目标设备上。它是构建过程中最后的打包阶段。根据 Yocto 配方中配置的打包方式(例如 .ipk
、.deb
或 .rpm
),do_package
生成相应的安装包文件。打包工具(如 opkg
、dpkg
、rpm
)会根据目标文件系统的结构将文件打包成相应的格式。
opkg_pkg
:用于生成.ipk
包,适用于 OpenEmbedded 系统。
rpm_pkg
:用于生成.rpm
包,适用于 Red Hat 系统。
deb_pkg
:用于生成.deb
包,适用于 Debian 系统。
tar_pkg
:用于生成.tar
或.tar.gz
压缩包
10.do_package_write_deb
do_package_write_deb
任务用于将已安装的文件打包成 .deb
格式的安装包,由 do_package
调用,依赖于 dpkg
工具链 。
11.do_package_qa
执行与质量检查相关的任务,确保生成的包符合 Yocto 和 BitBake 的质量标准。它检查生成的包是否符合一些特定的规则。
do_package_qa() {# 运行包质量检查工具,确保生成的包符合质量标准${QA_CHECK}
}
12.do_rootfs
do_rootfs
任务负责生成目标系统的 根文件系统(Root Filesystem)。根文件系统是操作系统的核心部分,包含了所有必需的系统文件(如库文件、二进制文件、设备节点、配置文件等)。do_rootfs
会把从各个配方安装的文件整理到一起,并生成一个完整的根文件系统。
13.do_flush_pseudodb
负责将 伪数据库(pseudodb)中的信息刷新到文件系统中。伪数据库是 BitBake 用来记录包的安装状态的一个缓存,确保构建过程中所有的文件和安装路径都能被正确记录。
do_flush_pseudodb() {# 刷新伪数据库中的信息${FLUSH_PSEUDODB_SCRIPT}
}
14.do_image_qa
对构建的镜像进行质量检查,确保生成的镜像符合目标系统的要求,并且没有错误或不符合标准的地方。
do_image_qa() {# 运行镜像质量检查工具,确保生成的镜像符合质量标准${QA_CHECK}
}
15.do_image
构建系统中最终生成目标镜像的核心任务。它将根文件系统(由 do_rootfs
生成的文件)打包成最终的镜像文件,主要是目标文件系统,可能不包含引导分区、内核等。通常用于存档、备份或虚拟机使用,不直接支持写操作
do_image() {# 生成镜像文件${IMAGE_GENERATION_SCRIPT}
}
16.do_rootfs_wicenv
do_rootfs_wicenv
是一个与 WIC(Writeable Image Creator) 环境相关的任务,专门用于生成目标设备的根文件系统(rootfs),并准备 WIC 镜像。WIC 镜像是一种嵌入式设备的磁盘映像格式,用于部署到目标硬件上。
17.do_image_tar
将目标文件系统(rootfs)打包成 tar 压缩文件,可以作为一个备份。
18.do_image_wic
do_image_wic
任务用于生成 WIC 格式的磁盘映像,这是嵌入式设备常用的一种文件系统映像格式。.wic
格式的镜像包含了目标设备的完整文件系统,并且可以用于烧录到目标设备的存储介质(如 SD 卡、eMMC 等)。
do_image_wic() {# 创建 WIC 格式的映像文件wic create ${WORKDIR}/myimage.wic --image-type wic
}
19.do_image_complete
负责生成 完整的目标镜像,并将所有必要的文件和配置整合到最终镜像中。这个镜像通常包括目标文件系统、引导加载器、内核映像和其他必须的系统文件,适合烧录到目标设备中。
do_image_complete() {# 将根文件系统、引导加载器和内核打包成完整的镜像create_image ${DEPLOY_DIR_IMAGE}/final_image.img
}
20.do_build
执行整个构建流程,包括获取源代码、应用补丁、配置、编译、打包和生成最终镜像。它是整个构建过程的启动任务,确保所有的构建任务按照正确的顺序执行。它并不直接做任何编译或打包,而是触发整个构建流程,依赖于任务之间的依赖关系来执行各个任务。