35 个版本 (14 个稳定版)
5.0.0 | 2024年2月21日 |
---|---|
4.2.3 | 2023年10月6日 |
4.0.0 | 2023年5月2日 |
3.0.0 | 2022年11月10日 |
0.0.0 | 2019年12月30日 |
#366 在 国际化 (i18n) 中
每月1,580 次下载
用于 26 个crate(23个直接使用)
1.5MB
44K SLoC
rust_icu:ICU 库的低级别 Rust 语言绑定
条目 | 描述 |
---|---|
测试 | |
源码 | https://github.com/google/rust_icu |
README | https://github.com/google/rust_icu/blob/main/README.md |
覆盖率 | 查看报告 |
文档 | https://docs.rs/crate/rust_icu |
这是一个针对 C(即 ICU4C)的 Unicode 国际组件(ICU)库的低级别本地 Rust 语言绑定的库。
如果您只需要快速了解如何下载和安装,请参阅 快速入门指南
有关 ICU 库的详细信息,请访问 ICU 项目主页。库源代码可以在 Github 上查看。
此文件的最新版本可在 https://github.com/google/rust_icu 上找到。
这不是一个官方支持的 Google 产品。
为什么要包装 ICU(而不是做其他事情)?
-
Rust 语言的 国际化 页面确认,Rust 中的 ICU 支持参差不齐,因此拥有一个功能性的包装器有助于推进技术的进步。
-
像 Fuchsia 这样的项目已经依赖于 ICU,而 Rust 绑定允许以简单的方式使用 Unicode 算法,而无需承担更多依赖。
-
与像 ICU4X 这样的项目在接口上的合作可能允许未来无缝过渡到全 Rust 实现。
仓库结构
该仓库按照Rust crates的格式组织。每个crate对应于ICU4C库的C API中的相应头文件。请参考覆盖率报告以获取关于头文件中函数覆盖的详细信息。
crate | 描述 |
---|---|
rust_icu | 顶级crate。如果您只想使用所有功能,请包含此crate。 |
rust_icu_common | 常用低级绑定封装。 |
rust_icu_intl | 实现ECMA 402推荐API。 |
rust_icu_sys | 低级绑定代码。 |
rust_icu_ubrk | 支持文本边界分析。实现了来自ICU库的ubrk.h C API头文件。 |
rust_icu_ucal | ICU日历。实现了来自ICU库的ucal.h C API头文件。 |
rust_icu_ucol | 排序支持。实现了来自ICU库的ucol.h C API头文件。 |
rust_icu_udat | ICU日期和时间。实现了来自ICU库的udat.h C API头文件。 |
rust_icu_udata | ICU二进制数据。实现了来自ICU库的udata.h C API头文件。 |
rust_icu_uenum | ICU枚举。实现了来自ICU库的uenum.h C API头文件。主要实现UEnumeration 和相关功能。 |
rust_icu_uformattable | 区域敏感的列表格式化支持。实现了来自ICU库的uformattable.h C API头文件。自0.3.1版本起。 |
rust_icu_ulistformatter | 区域敏感的列表格式化支持。实现了来自ICU库的ulistformatter.h C API头文件。 |
rust_icu_uloc | 区域支持。实现了来自ICU库的uloc.h C API头文件。 |
rust_icu_umsg | MessageFormat支持。实现了来自ICU库的umsg.h C API头文件。 |
rust_icu_unorm2 | Unicode规范化支持。实现了来自ICU库的unorm2.h C API头文件。 |
rust_icu_unum | 数字格式化支持。实现了来自ICU库的unum.h C API头文件。 |
rust_icu_unumberformatter | 数字格式化支持(现代)。实现了来自ICU库的unumberformatter.h C API头文件。 |
rust_icu_upluralrules | 区域敏感的复数规则支持。实现了来自ICU库的upluralrules.h C API头文件。 |
rust_icu_ustring | ICU字符串。实现了来自ICU库的ustring.h C API头文件。 |
rust_icu_utext | 文本操作。实现了来自ICU库的utext.h C API头文件。 |
rust_icu_utrans | 转写支持。实现了来自 ICU 库的 utrans.h C API 头文件。 |
限制
目前生成的 Rust 语言绑定方法限制了语言绑定的可用性,仅限于可用的 C API。ICU 库的 C API(在文档中有时称为 ICU4C)与 ICU C++ API 不同。
该库提供的绑定应用范围有限,这意味着它可能无法直接满足您的需求。如果您遇到这种情况,请随时提交一个错误报告,以便我们修复。欢迎提交拉取请求。
我们目前知道的限制如下:
-
没有保证的特性兼容性。 一些在 C++ 中实现的算法没有 C 等效版本,反之亦然。如果您使用的是 C++ 库,这通常不会成为问题,因为您可以自由选择任何适合您的 API 表面。但对于 Rust 绑定来说,这是一个问题,因为我们目前只能使用 C API。
-
新的算法的 C++ 实现不一定总是反映在 C API 中,导致 C 和 C++ API 表面之间的功能差异。例如,参见这个错误。
-
虽然使用
icu_config
功能可能会让您在一定程度上自由地为您自己的库版本自动生成绑定,但我们仍需要保持一个明确支持的 ICU 版本列表,以确保包装器稳定。
兼容性
兼容性保证如下:
- 对所有感兴趣的功能组合,自动测试在最后三个主要 ICU 库版本中执行。
- 自动测试在 docs.rs 系统使用的 ICU 库版本中执行(因此可以构建文档)。
rust_icu 版本 |
ICU 63.x | ICU 70.1 | ICU 71.1 | ICU 72.1 | ICU 73.1 | ICU 74.1 |
---|---|---|---|---|---|---|
3.0 | ✅ | ✅ | ✅ | ✅ | ||
4.0 | ✅ | ✅ | ✅ | ✅ | ||
5.0 | ✅ | ✅ | ✅ | ✅ |
功能
rust_icu
库旨在与 cargo
编译,并启用以下功能之一。使用 cargo
编译允许我们在 rust_icu_sys
库中的自定义 build.rs
文件中执行某些库检测,并使构建过程适应您的构建环境。但是,由于并非每个开发环境都会使用相同的设置,我们选择了以下功能(如下)作为配置选项。
尽管我们的意图是保持以下功能列表与实际列表(在 Cargo.toml
中)同步,但列表可能偶尔会过时。
要使用任何功能,您需要激活您打算使用的所有 rust_icu_*
包中的功能。否则,会导致编译结果混乱。
功能 | 默认? | 描述 |
---|---|---|
use-bindgen |
是 | 如果设置,则 cargo 会运行 bindgen 以根据安装的 ICU 库生成绑定。要使此功能正常工作,必须在 $PATH 中存在 icu-config 程序。将来可能会有其他自动检测库的方法,例如通过 pkg-config 。 |
renaming |
是 | 如果设置,则 ICU 绑定将带有版本号附加生成。这在 ICU 中称为“重命名”,通常仅在需要链接特定 ICU 版本时才需要,例如,为了绕过需要链接不同 ICU 版本的情况。有关重命名的讨论,请参阅ICU 文档。 如果未使用 bindgen ,则必须使用此功能。 |
icu_config |
是 | 如果设置为 true,将使用二进制 icu-config 来配置库。如果您不希望 build.rs 尝试自动检测构建环境,请关闭此功能。如果您构建环境以不同的方式配置 ICU,则应跳过此功能。此功能仅在使用 bindgen 功能时才有意义;否则不起作用。 |
icu_version_in_env |
否 | 如果设置为 true,将为在环境变量 RUST_ICU_MAJOR_VERSION_NUMBER 中指定的 ICU 版本创建 ICU 绑定,该变量在构建时提供给 cargo。有关如何使用此功能的详细信息,请参阅下面的章节。此功能仅在未使用 bindgen 功能时才有意义;否则不起作用。 |
静态 |
否 | 如果设置为 true,将静态链接 ICU 库(以及标准的 C++ 动态库)。如果您在非标准目录中有 ICU 的构建版本,可以使用 RUST_ICU_LINK_SEARCH_DIR 添加额外的搜索路径。 |
先决条件
必需
-
rust_icu
源代码使用
git
克隆git clone https://github.com/google/rust_icu.git
-
rustup
从 https://rustup.rs 安装。用于设置工具链默认值。这将安装
cargo
。 -
Clang
您必须安装 Clang 以访问正确的头文件。
-
ICU 库开发环境
您将需要访问 ICU 库以将
rust_icu
绑定链接到。下载和安装 ICU 不在本文档的范围内。请阅读ICU 简介以了解如何构建和安装。有时,ICU 库可能已经预安装在您的系统上,或者您可以从包管理程序中提取库。然而,这不一定是你需要链接到正在开发的程序中的库。简而言之,您有责任在系统上的某个地方拥有 ICU 的开发者版本。
我们有一个快速入门安装,它可能会在您的环境配置与我们非常相似且您想从源代码构建 ICU 的情况下帮助您。
可选
-
GNU Make,如果您想使用基于 make 的构建和测试。
安装 GNU Make 不在本文档的范围内。请参阅您的操作系统说明进行安装。
-
docker
,如果您决定使用基于 docker 的构建和测试。安装
docker
不在本文档的范围内,请参阅docker 安装说明以获取详细信息。由于安装docker
会干扰主机机器,您的公司可能有关于如何正确安装docker
的内部文档。 -
icu-config
工具,如果使用icu_config
功能。您需要在系统上安装 ICU 库,以便二进制
icu-config
在您的$PATH
中。构建脚本将使用它来发现库设置并生成正确的链接脚本。如果您使用该功能但找不到icu-config
, -
bindgen
工具,如果使用bindgen
功能。有关如何安装它的说明,请参阅bindgen 用户指南。
-
rustfmt
工具,如果使用bindgen
功能。有关如何安装的说明,请参阅https://github.com/rust-lang/rustfmt。
测试
有几个选项可以运行 rust_icu
的测试。
Cargo
使用 cargo
进行构建和测试是构建和测试 Rust 代码的标准方法。
在 rust_icu
库的情况下,你可能发现你的系统默认的 ICU 开发包很旧,在这种情况下,你需要构建自己的 ICU4C 库(下面有说明)。这将使得需要传递 PKG_CONFIG_PATH
和 LD_LIBRARY_PATH
环境变量来帮助构建代码定位和使用你构建的库,而不是系统默认的。
以下测试都应该能够构建并通过。请注意,因为所需的库在自定义位置,我们在运行测试时需要设置 LD_LIBRARY_PATH
,以及 PKG_CONFIG_PATH
。
如果你发现你可以使用系统默认的 ICU 安装,你可以安全地省略这两个库。
env PKG_CONFIG_PATH="$HOME/local/lib/pkgconfig" \
LD_LIBRARY_PATH="$HOME/local/lib" \
bash -c 'cargo test'
如果你认为上述方法太麻烦,可以考虑尝试基于 Docker 的方法。
GNU Make
如果你喜欢 GNU 的做事方式,你可能更喜欢 GNU Make 方法。
最简单的方法是使用 GNU Make 并运行
make test
如果你正在开发 rust_icu
,并且已经设置好你的开发环境,并且想要一个运行测试的快捷方式,你可能想使用这种方法。
基于 Docker 的
参见上面可选依赖部分。
要运行对 rust_icu
源代码的密封构建和测试,请发出以下命令
make docker-test
这将运行本地机器上的基于 Docker 的源代码构建和测试。这是一种测试你的代码是否与 ICU 的特定参考版本兼容的好方法。
现有技术
已经考虑了大量的现有技术
- https://github.com/servo/rust-icu
- https://github.com/open-i18n/rust-unic
- https://github.com/fullcontact/icu-sys
- https://github.com/rust-locale
- https://github.com/unicode-rs
目前的情况是,我首先想做一些自己的实验,然后看看这项工作是否可以融入上述任何努力。
另请参阅
- https://github.com/rust-lang/rfcs/issues/797
- https://unicode-rs.github.io
- https://github.com/i18n-concept/rust-discuss
假设
有几种 ICU 绑定的竞争性方法。然而,至少根据 rust 的 RFC 存储库中可用的信息,在 Rust 中对 ICU 的支持工作仍在进行中。
以下是在创建此库时所做的假设
-
我们需要一个完整、可重用且无痛苦的 Rust 低级 ICU 库。
这意味着我们必须依赖于外部 ICU 库,而不是将库本身与绑定代码一起携带。这种模块化允许库的最终用户使用他们选择的 ICU 库,并将其纳入他们各自的系统。
-
此库的工作不会重新实现任何 ICU 算法。
ICU 重新实现可能需要数千名工程师年的时间来完成。对于像 ICU 这样微妙和复杂的 API,我认为维护单个中央实现可能是一个更好的投资回报率。
此外,此库的存在并不会阻止重新实现。如果有人想尝试重新实现 ICU,那也很好。
-
此库应作为 Rust 实现的低级基础。
低级 ICU API 可能不适合最终用户。应该在这些绑定之上分层一个 Rustful API。可能最好将此功能细分到 crate 中,以符合 Rust 开发者的预期。
我很乐意重用上述项目中已经做出的逻辑划分。
-
我想探索与现有实现结合的方法,以构建一个完整的Rust ICU支持。
希望有可能将今天所有可用的Rust绑定中的优点结合成一个统一的Rust库。我随时可以讨论选项。
我之所以开始一个独立的项目,而不是在“现有技术”部分列出的任何项目中贡献力量,仅仅是因为我想尝试Rust中生成的库会是什么样子。
附加说明
快速入门指南
在开始之前,请确保满足以下先决条件
从那里,以下命令序列将检出、构建和测试rust_icu
源代码。
mkdir -p ~/tmp
cd tmp
git clone https://github.com/google/rust_icu
cd rust_icu
make docker-test
现在您可以修改代码和测试。您可以通过运行make docker-test
来重新运行编译和测试循环。
ICU安装说明
以下说明遵循ICU仓库中的“树外”构建说明。
假设
以下说明不是自包含的。它假定
- 您已设置系统,以便有效遵循ICU构建说明。这需要一些前期时间投资。
- 您可以从源代码构建ICU,并且您的项目可以访问ICU源代码。
- 您的设置是Linux,有一些非常具体的设置对我有效。您可能能够将其修改为在您的系统上工作。
编译
mkdir -p $HOME/local
mkdir -p $HOME/tmp
cd $HOME/tmp
git clone https://github.com/unicode-org/icu.git
mkdir icu4c-build
cd icu4c-build
../icu/icu4c/source/runConfigureICU Linux \
--prefix=$HOME/local \
--enable-static
make
make install
make doc
如果编译成功完成,目录$HOME/local/bin
将包含文件icu-config
,这是发现库配置所必需的。
您还可以执行以下操作
make check
以运行单元测试。
如果您将$HOME/local/bin
添加到$PATH
,或将icu-config
移动到您的$PATH
中列出的目录,您应该已经准备好编译rust_icu
。
ICU重建说明
如果您更改了ICU库的配置,并有意从源代码重新构建库,那么您可能需要添加一个中间的make clean
命令。
由于ICU构建不是封闭的,这确保了在构建目录中没有旧编译过程的残留。例如,如果您升级ICU库的主版本,则需要这样做。如果您忘记这样做,您可能会在编译ICU或链接或运行程序时遇到意外的错误。
为ICU的特定版本编译
假设
- 您已选择功能集
[重命名,icu_version_in_env]
o
或者:
- 您已手动验证,您想要使用的 ICU 版本和功能集的兼容性矩阵中显示为 "是"。
以下是一个测试示例。
env PKG_CONFIG_PATH="$HOME/local/lib/pkgconfig" \
LD_LIBRARY_PATH="$HOME/local/lib" \
RUST_ICU_MAJOR_VERSION_NUMBER=65 \
bash -c 'cargo test'
以下是一个尚未测试的示例,即编译 rust_icu
以针对现有的 ICU 版本 66。
env PKG_CONFIG_PATH="$HOME/local/lib/pkgconfig" \
LD_LIBRARY_PATH="$HOME/local/lib" \
RUST_ICU_MAJOR_VERSION_NUMBER=66 \
bash -c 'cargo test'
添加对 ICU 新版本的支持。
一般来说,只要支持 icu-config
方法,只要底层 C API 没有太大差异,就应能够为 ICU 库的新版本生成库包装器。
实现 ICU 65.1 的简单支持的方法包括以下步骤。下面,$RUST_ICU_SOURCE_DIR
是您提取 ICU 源代码的目录。
- 将新的 ICU 版本下载到
$RUST_ICU_SOURCE_DIR
。 - 按照例如上面的 编译 步骤使用新版本构建 ICU 库。
- 从输出目录
$RUST_ICU_SOURCE_DIR/target/debug/build/rust_icu_sys-...
获取文件lib.rs
,将其重命名为lib_66.rs
(如果使用 ICU 版本 66,否则附加您使用的版本)。 - 将文件保存到目录
$RUST_ICU_SOURCE_DIR/rust_icu_sys/bindgen
,这是包含预生成源文件的目录。
如果 build.rs
被更改以包含更多功能,则可能需要重新生成这些文件 lib_XX.rs
。
添加更多绑定
当添加更多 ICU 包装器时,请确保执行以下操作
- 检查
rust_icu_sys/build.rs
和rust_icu_sys/bindgen/run_bindgen.sh
,然后将适当的行添加到BINDGEN_SOURCE_MODULES
,然后是BINDGEN_ALLOWLIST_FUNCTIONS
和BINDGEN_ALLOWLIST_TYPES
。
开启特定功能集进行测试
这是一个在 ICU 67 上运行 docker 测试的示例,其中开启了 icu_version_in_env
和 renaming
功能,而不是默认功能。请注意,参数主要通过环境变量传递到运行 docker-test
的容器中。
make DOCKER_TEST_ENV=rust_icu_testenv-67 \
RUST_ICU_MAJOR_VERSION_NUMBER=67 \
DOCKER_TEST_CARGO_TEST_ARGS='--no-default-features --features icu_version_in_env,renaming' \
docker-test
一些解释
- 环境变量
RUST_ICU_MAJOR_VERSION_NUMBER
用于icu_version_in_env
功能,以指示cargo
使用文件rust_icu_sys/bindgen/lib_67.rs
作为预构建的 bindgen 源文件,而不是尝试即时生成。 - 环境变量
DOCKER_TEST_CARGO_TEST_ARGS
用于将命令行参数传递给在 docker 容器中使用的cargo test
,这些参数主要通过环境变量直接传递给cargo test
,不进行引号引用,因此环境中的单词在传递给cargo test
时将成为单独的参数。 - 环境变量
DOCKER_TEST_ENV
是运行测试所使用的 Docker 容器的基准名称。容器rust_icu_testenv-67
是一个包含预安装环境的容器镜像,其中包含 ICU 67 的编译版本。
刷新静态 bindgen 文件
需要 Docker。
定期运行 make static-bindgen
,以刷新静态生成的 bindgen 文件(命名为 lib_XX.rs
,其中 XX
是 ICU 版本,例如 67),位于目录 rust_icu_sys/bindgen
,当 bindgen
功能关闭时使用。
调用此 make 目标将修改带有较新版本的 lib_XX.rs
文件的本地检视。提交一个拉取请求并检查它们。
有关为什么需要此信息的更多信息,请参阅 bindgen README.md。
依赖项
~0.4–1MB
~22K SLoC