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"