18 使用库

库是系统不可或缺的组成部分。本节介绍构建系统时处理库的一些常用方法:

18 包含静态库文件

如果正在构建的库支持静态链接,可以控制构建产物包含哪些静态库文件 (*.a 文件)。

meta/conf/bitbake.conf 配置文件中的 PACKAGES 和 FILES:* 变量定义了 do_install 任务安装的文件 如何打包。默认情况下,PACKAGES 包含代表全部静态库文件的 ${PN}-staticdev。

备注

某些较早的 Yocto Project 版本通过 ${PN}-dev 定义静态库文件。

以下 BitBake 配置文件片段展示了静态库文件的定义方式:

PACKAGES = "${PN}-src ${PN}-dbg ${PN}-staticdev ${PN}-dev ${PN}-doc ${PN}-locale ${PACKAGE_BEFORE_PN} ${PN}"

FILES:${PN}-staticdev = "${libdir}/*.a ${base_libdir}/*.a ${libdir}/${BPN}/*.a"
SECTION:${PN}-staticdev = "devel"
RDEPENDS:${PN}-staticdev = "${PN}-dev (= ${EXTENDPKGV})"

18 将多个版本的库文件组合到同一镜像

构建系统可以构建采用不同目标优化或架构格式的库,并将它们组合到同一系统镜像。 可根据具体用途,让镜像中的不同二进制程序链接到不同库。这项功能称为 "Multilib"。

例如,系统大部分组件以 32 位模式编译并使用 32 位库,但数据库引擎之类的大型 程序需要以 64 位运行并使用 64 位库。Multilib 可以兼顾 32 位和 64 位库的优势。

虽然 Multilib 最常用于 32 位与 64 位的差异,但构建系统的实现方式也支持不同 目标优化。可以将一些二进制程序编译为使用一组库,另一些使用另一组库;这些库 可以在架构、编译器选项或其他优化上有所不同。

OpenEmbedded-Core (OE-Core) 的 meta-skeleton 层中有几个示例:

18 准备使用 Multilib

Multilib 由用户的具体需求驱动,因此没有一种开箱即用的配置能满足所有需求。

启用 Multilib 前,首先应确保配方已扩展为支持多个库。许多标准配方已经完成 扩展。可以查看 OpenEmbedded-Core (OE-Core) 中的 meta/conf/multilib.conf,了解如何通过 BBCLASSEXTEND 实现。 最终所有配方都会支持,此列表也就不再需要。

多数情况下,Multilib 类扩展会自动将软件包 名称从 ${PN} 扩展为 ${MLPREFIX}${PN},其中 MLPREFIX 指定 具体的 multilib,例如 "lib32-" 或 "lib64-"。系统会自动扩展 DEPENDS、RDEPENDS、RPROVIDES、RRECOMMENDS、 PACKAGES 和 PACKAGES_DYNAMIC 等标准变量。如果扩展配方中 手写的代码,可以使用 ${MLPREFIX} 确保相关名称正确扩展。

18 使用 Multilib

准备好配方后,需要定义实际构建的多库组合。可在 Build Directory 中的 build/conf/local.conf 配置文件,或自定义机器的 configuration file 中设置。例如:

MACHINE = "qemux86-64"
require conf/multilib.conf
MULTILIBS = "multilib:lib32"
DEFAULTTUNE:virtclass-multilib-lib32 = "x86"
IMAGE_INSTALL:append = " lib32-glib-2.0"

本例在普通目标软件包之外启用名为 lib32 的额外库变体,并为这些变体使用 "x86" 调优。此调优的更多信息见 meta/conf/machine/include/ia32/arch-ia32.inc。

然后,示例将 lib32-glib-2.0 包含到所有镜像中,演示了一种加入多库依赖的 方法。可以正常构建镜像来包含此依赖,例如:

$ bitbake core-image-sato

也可以单独构建 Multilib 软件包:

$ bitbake lib32-glib-2.0

18 其他实现细节

实现细节分为通用部分和软件包管理系统特定部分。以下细节与包管理系统无关:

  • Multilib 使用的类扩展代码通常约定:PACKAGES 中含 ${PN} 的软件包名称都以 ${PN} 开头。如果没有遵循此约定,将 ${PN} 放在名称中间或末尾,就会出现问题。

  • Multilib 下的 TARGET_VENDOR 会扩展为 "-vendormlmultilib", 例如 Poky 的 "lib32" 变体为 "-pokymllib32"。这种略显生硬的缩写是因为 供应商字符串中的 "-" 会破坏 Autoconf 的 config.sub,其他分隔符 也各有问题。

RPM 软件包管理系统的实现细节如下:

  • 为 Multilib 软件包定义独立架构,并在 Build Directory 的 tmp/deploy/rpm 下创建独立部署目录。例如,qemux86-64 镜像中的 lib32 可能涉及 "all"、"qemux86_64"、"lib32:qemux86_64" 和 "lib32:x86" 架构。

  • RPM 打包时会从 ${PN} 去掉 ${MLPREFIX}。在 qemux86-64 系统中, 普通 RPM 和 Multilib RPM 的名称分别类似于 bash-4.1-r2.x86_64.rpm 和 bash-4.1.r2.lib32_x86.rpm。

  • 安装 Multilib 镜像时,RPM 后端先安装基础镜像,再安装 Multilib 库。

  • 构建系统依靠 RPM 处理两个或更多 Multilib 软件包中的相同文件。

IPK 软件包管理系统的实现细节如下:

  • IPK 打包时不会从 ${PN} 去掉 ${MLPREFIX}。在 qemux86-64 系统中,普通软件包和 Multilib IPK 软件包的名称分别类似于 bash_4.1-r2.x86_64.ipk 和 lib32-bash_4.1-rw:x86.ipk。

  • IPK 部署目录不会因 ${MLPREFIX} 而改变。由于 ${PN} 不同,启用 和未启用 Multilib 的软件包可以放在同一目录。

  • IPK 使用特定文件比较、覆盖等规则,为 Multilib 安装定义合理性检查。

18 安装同一库的多个版本

有时需要在同一系统中同时安装并使用同一个库的多个版本,通常是因为库 API 发生变化,而多个软件分别依赖不同版本。为满足这种需求,可以并行安装多个版本。

只要库正确使用版本机制,过程就很直接:为各版本创建独立且名称适当的配方, 在名称的 PN 部分包含区分版本的内容,例如主版本号。不再由单个配方 加载库的某个版本(例如 clutter),而是提供多个配方生成所需的不同版本。 例如,以下两个配方允许两个 clutter 库版本在同一系统共存:

clutter-1.6_1.6.20.bb
clutter-1.8_1.8.4.bb

如果其他配方依赖指定库,需要用 DEPENDS 建立依赖。延续上例,若配方 需要 clutter 1.8 版本,在配方中使用:

DEPENDS = "clutter-1.8"