ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

yocto(二)——bitbake工作流程

2022-01-08 09:05:10  阅读:1070  来源: 互联网

标签:yocto do 文件 流程 bitbake 任务 image 配方 目录


本文参考yocto官方手册,如有理解不当之处,欢迎留言指出。

项目概述和概念手册:https://docs.yoctoproject.org/overview-manual/index.html

项目参考手册:https://docs.yoctoproject.org/ref-manual/index.html

yocto项目的厨师——bitbake

​ bitbake是OpenEmbedded构建系统的引擎,通过解析一系列配置文件(主要为recipes,即bb/bbappend文件)来创建任务列表,并根据依赖关系依次执行。通过bitbake -c listtasks xxx(模块名或映像名)命令可以查看编译一个模块或整个映像所需任务名称。编译一个模块/映像的主要执行过程如下(内核除外):
在这里插入图片描述
​ 下面按四个阶段来讲解bitbake的执行过程及涉及的变量,其中第四阶段(上图标黄的两任务)不是编译每个模块都有的。

源码获取及处理

​ 这个阶段包含三个任务,分别为do_fetch、do_unpack、do_patch。

原文件来源

​ yocto编译一个模块所需的源代码或开源组件从哪里获取?
在这里插入图片描述

​ 如上图所示,源码可以从上游开源项目(如busybox-1.28.3.tar.bz2)、本地项目(本地源代码)、软件配置管理(如git)中获取。

do_fetch任务:根据配置文件中SRC_URI变量所指定的方式获取源代码。

do_unpack任务:如果源文件需要解压,则该任务会将源码包解压到指定目录下。
在这里插入图片描述

do_patch任务:如果对开源项目进行了修改,则这个任务可以为解压后的源码打补丁,比如对linux开源内核源码进行了修改。
在这里插入图片描述

这个大阶段涉及的配置变量有以下:

SRC_URI

​ 源文件列表变量,位于配方(recipe)文件中。每个recipe必须有一个指向源的SRC_URI变量。

SRC_URI = "git://github.com/openbmc/linux;protocol=git;branch=${KBRANCH}" #表示从github上下载linux内核源码
SRC_URI += "file://defconfig" #表示从本地目录获取内核默认配置,目录的路径由FILESPATH变量指定

​ 以下列举常用的获取方式,更多的获取方式请参阅SRC_URI

file://-从本地机器 获取文件,通常是元数据附带的文件(例如补丁、内核配置、uboot配置文件),路径是相对于FILESPATH变量的。构建系统默认在配方同目录下名为“${BP}”"${BPN}""files"的目录下查找指定文件,如需增加额外路径,便通过FILESPATHFILESEXTRAPATHS指定。

​ 注意:如果源码时本地文件,确保每个文件都使用file://写出,而不是使用指定文件夹方式下载整个文件夹,因为yocto需要单独检查每个文件是否被修改。

bzr://-从 Bazaar 版本控制存储库中获取文件。

git://-从 Git 版本控制存储库中获取文件。

​ 如果是从本地仓库下载,则先配置好本地Git仓库。yocto依赖与git的版本控制,简单来说就是yocto每次编译时候,会去检查软件包的源文件是否修改,只有修改过才会让软件包重新编译,那么对于git仓库就是对比上一次与当次版本差异。所以,对于源码在本地的git仓库的软件包,需要在每次编译前进行以下操作:

