一个简单的 Swift GIR 解析器,用于为 .gir 文件创建 Swift 类型
要启动一个项目,该项目使用围绕利用 gobject-introspection 的底层库的 Swift 包装器,您需要创建一些脚本,这些脚本使用 gir2swift
将 gobject-introspection XML (.gir
) 文件中的信息转换为 Swift。以下是基本步骤的简要概述
gir2swift
(请参阅下面的 构建)gir2swift
作为插件添加到您的 Package.swift
文件中(请参阅下面的 用法)swift build
构建您的项目awk
或 sed
模块文件 -- 见下文),以纠正编译器抱怨的错误版本 16 提供了元数据属性和集合类型的类型化泛型,例如列表和数组。
版本 15 提供了 Package Manager 插件。这需要 Swift 5.6 或更高版本(旧版本可以通过 swift52 分支使用)。
通常,您不会直接构建此软件包(但为了测试,您可以 - 请参阅下面的“构建”)。相反,您可以使用 Swift Package Manager 将 gir2swift
嵌入到您自己的项目中。在安装先决条件(请参阅下面的“先决条件”)后,将 gir2swift
作为依赖项和插件添加到您的 Package.swift
文件中。这是一个例子。
// swift-tools-version:5.6
import PackageDescription
let package = Package(name: "MyPackage",
dependencies: [
.package(url: "https://github.com/rhx/gir2swift.git", branch: "main"),
],
targets: [
.target(
name: "MyPackage",
dependencies: [
.product(name: "gir2swift", package: "gir2swift"),
],
swiftSettings: [
.unsafeFlags(["-suppress-warnings"], .when(configuration: .release)),
.unsafeFlags(["-suppress-warnings", "-Xfrontend", "-serialize-debugging-options"], .when(configuration: .debug)),
],
plugins: [
.plugin(name: "gir2swift-plugin", package: "gir2swift")
]
)
]
)
为了使此插件工作,您的软件包需要一个 gir2swift-manifest.yaml
文件(位于包含 Package.swift
的同一目录中,或相关目标的 Sources
子目录中)。清单需要包含要使用的 .gir
和 pkg-config
文件的名称(不带扩展名),例如:
version: 1
gir-name: GLib-2.0
pkg-config: glib-2.0
output-directory: Sources/GLib
alpha-names: true
gir2-swift [<options>] [<gir-files> ...]
<gir-files> The .gir metadata files to process. Gir files
specified in CLI are merged with those specified in
the manifest.
-v Produce verbose output.
-a Disables all filters. Wrappers for all C types will
be generated.
--alpha-names Create a fixed set of output files ending in A-Z.
-e, --extension-namespace <extension-namespace>
Add a namespace extension with the given name.
-n, --namespace <namespace>
Add a namespace with the given name.
-s Create a single .swift file per class.
--post-process <post-process>
Additional files to post-process.
-p <p> Add pre-requisite .gir files to ensure the types in
file.gir are known. Prerequisities specified in CLI
are merged with the prerequisites found by gir2swift.
-o <o> Specify the output directory to put the generated
files into.
-t, --target-directory <target-directory>
Specify the target source directory to read the
manifest and configurations from.
-w, --working-directory <working-directory>
Specify the working directory (package directory of
the target) to change into.
--pkg-config-name <pkg-config-name>
Library name to pass to pkg-config. Pkg config name
specified in CLI trumps the one found in manifest.
-m <m> Add the given .swift file as the main (hand-crafted)
Swift file for your library target.
--manifest <manifest> Custom path to manifest. (default:
gir2swift-manifest.yaml)
--opaque-declarations Skips all other generation steps and prints opaque
struct stylized declarations for each record and
class to stdout.
-h, --help Show help information.
gir2swift
从 gobject-introspection XML (file.gir
) 文件中获取信息,并创建相应的 Swift 包装器。在读取 .gir
文件时,gir2swift
还会读取您创建的许多包含附加信息的 模块文件。
以下选项可用
-m Module.swift
添加Module.swift
作为您的库目标的主要(手工制作的)Swift 文件。
-o directory
指定将生成的文件放入的输出目录。
-p pre.gir
添加pre.gir
作为先决条件.gir
文件,以确保file.gir
中的类型是已知的
-s
为每个类创建一个单独的.swift
文件
-v
生成详细输出。
以下命令从 /usr/share/gir-1.0/Gio-2.0.gir
中的信息生成 Sources/GIO
中的 Swift 包装器,复制 Gio-2.0.module
中的内容,并考虑 GLib-2.0.gir
和 GObject-2.0.gir
中的信息
gir2swift -o Sources/GIO -m Gio-2.0.module -p /usr/share/gir-1.0/GLib-2.0.gir -p /usr/share/gir-1.0/GObject-2.0.gir /usr/share/gir-1.0/Gio-2.0.gir
Gio-2.0.module
文件需要包含您想要手动添加到您的 Swift 模块的代码,例如
import CGLib
import GLib
import GLibObject
public struct GDatagramBased {}
public struct GUnixConnectionPrivate {}
public struct GUnixCredentialsMessagePrivate {}
public struct GUnixFDListPrivate {}
public struct GUnixFDMessagePrivate {}
public struct GUnixInputStreamPrivate {}
public struct GUnixOutputStreamPrivate {}
public struct GUnixSocketAddressPrivate {}
func g_io_module_load(_ module: UnsafeMutablePointer<GIOModule>) {
fatalError("private g_io_module_load called")
}
func g_io_module_unload(_ module: UnsafeMutablePointer<GIOModule>) {
fatalError("private g_io_module_unload called")
}
此外,您还需要一个相应的序言文件 Gio-2.0.preamble
,用于导入必要的底层库,例如
import CGLib
import GLib
import GLibObject
除了读取给定的 Module.gir
文件外,gir2swift
还会从当前工作目录读取许多模块文件,这些文件包含附加信息。这些模块文件需要与 .gir
文件具有相同的名称,但具有不同的文件扩展名
此文件包含您需要作为每个生成的 .swift
文件的序言的 Swift 代码(例如,您想要导入的所有模块的 import
语句)。
此文件包含 Swift 代码(除了 Module.preamble
之外)会进入生成的 Module.swift
文件(例如,额外的 import
语句或定义)。
此文件包含您想要在输出中抑制的符号(以换行符分隔)。在此处,您应该包含 .gir
文件中 Swift 编译器无法从相关的 C 语言头文件导入的所有符号。
此文件包含否则将被抑制的符号(以换行符分隔)(例如,因为 gir2swift
认为它们是重复的),但您希望包含在 gir2swift
输出中。
通常,gir2swift
尝试按照 .gir
文件中的定义将常量从 C 转换为 Swift。在此文件中列出的常量名称(并以换行符分隔)将不会被转换。
此文件包含被视为 C 回调的类型后缀,并将被 gir2swift
注释为 @escaping
。如果未指定,则默认为 ["Notify", "Func", "Marshaller", "Callback"]
。
此文件包含以 \t
分隔的行,其中包含命名空间及其替换项。这可以用于解决 Swift 编译器的限制,例如区分具有相同名称的模块和类型。
用于后处理生成文件的 sed 脚本。
用于后处理生成文件的 awk 脚本。
要构建,您至少需要 Swift 5.6;从 https://swiftlang.cn/download/ 下载 -- 如果您使用的是 macOS,请确保您也安装了命令行工具)。使用 swift --version
测试您的编译器是否工作,这应该为您提供类似以下内容的结果
$ swift --version
swift-driver version: 1.75.2 Apple Swift version 5.8 (swiftlang-5.8.0.124.2 clang-1403.0.22.11.100)
Target: arm64-apple-macosx13.0
在 macOS 上,或者在 Linux 上,您应该得到类似以下内容的结果
$ swift --version
Swift version 5.8.1 (swift-5.8.1-RELEASE)
Target: x86_64-unknown-linux-gnu
这些 Swift 包装器已经过 libxml-2.9.4 和 2.9.9 的测试。它们应该适用于更高版本,但 YMMV。另请确保您已安装 gobject-introspection
及其 .gir
文件。
在当前版本的 macOS 上,您需要使用 HomeBrew 安装 libxml2
(系统自带的版本不包含必要的开发头文件 -- 有关 HomeBrew 设置说明,请参阅 https://brew.sh.cn)
brew update
brew install libxml2 gobject-introspection
在 Ubuntu 16.04、18.04 和 20.04 上,您可以使用发行版自带的 gtk。只需使用 apt
包管理器安装即可
sudo apt update
sudo apt install libxml2-dev gobject-introspection libgirepository1.0-dev jq
在 Fedora 上,您可以使用发行版自带的 gtk。只需使用 dnf
包管理器安装即可
sudo dnf install libxml2-devel gobject-introspection-devel jq
通常,您不会直接构建此软件包,而是将其嵌入到您自己的项目中(请参阅下面的“嵌入”)。但是,您可以单独构建和测试此模块,以确保一切正常。确保您已安装所有先决条件(请参阅上文)。之后,您可以简单地克隆此存储库并使用以下命令构建命令行可执行文件(请耐心等待,这将下载所有必需的依赖项并花费一段时间进行编译)
git clone https://github.com/rhx/gir2swift.git
cd gir2swift
swift build
在 macOS 上,您可以改用 Xcode 构建项目。为此,只需在 Xcode IDE 中打开软件包
cd gir2swift
open Package.swift
之后,使用(通常的)“构建”和“测试”按钮来构建/测试此软件包。
以下是您可能遇到的一些常见错误以及如何修复它们。
如果您收到如下错误
Girs located at
Cannot open '/GLib-2.0.gir': No such file or directory
请确保您已安装相关的 gobject-introspection
软件包(按照“先决条件”部分),包括它们的 .gir
和 .pc
文件。
如果您在运行 swift build
时收到 Segmentation fault (core dumped)
或循环依赖错误,例如
warning: circular dependency detected while parsing pangocairo: harfbuzz -> freetype2 -> harfbuzz
这可能意味着您的 Swift 工具链太旧了。请确保最新的工具链是您运行 Swift 编译器时找到的工具链(请参阅上文)。
如果您得到一个旧版本,请确保在您的 PATH
中首先找到正确版本的 swift 编译器。在 macOS 上,使用 xcode-select 选择并安装最新版本,例如
sudo xcode-select -s /Applications/Xcode.app
xcode-select --install