34 使用 buildhistory 维护构建输出质量

许多因素都会影响构建质量。例如,将配方升级为使用新版上游软件包,或试用 新的配置选项,都可能产生直到后来才察觉的细微变化。假设配方改用了新版上游 软件包,而新版本增加了对另一个库的可选依赖,并自动检测该库。如果软件构建 时这个库已经构建完成,软件就会链接它,并将库随新软件一起带入镜像,即使你 并不希望包含该库。

buildhistory 类有助于维护构建输出质量,可突出显示意外 且可能不需要的输出变化。启用构建历史后,它记录各软件包和镜像的内容信息, 并提交到本地 Git 仓库,供你检查。

本节其余部分介绍:

34 启用和禁用构建历史

构建历史默认禁用。要启用它,在 build/conf/local.conf 等 configuration file 中添加以下 INHERIT 语句,并将 BUILDHISTORY_COMMIT 设为 "1":

INHERIT += "buildhistory"
BUILDHISTORY_COMMIT = "1"

按上述方式启用后,OpenEmbedded 构建系统会收集构建输出信息,并以单个提交 写入本地 Git 仓库。

备注

启用构建历史会略微增加构建时间,尤其是镜像构建时间,也会增加构建期间 的磁盘占用。

从 configuration file 中移除上述语句即可禁用构建历史。

34 理解构建历史的内容

构建历史信息保存在 Build Directory 的 ${TOPDIR}/buildhistory 中,其位置由 BUILDHISTORY_DIR 定义。以下为简化的目录示例:

../_images/buildhistory.png

顶层的 metadata-revs 文件列出生成此次构建时各启用层所在仓库的修订版本。 其他数据分别存放在 packages、images 和 sdk 目录中,内容如下。

34 构建历史中的软件包信息

每个软件包的历史都包含文本文件,以名称和值的形式记录信息。例如, buildhistory/packages/i586-poky-linux/busybox/busybox/latest 包含:

