19 使用预构建库
19 简介
有些库供应商不发布源码,只提供预构建二进制文件。构建共享库时应附加版本 信息,背景知识见 这篇文章, 但有时供应商没有这样做。
带版本的库必须满足两个条件:
文件名附加版本号,例如
libfoo.so.1.2.3。库的 ELF 标签
SONAME设为库的主版本,例如libfoo.so.1。 可运行readelf -d filename | grep SONAME检查。
本节介绍如何处理带版本和不带版本的预构建库。
19 带版本的库
本例使用 FT4222H USB I/O 芯片的预构建库。供应商为多个目标架构变体构建了 库,并按以下结构打包:
├── build-arm-hisiv300
│ └── libft4222.so.1.4.4.44
├── build-arm-v5-sf
│ └── libft4222.so.1.4.4.44
├── build-arm-v6-hf
│ └── libft4222.so.1.4.4.44
├── build-arm-v7-hf
│ └── libft4222.so.1.4.4.44
├── build-arm-v8
│ └── libft4222.so.1.4.4.44
├── build-i386
│ └── libft4222.so.1.4.4.44
├── build-i486
│ └── libft4222.so.1.4.4.44
├── build-mips-eglibc-hf
│ └── libft4222.so.1.4.4.44
├── build-pentium
│ └── libft4222.so.1.4.4.44
├── build-x86_64
│ └── libft4222.so.1.4.4.44
├── examples
│ ├── get-version.c
│ ├── i2cm.c
│ ├── spim.c
│ └── spis.c
├── ftd2xx.h
├── install4222.sh
├── libft4222.h
├── ReadMe.txt
└── WinTypes.h
编写配方以在系统中使用此类库时:
供应商可能采用专有许可证,因此应在配方中设置 LICENSE_FLAGS。
供应商提供包含库的归档包,应相应设置 SRC_URI。
设置 COMPATIBLE_HOST,避免在不受支持的架构上使用配方。以下示例 只支持
x86架构的 32 位和 64 位变体。供应商提供的是带版本的库,因此可以使用 utils 中的
oe_soinstall安装共享库并创建符号链接。若库不带版本,应遵循下一节。供应商使用的 LDFLAGS 很可能与当前 Yocto Project 构建不同,应将
ldflags加入 INSANE_SKIP,禁用对应检查。供应商通常提供不含调试符号的发行构建。应通过下面的
INHIBIT_标志, 禁止打包任务剥离符号并将其放入独立调试软件包,避免出现错误。
完整配方如下:
SUMMARY = "FTDI FT4222H Library"
SECTION = "libs"
LICENSE_FLAGS = "ftdi"
LICENSE = "CLOSED"
COMPATIBLE_HOST = "(i.86|x86_64).*-linux"
# Sources available in a .tgz file in .zip archive
# at https://ftdichip.com/wp-content/uploads/2021/01/libft4222-linux-1.4.4.44.zip
# Found on https://ftdichip.com/software-examples/ft4222h-software-examples/
# Since dealing with this particular type of archive is out of topic here,
# we use a local link.
SRC_URI = "file://libft4222-linux-${PV}.tgz"
S = "${UNPACKDIR}"
ARCH_DIR:x86-64 = "build-x86_64"
ARCH_DIR:i586 = "build-i386"
ARCH_DIR:i686 = "build-i386"
INSANE_SKIP:${PN} = "ldflags"
INHIBIT_PACKAGE_STRIP = "1"
INHIBIT_SYSROOT_STRIP = "1"
INHIBIT_PACKAGE_DEBUG_SPLIT = "1"
do_install () {
install -m 0755 -d ${D}${libdir}
oe_soinstall ${S}/${ARCH_DIR}/libft4222.so.${PV} ${D}${libdir}
install -d ${D}${includedir}
install -m 0755 ${S}/*.h ${D}${includedir}
}
如果预编译二进制文件不是静态链接,且依赖其他库,将这些库加入 DEPENDS 后,构建系统就可以检查链接关系,并自动添加适当的 RDEPENDS。
19 不带版本的库
19 背景知识
Linux 系统中的库通常带有版本,便于同时安装同一库的多个版本,从而简化
升级并支持旧软件。例如,实际库为 libfoo.so.1.2,符号链接 libfoo.so.1
和 libfoo.so 均指向它。将二进制程序链接到库时,通常提供不带版本的
名称,例如向链接器传递 -lfoo;但链接器会沿符号链接,实际链接到带版本
的文件名。不带版本的符号链接仅在开发时使用,因此它与头文件一起放入开发
软件包 ${PN}-dev,实际库和带版本的符号链接则放入 ${PN}。带版本
的库远比不带版本的库常见,所以默认打包规则假定库带版本。
19 Yocto 库打包概述
因此,打包不带版本的库需要调整配方。默认情况下,libfoo.so 会进入
${PN}-dev,触发“非符号链接库位于 -dev 软件包”的 QA 警告;同一
配方中的二进制程序链接到 ${PN}-dev 中的库,还会触发其他 QA 警告。
解决方法是将不带版本的库打包到其应在的 ${PN}。bitbake.conf 中
默认 FILES 变量的简化内容如下:
SOLIBS = ".so.*"
SOLIBSDEV = ".so"
FILES:${PN} = "... ${libdir}/lib*${SOLIBS} ... ${base_libdir}/*${SOLIBS} ..."
FILES_SOLIBSDEV ?= "${base_libdir}/lib*${SOLIBSDEV} ${libdir}/lib*${SOLIBSDEV}"
FILES:${PN}-dev = "... ${FILES_SOLIBSDEV} ..."
SOLIBS 定义匹配实际共享库的模式,SOLIBSDEV 匹配开发形式,
即不带版本的符号链接。FILES:${PN} 和 FILES:${PN}-dev 使用这两个
变量,将实际库放入 ${PN},将不带版本的符号链接放入 ${PN}-dev。
要打包不带版本的库,应在配方中如下修改变量:
SOLIBS = ".so"
FILES_SOLIBSDEV = ""
这样会将 .so 文件视为实际库,并清空 FILES_SOLIBSDEV,防止
任何库进入 ${PN}-dev。这是必要的,因为除非修改 PACKAGES,
${PN}-dev 总会先于 ${PN} 收集文件;它不能抢先收集本应放入
${PN} 的文件。
可加载模块本质上是不带版本的库,在运行时通过 dlopen() 加载,而不是
构建时链接。通常应将它们安装到私有目录。如果安装到 ${libdir},
则可以按不带版本的库处理。
19 示例
以下示例安装名为 libfoo.so 的不带版本 x86-64 预构建库。
COMPATIBLE_HOST 将配方限制在 x86-64 架构;INSANE_SKIP、
INHIBIT_PACKAGE_STRIP 和 INHIBIT_SYSROOT_STRIP 与前面的
带版本库示例设置相同。关键是按上述说明设置 SOLIBS 和
FILES_SOLIBSDEV:
SUMMARY = "libfoo sample recipe"
SECTION = "libs"
LICENSE = "CLOSED"
SRC_URI = "file://libfoo.so"
COMPATIBLE_HOST = "x86_64.*-linux"
INSANE_SKIP:${PN} = "ldflags"
INHIBIT_PACKAGE_STRIP = "1"
INHIBIT_SYSROOT_STRIP = "1"
SOLIBS = ".so"
FILES_SOLIBSDEV = ""
do_install () {
install -d ${D}${libdir}
install -m 0755 ${UNPACKDIR}/libfoo.so ${D}${libdir}
}