git add ./*
git commit -m "test"

​ 这样就可以确保本地git仓库源码修改后能参与yocto工程编译。

svn://-从 Subversion (svn) 版本控制存储库中获取文件。

http://-使用http。

https://-使用https。

DL_DIR

​ 用于指定开源组件包(tar、git等)下载的存放路径,位于编译目标层的conf/local.conf.sample文件中(如有需要可在此文件中修改),这个文件将被解析到build/conf/local.conf文件中,默认情况下该变量指定的目录为build/downloads/,如果多用户在一台编译机器上使用,可以指定一个公共目录,避免重复下载,比如DL_DIR ?= "/opt/downloads",同时修改chmod 777 /opt/downloads即可。

​ 通常一个组件包下载完毕后,在存放目录下会生成一个包名加".done"的文件表示该包下载完成,比如:

root:~/work/open_source/openbmc/build/downloads$ ls busybox-1.32.0.tar.bz2* -l
-rw-r--r-- 1 root root 2439463 Jun 27  2020 busybox-1.32.0.tar.bz2
-rw-r--r-- 1 root root     463 Mar  7  2021 busybox-1.32.0.tar.bz2.done

​ 一个技巧就是某个开源组件一直下载失败,那就从其他地方下载同版本组件拷贝到存放目录下,并复制一个*.done文件改为对应名字即可。

FILESPATH

​ 构建系统搜索本地文件(本地源码、补丁、配置文件等)的目录集合,位于配方(recipe)文件中。在构建过程中,bitbake查找SRC_URI变量的file://语句指定的本地文件时,会依次搜索FILESPATH变量指定的目录集合,该变量的默认值在meta/classes/base.bbclass中定义:

FILESPATH = "${@base_set_filespath(["${FILE_DIRNAME}/${BP}", \
        "${FILE_DIRNAME}/${BPN}", "${FILE_DIRNAME}/files"], d)}"

​ 一个简单的示例如下。

SRC_URI += "file://defconfig" #只是将配置文件拷贝到${WORKDIR}目录下
SRC_URI += "file://patch/0001-XXX.patch" #将补丁文件拷贝到${WORKDIR}目录下,并将补丁应用到${S}目录
SRC_URI += "file://patch/0002-XXX.diff" #将补丁文件拷贝到${WORKDIR}目录下,并将补丁应用到${S}目录
SRC_URI += "file://patch/0003-XXX.patch;apply=yes" #将补丁文件拷贝到${WORKDIR}目录下,并将补丁应用到${S}目录,这是显示指定应用补丁
SRC_URI += "file://patch/0004-XXX.patch;apply=no" #将补丁文件拷贝到${WORKDIR}目录下,但不应用补丁

​ 默认情况,构建系统会将file://指定带".diff"或".patch"的补丁文件应用到${S}目录,如果不想使用这个补丁,可以显示指定不应用。

注意:很多时候我们会在配方文件(.bb)中看见如下类似代码。

FILESPATH := "${THISDIR}/../../sources/${PN}:"

​ 这种强制更改FILESPATH变量默认值的方法是不正确的,正确做法是采用FILESEXTRAPATHS变量来扩展搜索目录,比如下面做法:

FILESEXTRAPATHS_prepend := " ${THISDIR}/../../sources/XXX:${THISDIR}/../../sources/YYY:" #同时扩展2个路径
FILESEXTRAPATHS_append := " ${THISDIR}/../EEE:" #尾部的分号必须存在

​ 额外说明一下,在.bbappend文件中只能使用FILESEXTRAPATHS变量。关于"_prepend""_append"操作符说明将在后续讲解。

THISDIR

​ bb或bbappend文件所在目录,位于配方(recipe)文件中。比如某个配方文件位于如下路径:

/work/open_source/openbmc/meta-aspeed/recipes-kernel/linux/linux-aspeed_git.bb

​ 那么在linux-aspeed_%.bbappend配方文件中的${THISDIR}变量值为也包含/work/open_source/openbmc/meta-aspeed/recipes-kernel/linux/

​ 注意,${THISDIR}变量值是配方文件所在目录,也就是说在bbappend文件中使用${THISDIR}变量,即包含bb文件所在目录,也包含bbappend文件所在目录,比如上面和下面两个目录都包含。

/work/open_source/openbmc/meta-ibm/meta-romulus/recipes-kernel/linux/linux-aspeed_%.bbappend

TMPDIR

​ 此变量是 OpenEmbedded 构建系统用于所有构建输出和中间文件(共享状态缓存除外)的基本目录,位于编译目标层的conf/local.conf.sample文件中(如有需要可在此文件中修改),这个文件将被解析到build/conf/local.conf文件中,默认情况下该变量指定的目录为build/tmp/

PACKAGE_ARCH

​ 包架构名,位于配方(recipe)文件中(一般不会在配方中自己指定)。查看示例:

~/work/bmc/build$ bitbake -e obmc-phosphor-image | grep ^PACKAGE_ARCH
PACKAGE_ARCH="4u_x201"
PACKAGE_ARCHS="all any noarch arm armv4 armv4t armv5 armv5t armv5e armv5te armv6 armv6t 4u_x201"

​ 其中obmc-phosphor-image为映像名(可使用包名),最终该映像就会生成于build\tmp\deploy\images\4u-x201目录中。

TARGET_OS

​ 指定目标的操作系统。对于基于 glibc 的系统(GNU C 库),该变量可以设置为“linux”,对于 musl libc 可以设置为“linux-musl”。对于 ARM/EABI 目标,存在“linux-gnueabi”“linux-musleabi”可能的值。查看示例:

~/work/bmc/build$ bitbake -e obmc-phosphor-image | grep ^TARGET_OS
TARGET_OS="linux-gnueabi"

PN

​ 用于构建包的配方名称或包的名称,该变量位于配方文件中(如有需要可在此文件中修改,一般会自动捕获配方名称)。例如,如果配方名为 expat_2.0.1.bb,则PN默认值为“expat”。这里需要注意一下,包名或配方名称中不能使用下划线_,在yocto下划线为版本分隔符。查看示例:

~/work/bmc/build$ bitbake -e obmc-phosphor-image | grep ^PN
PN="obmc-phosphor-image"

PV

​ 配方版本,该变量位于配方文件中(如有需要可在此文件中修改,一般会自动捕获配方版本)。例如,如果配方名为 expat_2.0.1.bb,则 PV 的默认值将为“2.0.1”。查看示例:

~/work/bmc/build$ bitbake -e obmc-phosphor-image | grep ^PV
PV="1.0"

PR

​ 配方的修订版本,该变量位于配方文件中(如有需要可在此文件中修改,一般需要手动指定)。此变量的默认值为“r0”,配方的后续修订通常具有值“r1”、“r2”等。当PV增加时,PR通常重置为“r0”。查看示例:

~/work/bmc/build$ bitbake -e obmc-phosphor-image | grep ^PR
PR="r0"

BP

​ 该变量的值基本配方名称和版本,但没有任何特殊配方名称后缀(即 -native、lib64- 等)。 BP 由组成为${BPN}-${PV},其查看示例为:

~/work/bmc/build$ bitbake -e obmc-phosphor-image | grep ^BP
BP="obmc-phosphor-image-1.0"

WORKDIR

​ OpenEmbedded 构建系统在其中构建配方的工作目录的路径名。该目录位于TMPDIR目录下,实际路径基于正在构建的配方和正在构建的系统,默认定义如下:

${TMPDIR}/work/${MULTIMACH_TARGET_SYS}/${PN}/${EXTENDPE}${PV}-${PR}
  • TMPDIR: 顶层构建输出目录
  • MULTIMACH_TARGET_SYS: 目标系统标识符,默认值为${PACKAGE_ARCH}${TARGET_VENDOR}-${TARGET_OS},示例值为4u_x201-openbmc-linux-gnueabiarmv6-openbmc-linux-gnueabi,详细请参阅https://www.yoctoproject.org/docs/2.7/ref-manual/ref-manual.html#var-MULTIMACH_TARGET_SYS
  • PN: 配方名称
  • EXTENDPE: 扩展前缀 ,如果PE未指定,EXTENDPE`则为空白,大多数食谱通常都是这种情况
  • PV: 配方版本
  • PR: 配方修改

BPN

​ 用于构建包的配方名称,它是PN变量的变种,去掉了常用的前缀和后缀,比如nativesdk-、-cross、-native,以及multilib的lib64-和lib32-。

~/work/byobmc/build$ bitbake -e obmc-phosphor-image | grep ^BPN
BPN="obmc-phosphor-image"

S

​ 解压后的配方源代码所在路径,该变量位于配方文件中(如有需要可在此文件中修改)。默认情况下,此目录为${WORKDIR}/${BPN}-${PV},如果源压缩包将代码提取到名为 ${BPN}-${PV} 以外的任何目录,或者如果源代码是从 SCM(例如 Git 或 Subversion)获取的,则必须在配方中设置 S,以便OpenEmbedded 构建系统知道在哪里可以找到解压的源代码。

​ 假设bb文件中指定源码来源于git,则在 do_fetch 期间,源码将被被克隆到 ${WORKDIR}/git目录中。由于此路径与S的默认值不同,所以必须专门设置,才能定位到源:

 SRC_URI = "git://path/to/repo.git"
 S = "${WORKDIR}/git"

总结:源码获取及处理阶段就是根据${SRC_URI}变量指定方式来获取源码存放到${WORKDIR}路径,若是压缩包则解压到S路径下,若有补丁文件则应用到S目录。

源码配置、源码编译及成果物安装

​ 源代码打好补丁后,bitbake 执行配置和编译源代码的任务。编译完成后,成果物文件将复制到保存区域(暂存)以准备打包:
在这里插入图片描述

​ 这个阶段主要包含四个任务,分别为do_prepare_recipe_sysrootdo_configuredo_compiledo_install

​ 是不是很好奇,突然跑出一个奇怪任务do_prepare_recipe_sysroot?虽然这个任务没有出现在上图中,但它却非常重要。

do_prepare_recipe_sysroot任务

​ 网上大多资料都简要带过这个任务,未能讲明白这个任务是做什么的,但想要了解yocto的配方文件共享机制就必须弄明白这个任务是做什么的!

do_prepare_recipe_sysrootdo_populate_sysrootstaging.bbclass类中关键任务,用于共享配方之间成果物!抛出一个问题思考一下,如果一个配方B需要使用配方A的成果物怎么办(比如头文件、动态/静态链接库、配置文件)?yocto为了解决这种问题,提供了一套配方成果物共享机制,该机制分为两阶段:

  • ​ 第一阶段在A配方构建时完成。A配方在构建时,需要在do_install 任务中将需要共享的文件安装至${D}目录,后续执行的do_populate_sysroot任务将自动拷贝${D}目录下部分子目录到${SYSROOT_DESTDIR},而${SYSROOT_DESTDIR}目录最终会放置到共享区(默认为build/tmp/sysroots-components)暂存,其他配方构建时就可以从共享区拷贝。

    ​ 那么,${D}目录下哪些子目录会被自动拷贝?自动拷贝的目录由三个变量指定,分别为SYSROOT_DIRS(目标设备需要保存的子目录)、SYSROOT_DIRS_BLACKLIST(目标设备不需要保存的子目录)、SYSROOT_DIRS_NATIVE(本机设备需要保存的目录),以SYSROOT_DIRS变量为例,其默认值为:

    SYSROOT_DIRS = " \
             ${includedir} \
             ${libdir} \
             ${base_libdir} \
             ${nonarch_base_libdir} \
             ${datadir} \
         "
    

    如果需要添加其他额外保存的目录,可以在配方文件中增加SYSROOT_DIRS += “YYY”

  • ​ 第二阶段在B配方构建时完成。B配方中添加DEPENDS += "A",便可使用A配方的成果物了。bitbake执行构建任务时会保证B配方的do_prepare_recipe_sysroot任务执行前,A配方的成果物已位于build/tmp/sysroots-components中。

    do_prepare_recipe_sysroot任务会在${WORKDIR}目录中创建两个sysroot目录并填充(所有依赖拷贝到其中),这两个目录名分别为"recipe-sysroot""recipe-sysroot-native"(本机),其中"recipe-sysroot"给目标设备使用,A配方生成的成果物就在里面,另一个"recipe-sysroot-native"是给本机设备使用的。

    ​ 不知道目标设备与本机设备的差异?简要讲解一下:假设要给arm平台编译flash固件,编译主机是x86平台,那么目标设备就是arm设备,本机设备就是x86编译主机。我们知道为arm设备编译代码需要使用交叉编译链(如arm-linux-gcc),编译链需要使用根文件系统下的各种库(或其他配方生成的头文件及库),因此便设置"recipe-sysroot"为编译器使用的文件系统。注意了,源码编译do_compile任务只是bitbake众多任务当中的一个,那其他任务也需要使用库或工具(如制作文件系统工具、压缩工具、cmake工具)怎么办?所以yocto将本机执行其他任务所需库或工具都放置于"recipe-sysroot-native"

    ​ 这里只介绍了构建依赖DEPENDS,但还有一种运行时依赖RDEPENDS,一般情况运行依赖会由构建系统自动添加,详情请参阅RDEPENDS

do_configure任务

​ 此任务用于完成编译源码前的配置,配置可以来自配方本身,也可以来自继承的类,一般情况我们都会使用autotools(配方中使用inherit autotools)、cmake类(配方中使用inherit cmake)或默认的make(不需要额外配置)。该任务运行时将当前工作目录设置为${B}(一般与${S}相同),该任务有个默认行为,即如果找到一个makefile (makefile, makefile,或GNUmakefile)并且CLEANBROKEN没有设置为“1”,则运行oe_runmake clean

​ 简单说明一下该任务怎么用:

  • ​ 如果你的软件包编译是基于autotools的,则可以使用EXTRA_OECONFPACKAGECONFIG_CONFARGS 变量添加其他配置选项,比如在配方文件中添加如下:

    EXTRA_OECONF += "--with-mib-modules="mib" \
                     --with-openssl=openssl \
                     --with-default-snmp-version="3" \
                     --with-logfile="/var/log/snmpd.log" \
                     --with-persistent-directory="/etc" \
                     --enable-privacy \
                     --enable-md5 \
                     --enable-des \
                     --prefiex=/xxx/yyy/ \
     "
    

    do_configure任务就如同手动执行./configure ${EXTRA_OECONF} ${PACKAGECONFIG_CONFARGS}一样。

  • ​ 如果你的软件包编译是基于cmake的,则可以使用EXTRA_OECMAKE变量添加其他配置选项,比如在软件包的配方文件添加如下:

    EXTRA_OECMAKE = " \
         -DBMCWEB_INSECURE_ENABLE_REDFISH_FW_TFTP_UPDATE=ON  -DBMCWEB_INSECURE_DISABLE_SSL=ON  \
         -DBMCWEB_ENABLE_DEBUG=ON -DBMCW   EB_ENABLE_LOGGING=ON \
    "
    

    do_configure任务就如同手动执行mkdir build/ && cd build/ && cmake ${EXTRA_OECMAKE}一样。

  • ​ 如果你的软件包编译是基于make的,则可以使用EXTRA_OEMAKE变量添加其他配置选项,比如在软件包的配方文件添加如下:

    EXTRA_OEMAKE = "INSTALL_PREFIX=${D} OTHERLDFLAGS='${LDFLAGS}' HOST_CPPFLAGS='${BUILD_CPPFLAGS}'"
    

    do_configure任务相当于只做默认行为(EXTRA_OEMAKE在执行make时才传入)。

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" #编译器链接选项

​ 注意,如果源码是在${WORKDIR}${BPN}-${PV} 以外的任何目录,需要显性指定S变量值,比如从本地直接获取源码xxx.c和Makefile,则需要在配方中添加S = "${WORKDIR}",这样编译任务才能正常进行。

do_install任务

​ 文件或成果物的安装任务。该任务会将编译目录${B}中需要打包的文件(放到目标设备中去的及其他配方依赖的)复制到保存区${D}中。注意:安装文件时不要把所有者和组ID设置错误,特别是使用cp命令时会保留原始文件的UID和GID,以下是推荐的安全方法:

使用install命令
使用cp命令时加上"--no-preserve=ownership"选项
使用tar命令时加上"--no-same-owner"选项

​ 还记得上面提过的依赖吗?这个任务就是把其他配方所需依赖安装到${D}目录,然后do_populate_sysroot任务才能去${D}目中拷贝。假设A模块执行do_install的一个简单示例:

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 #安装头文件
    install -m 0644 ${S}/api_xxx.h  ${D}${includedir}/api #安装头文件
}

​ 之后B模块在配方中添加如下:

DEPENDS += " A"
CFLAGS += " -I${WORKDIR}/recipe-sysroot/usr/include/api"

​ 这样B模块就可以使用A模块编译的动态库。

该大阶段涉及但未解释的变量有以下:

B

​ 包构建的编译目录,一般情况${B}${S}相同,即为${WORKDIR}/${BPN}-${PV}

D

​ 包构建成果物的安装目录,也称为目标目录。默认情况这个目录为${WORKDIR}/image

SYSROOT_DESTDIR

​ 指向包构建工作目录下的临时目录,其默认值为${WORKDIR}/sysroot-destdir

总结:源码配置、源码编译及成果物安装阶段就是引用依赖(如果有)完成源码配置、编译及成果物安装,安装的成果物可能是目标设备使用的,也可能是其他模块所需依赖。

包拆分处理

​ 在配置、编译和安装完成后,构建系统分析结果并将包拆分处理,比如将文件stripped后放入packages-split目录:
在这里插入图片描述

​ 该阶段分为三个任务,分别为do_packagedo_packagedatado_populate_sysroot

do_package、do_packagedata任务

do_packagedo_packagedata任务组合起来分析在${D}目录中找到的文件,并根据可用的包和文件将它们分成子集。分析处理过程包括以下内容:去除调试符号,查看包之间的共享库依赖关系,以及查看包之间的关系。

do_packagedata任务根据分析创建包元数据放置Package Feeds(即PKGDATA_DIR指定目录)中,这样构建系统就可以从拿到包生成最终的image。

do_populate_sysroot任务

do_populate_sysroot任务在之前已经介绍过。该任务将自动拷贝${D}目录下部分子目录到${SYSROOT_DESTDIR},并将${SYSROOT_DESTDIR}目录内容暂存至共享区(默认为build/tmp/sysroots-components)。自动拷贝的子目录由三个变量指定,分别为SYSROOT_DIRS(目标设备需要保存的子目录)、 SYSROOT_DIRS_BLACKLIST(目标设备不需要保存的子目录)、SYSROOT_DIRS_NATIVE(本机设备需要保存的目录),前面已经简要介绍过它们,详情请点入进官网参看。

该大阶段会涉及到以下变量:

PACKAGE_CLASSES

​ 用于指定构建系统在打包文件时使用何种包管理器,该变量位于编译目标层的conf/local.conf.sample文件中(如有需要可在此文件中修改),这个文件将被解析到build/conf/local.conf文件中,比如设置其值为PACKAGE_CLASSES ?= "package_rpm package_tar"

PKGD

​ 在将包拆分为单独的包之前,包的目标目录。

PKGDESTWORK

do_package任务用来保存包元数据的临时工作区(即pkgdata)。

PKGDEST

​ 拆分后的包的父目录(即packages-split)。

PKGDATA_DIR

​ 一个共享的全局状态目录,其中包含打包过程中生成的打包元数据。打包过程将元数据从PKGDESTWORK复制到PKGDATA_DIR区域,在那里元数据成为全局可用的。

STAGING_DIR_HOST

​ 要运行组件的系统的系统根路径(即recipe-sysroot),也就是当前配方源码编译时的根文件系统,里面包含配方所需依赖及交叉编译器所需依赖。

STAGING_DIR_NATIVE

​ 为构建主机构建组件时使用的系统根路径(即recipe-sysroot-native)。

STAGING_DIR_TARGET

​ 当构建在系统上执行的组件并为另一台机器生成代码(例如cross-canadian recipes)时使用的 sysroot 路径,一般与STAGING_DIR_HOST一样。

FILES

​ 用于指定包(模块)安装在${D}目录中哪些成果物要打包,该变量位于配方文件中(如有需要可在此文件中修改)。简单来说就是在do_install任务中安装在${D}目录下的文件不会都打包,以rsa模块为例该变量的默认值为:

FILES_rsa="/usr/bin/* /usr/sbin/* /usr/libexec/* /usr/lib/lib*.so.*             /etc /com /var             /bin/* /sbin/*             /lib/*.so.*             /lib/udev /usr/lib/udev             /lib/udev /usr/lib/udev             /usr/share/hikrsa /usr/lib/hikrsa/*             /usr/share/pixmaps /usr/share/applications             /usr/share/idl /usr/share/omf /usr/share/sounds             /usr/lib/bonobo/servers"

​ 也就是说,只要成果物安装在上面这些目录下的都会参与打包,当然如果不放心或需要额外增加文件,可以在配方文件中显性指定:

FILES_${PN} += " \
        ${sbindir}/rsaverify \
" #${sbindir}默认为/usr/sbin/

总结:包拆分处理阶段就是根据conf配置将${D}目录中成果物打包放置于Package Feeds 区域,同时生成包元数据,最后将其他配方可能用到的文件放置于文件共享区(为其他配方提供依赖)。

image生成

​ 注意,这个阶段在一般包(模块)编译过程中不存在!!!可通过bitbake -c listtasks XXX(包名或固件名)命令查看编译任务列表。

​ 一旦软件包被拆分并存储在 Package Feeds 区域中,构建系统将使用 bitbake 生成根文件系统映像(image):
在这里插入图片描述

​ 该阶段涉及两个任务,分别为do_rootfsdo_image

do_rootfs任务

​ 该任务将创建目标设备的根文件系统(将需要打包至目标设备的程序、库、文件等都放置到根文件系统中),这个根文件系统最终打包到image中。do_rootfs任务会通过ROOTFS_POSTPROCESS_COMMAND来优化文件大小(如mklibs过程优化了库的大小,同时prelink优化了共享库的动态链接以减少可执行文件的启动时间),ROOTFS_POSTPROCESS_COMMAND如下:

ROOTFS_POSTPROCESS_COMMAND() {
write_package_manifest; license_create_manifest;   ssh_allow_empty_password;  ssh_allow_root_login;  postinst_enable_logging;
  rootfs_update_timestamp ;   write_image_test_data ;  set_systemd_default_target; systemd_create_users; empty_var_volatile;
remove_etc_version ;  set_user_group; sort_passwd; rootfs_reproducible;
}

​ 创建的文件系统所在位置由IMAGE_ROOTFS变量指定,查看示例:

~/work/bmc$ bitbake -e obmc-phosphor-image | grep ^IMAGE_ROOTFS
IMAGE_ROOTFS="~/work/bmc/build/tmp/work/4u_x201-openbmc-linux-gnueabi/obmc-phosphor-image/1.0-r0/rootfs"

​ 如果我们修改了某个程序,但又不想重新烧写整个固件,那就去这个目录下找到程序,再通过TFTP方式(或NFS直接挂载)下载到目标是设备调试即可。

do_image任务

do_image 任务会通过 IMAGE_PREPROCESS_COMMAND 对image进行预处理,主要是优化image大小,IMAGE_PREPROCESS_COMMAND 如下:

IMAGE_PREPROCESS_COMMAND() {
 mklibs_optimize_image;  prelink_setup; prelink_image;  reproducible_final_image_task;
}

​ 构建系统do_image根据需要动态生成支持的 do_image_* 任务,生成的任务类型取决于IMAGE_FSTYPES变量。do_image_* 任务将所有内容转换为一个image文件或一组image文件,并且可以压缩根文件系统image大小,以减小最终烧写到目标设备的image整体大小。用于根文件系统的格式取决于 IMAGE_FSTYPES变量,压缩取决于格式是否支持压缩。

image生成完成后执行最后一个任务do_image_complete,该任务将通过IMAGE_POSTPROCESS_COMMAND完成image的后续处理,默认情况IMAGE_POSTPROCESS_COMMAND为空,查看示例:

~/work/bmc$ bitbake -e obmc-phosphor-image | grep ^IMAGE_POSTPROCESS_COMMAND
IMAGE_POSTPROCESS_COMMAND=""

该大阶段涉及变量如下:

IMAGE_INSTALL

​ 该变量指明Package Feeds 区域安装的基本软件包集中,哪些包(模块)最终要打包到image,该变量一般位于编译目标层的conf/local.conf.sample文件中(如有需要可在此文件中修改),这个文件将被解析到build/conf/layer.conf文件中。注意与FILES差异,FILES是指明软件包内部哪些文件需要参与打包,而IMAGE_INSTALL是指明哪个软件包需要参与打包。

​ 一个简单示例:

IMAGE_INSTALL_append += ”rsa"

PACKAGE_EXCLUDE

​ 指定不应安装到image中的包。

IMAGE_FEATURES

​ 指定要包含在图像中的特征,大多数这些功能映射到其他安装包(未能弄明白具体作用)。

IMAGE_LINGUAS

​ 确定安装附加语言支持包的语言,该变量一般位于编译目标层的conf/local.conf.sample文件中(如有需要可在此文件中修改),这个文件将被解析到build/conf/layer.conf文件中。默认情况下为:

~/work/bmc$ bitbake -e rsa | grep ^IMAGE_LINGUAS
IMAGE_LINGUAS="en-us en-gb"

PACKAGE_INSTALL

​ 传递给包管理器以安装到映像中的包的最终列表。

DEPLOY_DIR

​ 最终image和SDK输出的目录,默认值为build/tmp/deploy/

总结:image生成生成阶段就是创建目标设备的根文件系统,并将需要打包至目标设备的程序、库、文件等都放置到根文件系统中,然后对文件和整个文件系统进行优化压缩,最终生成image。

简单示例

api.bb的配方为例,其内容如下:

SUMMARY = "This is an example"
SECTION = "Examples" 
HOMEPAGE = "http://www.xxx.com.cn/"
PR = "r1" #修订版本
#PV = "1.0" #这里不用指定配方版本,因为配方api.bb本身就不带版本,所以默认PV就是1.0

LICENSE = "MIT" #许可证类型
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" #校验许可证

FILESPATH := "${THISDIR}/../../sources/${PN}:" #本地文件搜索路径,PN默认为配方名称,即api

#此配方所依赖的其他配方
DEPENDS += "audit"
DEPENDS += "phosphor-ipmi-host"

#由于源码下载的目录是${WORKDIR},而非${WORKDIR}/${BPN}-${PV},因此需设置S,否则编译失败
S = "${WORKDIR}"
#指定需要下载的文件
SRC_URI += "\
                        file://Makefile \
                        file://make.libs \
                        file://api_common.h \
                        file://api_common.c \
                        file://api_ethernet.c \
                        file://api_ethernet.h \
                        "
#增加额外文件              
SRC_URI += " \
            file://api_systems.c \
            file://api_systems.h \
        "

#追加额外路径下的文件,还记得之前提过吗?尽量不要直接改变FILESPATH变量的值,所以下面方法虽然可用,但不是合理的,正确做法是使用FILESEXTRAPATHS变量
FILESPATH_append := "${THISDIR}/../../../meta-common/sources/host-ipmid/ipmi/:" #换成FILESEXTRAPATHS_append
SRC_URI_append = " \
            file://sharememory.c \
"

#传入参数
TARGET_CC_ARCH += "${LDFLAGS}"
EXTRA_OEMAKE = " 'RECIPE_SYSROOT=${RECIPE_SYSROOT}' "
CFLAGS_prepend = "-I${WORKDIR}/recipe-sysroot/usr/include/audit "

#这里注意没有出现do_configure、do_compile任务,故默认执行构建系统的do_configure、do_compile任务
#在本配方基于make构建包,所以do_configure任务相当于啥也没干,do_compile任务则执行oe_runmake并传入参数

#重载do_install任务,即构建系统原始的do_install任务不再执行,转而执行以下do_install任务
do_install() {
        oe_runmake DESTDIR=${D}${libdir} install #执行Makefile文件中的安装任务,并传入安装目录
        install -m 0644 -d ${D}${includedir}/api
        install -m 0644 ${S}/api_common.h  ${D}${includedir}/api
        install -m 0644 ${S}/api_common.c  ${D}${includedir}/api #不仅可以安装头文件,c文件也可以给其他模块使用,但这不是合理的方式
        install -m 0644 ${S}/api_ethernet.h ${D}${includedir}/api
    	install -m 0644 ${S}/api_systems.h ${D}${includedir}/api
}

#FILES变量默认会加上${includedir}和${libdir}目录,所以下面语句可以不要
#FILES_${PN} += "${includedir}/api"
#FILES_${PN} += "${libdir}"

标签:yocto,do,文件,流程,bitbake,任务,image,配方,目录
来源: https://blog.csdn.net/zz2633105/article/details/122336873

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有