PV = 1.22.1
PR = r32
RPROVIDES =
RDEPENDS = glibc (>= 2.20) update-alternatives-opkg
RRECOMMENDS = busybox-syslog busybox-udhcpc update-rc.d
PKGSIZE = 540168
FILES = /usr/bin/* /usr/sbin/* /usr/lib/busybox/* /usr/lib/lib*.so.* \
   /etc /com /var /bin/* /sbin/* /lib/*.so.* /lib/udev/rules.d \
   /usr/lib/udev/rules.d /usr/share/busybox /usr/lib/busybox/* \
   /usr/share/pixmaps /usr/share/applications /usr/share/idl \
   /usr/share/omf /usr/share/sounds /usr/lib/bonobo/servers
FILELIST = /bin/busybox /bin/busybox.nosuid /bin/busybox.suid /bin/sh \
   /etc/busybox.links.nosuid /etc/busybox.links.suid

大多数名称和值对应生成软件包时使用的变量。例外是 FILELIST,表示软件包 实际文件列表;以及 PKGSIZE,表示包中文件总大小,单位为字节。

另有对应软件包来源配方的文件,例如 buildhistory/packages/i586-poky-linux/busybox/latest:

PV = 1.22.1
PR = r32
DEPENDS = initscripts kern-tools-native update-rc.d-native \
   virtual/i586-poky-linux-compilerlibs virtual/i586-poky-linux-gcc \
   virtual/libc virtual/update-alternatives
PACKAGES = busybox-ptest busybox-httpd busybox-udhcpd busybox-udhcpc \
   busybox-syslog busybox-mdev busybox-hwclock busybox-dbg \
   busybox-staticdev busybox-dev busybox-doc busybox-locale busybox

对于从 Git 等版本控制系统获取的配方,还会有文件列出配方指定的源码修订版本 以及构建实际使用的版本。SRCREV 设为 ${AUTOREV} 时,两者 可能不同。以下以 buildhistory/packages/qemux86-poky-linux/linux-yocto/latest_srcrev 为例:

# SRCREV_machine = "38cd560d5022ed2dbd1ab0dca9642e47c98a0aa1"
SRCREV_machine = "38cd560d5022ed2dbd1ab0dca9642e47c98a0aa1"
# SRCREV_meta = "a227f20eff056e511d504b2e490f3774ab260d6f"
SRCREV_meta ="a227f20eff056e511d504b2e490f3774ab260d6f"

使用 buildhistory-collect-srcrevs 命令的 -a 选项,可以收集构建历史 保存的 SRCREV 值,并以适合全局配置的格式输出,例如用于发行版包含 configuration file,将浮动的 AUTOREV 固定为一组修订版本。 示例输出如下:

$ buildhistory-collect-srcrevs -a
# all-poky-linux
SRCREV:pn-ca-certificates = "07de54fdcc5806bde549e1edf60738c6bccf50e8"
SRCREV:pn-update-rc.d = "8636cf478d426b568c1be11dbd9346f67e03adac"
# core2-64-poky-linux
SRCREV:pn-binutils = "87d4632d36323091e731eb07b8aa65f90293da66"
SRCREV:pn-btrfs-tools = "8ad326b2f28c044cb6ed9016d7c3285e23b673c8"
SRCREV_bzip2-tests:pn-bzip2 = "f9061c030a25de5b6829e1abf373057309c734c0"
SRCREV:pn-e2fsprogs = "02540dedd3ddc52c6ae8aaa8a95ce75c3f8be1c0"
SRCREV:pn-file = "504206e53a89fd6eed71aeaf878aa3512418eab1"
SRCREV_glibc:pn-glibc = "24962427071fa532c3c48c918e9d64d719cc8a6c"
SRCREV:pn-gnome-desktop-testing = "e346cd4ed2e2102c9b195b614f3c642d23f5f6e7"
SRCREV:pn-init-system-helpers = "dbd9197569c0935029acd5c9b02b84c68fd937ee"
SRCREV:pn-kmod = "b6ecfc916a17eab8f93be5b09f4e4f845aabd3d1"
SRCREV:pn-libnsl2 = "82245c0c58add79a8e34ab0917358217a70e5100"
SRCREV:pn-libseccomp = "57357d2741a3b3d3e8425889a6b79a130e0fa2f3"
SRCREV:pn-libxcrypt = "50cf2b6dd4fdf04309445f2eec8de7051d953abf"
SRCREV:pn-ncurses = "51d0fd9cc3edb975f04224f29f777f8f448e8ced"
SRCREV:pn-procps = "19a508ea121c0c4ac6d0224575a036de745eaaf8"
SRCREV:pn-psmisc = "5fab6b7ab385080f1db725d6803136ec1841a15f"
SRCREV:pn-ptest-runner = "bcb82804daa8f725b6add259dcef2067e61a75aa"
SRCREV:pn-shared-mime-info = "18e558fa1c8b90b86757ade09a4ba4d6a6cf8f70"
SRCREV:pn-zstd = "e47e674cd09583ff0503f0f6defd6d23d8b718d3"
# qemux86_64-poky-linux
SRCREV_machine:pn-linux-yocto = "20301aeb1a64164b72bc72af58802b315e025c9c"
SRCREV_meta:pn-linux-yocto = "2d38a472b21ae343707c8bd64ac68a9eaca066a0"
# x86_64-linux
SRCREV:pn-binutils-cross-x86_64 = "87d4632d36323091e731eb07b8aa65f90293da66"
SRCREV_glibc:pn-cross-localedef-native = "24962427071fa532c3c48c918e9d64d719cc8a6c"
SRCREV_localedef:pn-cross-localedef-native = "794da69788cbf9bf57b59a852f9f11307663fa87"
SRCREV:pn-debianutils-native = "de14223e5bffe15e374a441302c528ffc1cbed57"
SRCREV:pn-libmodulemd-native = "ee80309bc766d781a144e6879419b29f444d94eb"
SRCREV:pn-virglrenderer-native = "363915595e05fb252e70d6514be2f0c0b5ca312b"
SRCREV:pn-zstd-native = "e47e674cd09583ff0503f0f6defd6d23d8b718d3"

备注

使用 buildhistory-collect-srcrevs 时请注意:

  • 默认只报告未硬编码的 SRCREV 值,通常是使用 AUTOREV 的情况。使用 -a 可查看所有 SRCREV 值。

  • 如果构建配置其他位置应用了覆盖,输出语句可能不起作用。可用 -f 为每行输出添加 forcevariable 覆盖,以绕过此限制。

  • 脚本对多机器构建进行特殊处理,并在每组值前添加注释,指明所属三元组, 如前文的 i586-poky-linux。

34 构建历史中的镜像信息

每个镜像生成以下文件:

  • image-files: 保存根文件系统中特定文件的目录,由 BUILDHISTORY_IMAGE_FILES 指定。

  • build-id.txt: 易于阅读的构建配置和元数据源码修订信息,包含 BitBake 输出的完整构建头部。

  • *.dot: 与 graphviz 兼容的镜像依赖图。

  • files-in-image.txt: 镜像文件列表,包含权限、所有者、组、大小及符号 链接信息。

  • image-info.txt: 以名称和值的形式记录镜像信息的文本文件,示例见下文。

  • installed-package-names.txt: 仅包含名称的已安装软件包列表。

  • installed-package-sizes.txt: 按大小排序的已安装软件包列表。

  • installed-packages.txt: 包含完整软件包文件名的已安装软件包列表。

备注

即使最终镜像禁用了包管理,仍然可以收集并生成已安装软件包信息。

image-info.txt 的示例如下:

DISTRO = poky
DISTRO_VERSION = 3.4+snapshot-a0245d7be08f3d24ea1875e9f8872aa6bbff93be
USER_CLASSES = buildstats
IMAGE_CLASSES = qemuboot qemuboot license_image
IMAGE_FEATURES = allow-empty-password empty-root-password allow-root-login post-install-logging
IMAGE_LINGUAS =
IMAGE_INSTALL = packagegroup-core-boot speex speexdsp
BAD_RECOMMENDATIONS =
NO_RECOMMENDATIONS =
PACKAGE_EXCLUDE =
ROOTFS_POSTPROCESS_COMMAND = ssh_allow_empty_password  ssh_allow_root_login  postinst_enable_logging  rootfs_update_timestamp   write_image_test_data   empty_var_volatile   sort_passwd rootfs_reproducible
IMAGE_POSTPROCESS_COMMAND =  buildhistory_get_imageinfo
IMAGESIZE = 9265

除 IMAGESIZE 表示镜像中文件总大小(KB)外,其他名称和值都对应可能 影响镜像内容的变量。这些信息常有助于判断软件包或文件列表为何发生变化。

34 仅使用构建历史收集镜像信息

构建历史生成镜像信息及依赖图,可帮助理解某项内容为何进入镜像。如果只关心 这些信息,不需要特定软件包或 SDK 信息,可以在 configuration file 中添加以下内容,只写镜像信息而不保留历史:

INHERIT += "buildhistory"
BUILDHISTORY_COMMIT = "0"
BUILDHISTORY_FEATURES = "image"

此处将 BUILDHISTORY_FEATURES 设置为仅使用 image 功能。

34 构建历史中的 SDK 信息

构建历史对 SDK 内容收集的信息与镜像类似,例如执行 bitbake -c populate_sdk imagename 时收集的信息。生成可扩展 SDK 和标准 SDK 时,收集内容又有所不同。

SDK 会生成以下文件:

  • files-in-sdk.txt: SDK 文件列表,包含权限、所有者、组、大小和符号 链接信息,涵盖 SDK 的主机和目标两部分。

  • sdk-info.txt: 以名称和值的形式记录 SDK 信息的文本文件,见下方示例。

  • sstate-task-sizes.txt: 以名称和值的形式记录任务组大小,例如全部 do_populate_sysroot 任务的总大小。仅生成可扩展 SDK 时存在。

  • sstate-package-sizes.txt: 以名称和值的形式记录 SDK 共享状态软件包及 大小。仅生成可扩展 SDK 时存在。

  • sdk-files: 保存 BUILDHISTORY_SDK_FILES 指定且存在于输出中的文件 副本。BUILDHISTORY_SDK_FILES 默认值专用于可扩展 SDK,但也可以修改 它以收集标准 SDK 中的指定文件。

    默认文件为 build/conf/local.conf、 build/conf/bblayers.conf、build/conf/auto.conf、 conf/locked-sigs.inc 和 conf/devtool.conf。对于可扩展 SDK,这些 文件会复制到 sdk-files 目录。

  • host 和 target 目录分别记录 SDK 中运行于主机和目标的部分, 各自包含以下信息:

    备注

    生成可扩展 SDK 时,下列文件大多为空,因为它不像标准 SDK 那样从 软件包组装而来。

    • depends.dot: 与 graphviz 兼容的 SDK 依赖图。

    • installed-package-names.txt: 仅包含名称的已安装软件包列表。

    • installed-package-sizes.txt: 按大小排序的已安装软件包列表。

    • installed-packages.txt: 包含完整软件包文件名的已安装软件包列表。

sdk-info.txt 的示例如下:

DISTRO = poky
DISTRO_VERSION = 1.3+snapshot-20130327
SDK_NAME = poky-glibc-i686-arm
SDK_VERSION = 1.3+snapshot
SDKMACHINE =
SDKIMAGE_FEATURES = dev-pkgs dbg-pkgs
BAD_RECOMMENDATIONS =
SDKSIZE = 352712

除 SDKSIZE 表示 SDK 中文件总大小(KB)外,其余名称和值对应可能影响 SDK 内容的变量。这些信息常有助于判断软件包或文件列表变化的原因。

34 检查构建历史信息

可以通过命令行或 Web 界面检查构建历史输出。

若 BUILDHISTORY_COMMIT = "1",可使用任意能查看仓库历史的 Git 命令检查变化,例如:

$ git log -p

不过,这种方式也会显示不重要的变化,例如软件包大小只变化几字节。

buildhistory-diff 命令行工具会查询 Git 仓库,仅以易读形式输出可能 重要的差异,例如:

$ bitbake-builds/layers/openembedded-core/scripts/buildhistory-diff . HEAD^
Changes to images/qemux86_64/glibc/core-image-minimal (files-in-image.txt):
   /etc/anotherpkg.conf was added
   /sbin/anotherpkg was added
   * (installed-package-names.txt):
   *   anotherpkg was added
Changes to images/qemux86_64/glibc/core-image-minimal (installed-package-names.txt):
   anotherpkg was added
packages/qemux86_64-poky-linux/v86d: PACKAGES: added "v86d-extras"
   * PR changed from "r0" to "r1"
   * PV changed from "0.1.10" to "0.1.12"
packages/qemux86_64-poky-linux/v86d/v86d: PKGSIZE changed from 110579 to 144381 (+30%)
   * PR changed from "r0" to "r1"
   * PV changed from "0.1.10" to "0.1.12"

备注

buildhistory-diff 需要 GitPython 软件包。请用 Pip3 安装:

$ pip3 install GitPython --user

也可以使用发行版包管理器安装 python3-git,例如 apt、dnf 或 zipper。

要通过 Web 界面查看构建历史变化,请遵循 此处 的 README 文件说明。

以下是界面截图示例:

../_images/buildhistory-web.png