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日 |
#55 在 国际化 (i18n) 中
每月 1,474 次下载
在 18 个 库中使用 18 (直接使用9个)
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 库的 cargo 工作区。每个库对应 ICU4C 库 C API 中的相应头文件。请参考覆盖率报告了解头文件中函数覆盖的详细信息。
库 | 描述 |
---|---|
rust_icu | 顶级库。如果您只想使用所有可用的功能,请包含此库。 |
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库生成绑定。要使此功能正常工作,必须将icu-config 放入$PATH。将来可能会采用其他方法来自动检测库,例如通过pkg-config 。 |
重命名 |
是 | 如果设置,ICU绑定将带有版本号附加。这在ICU中称为“重命名”,通常仅在需要链接到特定ICU版本时才需要,例如,为了解决需要链接不同ICU版本的问题。有关重命名的讨论,请参见ICU文档。 如果未使用bindgen ,则必须使用此功能。 |
icu_config |
是 | 如果启用,将使用二进制icu-config来配置库。如果不希望build.rs 尝试自动检测构建环境,请关闭此功能。如果你的构建环境以不同的方式配置ICU,则应跳过此功能。此功能仅在启用bindgen 功能时才有意义;否则没有作用。 |
icu_version_in_env |
否 | 如果启用,将为环境变量RUST_ICU_MAJOR_VERSION_NUMBER 中指定的ICU版本创建绑定,该变量在构建时提供给Cargo。有关如何使用此功能的详细信息,请参阅下面的章节。此功能仅在未使用bindgen 功能时才有意义;否则没有作用。 |
静态 |
否 | 如果启用,将静态链接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,这可能会帮助您。
可选
-
如果您想使用基于make的构建和测试,请使用GNU Make。
安装GNU Make超出了此文件的范围。请参阅您操作系统的安装说明。
-
如果您决定使用基于docker的构建和测试,请使用
docker
。安装
docker
超出了此文件的范围,请参阅docker安装说明以获取详细信息。由于安装docker
会干扰主机机器,您的公司可能有关于如何正确安装docker
的内部文档。 -
如果使用
icu_config
功能,请使用icu-config
实用程序。您需要在您的系统上安装ICU库,使得二进制
icu-config
位于您的$PATH
中。构建脚本将使用它来发现库设置并生成正确的链接脚本。如果您使用此功能但找不到icu-config
, -
如果使用
bindgen
功能,请使用bindgen
实用程序。有关如何安装它的说明,请参阅bindgen用户指南。
-
如果使用
bindgen
功能,请使用rustfmt
实用程序。请参阅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的支持工作仍在进行中。
以下是在制作此库时所做的假设
-
我们需要一个完整、可重用且无痛苦的ICU底层库,用于rust。
例如,这意味着我们必须依赖于外部ICU库,而不是将库本身与绑定代码一起携带。这种模块化允许库的最终用户使用他们选择的ICU库,并将其纳入他们各自的系统中。
-
不会在库的工作中重新实现任何ICU算法。
ICU重新实现可能需要数千名工程师的年数才能完成。对于像ICU这样微妙和复杂的API,我认为维护单个集中实现可能是一个更好的投资回报。
此外,这个库的存在并不会阻止重新实现。如果有人想尝试重新实现ICU,那也很好。
-
此库应作为rust实现的底层基础。
低级别的 ICU API 可能不适合最终用户。应该在这些绑定之上构建一个 rust-ful API。可能将这个功能细分为 crate,以符合 Rust 开发者的期望是个不错的主意。
我很乐意重用上述项目中已经进行的逻辑细分。
-
我想探索将现有实现结合起来的方法,以构建一个完整的 Rust ICU 支持。
希望有可能将今天所有可用的 Rust 绑定的优点结合到一个统一的 Rust 库中。我随时准备讨论选项。
我之所以开始一个独立的项目而不是向“先前艺术”部分中列出的任何项目贡献,仅仅是因为我想尝试看看生成的库在 Rust 中的样子。
附加说明
快速入门指南
在开始之前,请确保满足以下先决条件
- 您已安装 docker,并且它在您的系统上运行。
- 您有 GNU Make。
- 您有 git。
- 您有足够的磁盘空间。构建环境的 Docker 图像有点大,所以需要几吉字节的空间才能容纳所有这些。
- 您有互联网连接。
从那里,以下命令序列将检出、构建和测试 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'
以下是一个尚未测试的示例,即使用预存的ICU版本66编译rust_icu
。
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
~23K SLoC