3.1.4 添加对系统库的依赖
3 分钟阅读
原文链接: https://docs.swift.org/latest/documentation/packagemanagerdocs/addingsystemlibrarydependency/
3.1.4 添加对系统库的依赖
定义库的位置,并提供模块映射,把 C 头文件暴露给 Swift。
概述
你可以借助包管理器链接系统库,把它们当作代码中的依赖使用。为此,添加一个 systemLibrary 类型的 target,并为你使用的每个系统库提供一个 module.modulemap。
使用 pkg-config 提供头文件和链接器搜索路径
在类 Unix 系统上,Swift Package Manager 可以使用 pkgConfig 为编译器提供包含库头文件和链接二进制文件所需的路径。如果你的系统不提供 pkgConfig,或者该库不包含包配置文件,你也可以直接把选项提供给 Swift 编译器。
pkgConfig 按名称查找库,这个名称就是你传给 systemLibrary 目标的参数。下面两个例子展示了用 libgit2 手动查找该库路径的做法:
| |
要手动提供头文件搜索路径,把 -Xcc -I/path/to/include/ 作为额外参数传给 swift build。要与上面 pkgConfig 的例子匹配,额外的命令行选项应当是:-Xcc -I/opt/homebrew/Cellar/libgit2/1.9.0/include
| |
要手动提供链接二进制文件的搜索路径,把 -Xlinker -L/path/to/include/ 作为额外参数传给 swift build。要与上面 pkgConfig 的例子匹配,额外的命令行选项应当是:-Xlinker -L/opt/homebrew/Cellar/libgit2/1.9.0/lib。
声明系统库
systemLibrary 定义会告诉 Swift 编译器在哪里找到该 C 库。在类 Unix 系统上构建时,包管理器可以用 pkg-config 查找库的安装位置。在 pkgConfig 参数中指定你要查找的 C 库名称。如果你希望用 Swift Package Manager 在本地安装该包(如果尚未安装),可以指定一个或多个 provider。
下面的例子给出了 libgit2 库的声明,在 macOS 上用 homebrew 安装该库,在基于 Debian 的 Linux 系统上用 apt 安装:
| |
编写模块映射
module.modulemap 文件声明要暴露哪些 C 库头文件、暴露其中的哪些部分,作为一个或多个可以在 Swift 代码中导入的 clang 模块。每个模块都定义了:
- 要暴露的模块名称
- 一个或多个要引用的头文件
- 对 C 库名称的引用
- 一行或多行 export,指明要向 Swift 暴露什么
例如,下面的模块映射使用头文件 git2.h,链接到 libgit2,并把 git2.h 中定义的所有函数导出给 Swift:
module Clibgit [system] {
header "git2.h"
link "git2"
export *
}
请尽量引用位于同一目录中的头文件,或者使用本地路径,以获得最大的灵活性。你也可以使用绝对路径,不过那会让声明更脆弱,因为不同系统会把系统库安装在各式各样的路径下。
注意:并非所有库都能轻易地变成模块。你可能需要创建额外的垫片(shim)头文件,为 Swift 编译器提供完整编译和链接该库所需的引用。
关于模块映射结构的更多信息,参见 LLVM 文档的模块映射语言。
系统库模块的版本命名
创建模块映射时,请遵循系统打包者的约定,在模块名中带上版本信息。例如,python3 在 Debian 中的包名就叫 python3。在 Debian 中并没有一个统一的 python 包;系统打包者将其设计为可以与其他版本并存安装。基于这一点,在 Debian 系统上为 python3 创建模块映射时,推荐的名称是 CPython3。
带可选依赖的系统库
要引用一个带可选依赖的系统库,你需要再做一个包来表示那个可选库。
例如,库 libarchive 可选地依赖 xz,这意味着它可以在启用 xz 支持的情况下编译,但并不强制要求。要提供一个使用带 xz 支持的 libarchive 的包,请做一个 CArchive+CXz 包,它依赖 CXz 并提供 CArchive。