#icu #unicode #localization #native-bindings

rust_icu_unorm2

Unicode ICU4C 库的本地绑定。unorm2.h

12 个稳定版本 (4 个主要版本)

5.0.0 2024年2月21日
4.2.3 2023年10月6日
4.0.0 2023年5月2日
3.0.0 2022年11月10日
1.0.3 2021年10月13日

#395国际化 (i18n)

Download history 22/week @ 2024-04-21 1/week @ 2024-04-28 3/week @ 2024-05-19 7/week @ 2024-05-26 7/week @ 2024-06-02 6/week @ 2024-06-09 12/week @ 2024-06-16 1/week @ 2024-06-23 2/week @ 2024-07-07 4/week @ 2024-07-14 53/week @ 2024-07-28

每月59 次下载
用于 2 个

Apache-2.0

1.5MB
46K SLoC

rust_icu:ICU 库的底层 Rust 语言绑定

条目 描述
测试 Test status
源码 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) 的国际组件 (ICU) 库提供的底层本地 Rust 语言绑定的库。

如果您只需要快速了解如何下载和安装的说明,请参阅 快速入门指南

有关 ICU 库的详细信息,请参阅 ICU 项目主页。库源代码可以在 Github 上查看。

此文件的最新版本可在 https://github.com/google/rust_icu 上找到。

这不是一个官方支持的谷歌产品。

为什么封装 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 不同。

此库提供的绑定适用性有限,这意味着它可能有时不能直接使用。如果您遇到这种情况,请随时提交错误给我们修复。Pull requests 欢迎接受。

我们目前知道的局限性如下

  • 没有保证的功能一致性。一些在 C++ 中实现的算法在 C 中没有等效的,反之亦然。如果您使用的是 C++ 库,这通常不是问题,因为您可以自由选择任何适合您的 API 表面。但对于 Rust 绑定来说,这是一个问题,因为我们目前只能使用 C API。

  • 新的 C++ 算法的实现并不一定总是反映在 C API 中,导致 C 和 C++ API 表面之间的功能差异。例如,请参阅此错误

  • 虽然使用 icu_config 功能可能会让您在一定程度上自由地为您的库版本自动生成绑定,但我们仍然需要保留一个明确支持的 ICU 版本列表,以确保包装器的稳定性。

兼容性

兼容性保证如下

  1. 对所有感兴趣的特征组合,对最后三个主要 ICU 库版本执行自动测试。
  2. 对 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_* crate 中激活该功能。否则,编译结果可能会令人困惑。

功能 默认? 描述
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 版本创建 ICU 绑定,该变量在构建时对 cargo 可用。有关如何使用此功能的详细信息,请参阅下面的章节。当不使用 bindgen 功能时,此功能才有意义;否则没有影响。
static 如果设置,将静态链接 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 用户指南

  • 如果使用了 bindgen 功能,则会使用 rustfmt 工具。

    有关如何安装的说明,请参阅 https://github.com/rust-lang/rustfmt

测试

运行 rust_icu 测试有几个选项。

Cargo

使用 cargo 构建 和 测试 是构建和测试 rust 代码的标准方式。

rust_icu 库的情况下,您可能会发现系统默认的 ICU 开发包非常古老,在这种情况下,您将需要构建自己的 ICU4C 库(有关详细信息,请参阅下文)。这将使得必须传递 PKG_CONFIG_PATHLD_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 版本兼容的好方法。

已有技术

已经考虑了很多已有技术

目前的情况是,我想先自己做一些实验,然后再看看这些工作是否可以合并到上述努力中。

另请参阅

假设

对于 ICU 绑定存在几种竞争性方法。然而,根据 rust 的 RFC 存储库中的信息,至少看起来 rust 中 ICU 的支持工作仍在进行中。

以下是创建此库时所做的假设

  • 我们需要一个完整、可重用且易于使用的 rust 低级 ICU 库。

    例如,这意味着我们必须依赖外部 ICU 库,而不是将库本身与绑定代码一起携带。这种模块化允许库的最终用户使用他们选择的 ICU 库,并将其纳入各自的系统中。

  • 在此库的工作中不会重新实现任何 ICU 算法。

    ICU 的重新实现可能需要数千名工程师年才能完成。对于像 ICU 这样微妙且复杂的 API,我认为维护单个中央实现可能是更好的投资回报。

    此外,该库的存在并不会阻止重新实现。如果其他人想尝试重新实现 ICU,这也是可以的。

  • 该库应作为 rust 实现的低级基础。

    低级 ICU API 可能不适合最终用户。应该在这些绑定之上分层 rust-ful API。将功能细分到 crates 中可能是个好主意,以符合 rust 开发者的期望。

    我乐意重用上述提到的项目中已经做出的某些逻辑细分。

  • 我想探索将现有实现组合起来的方法,以构建一个完整的 rust ICU 支持。

    希望有可能将今天可用的所有 rust 绑定中的优点结合成一个统一的 rust 库。我随时可以讨论选项。

    我之所以开始一个单独的努力而不是向“现有技术”部分中列出的任何项目贡献,仅仅是因为我想尝试 rust 中的生成库会是什么样子。

附加说明

快速入门指南

在开始之前,请确保满足以下先决条件

  • 您已安装 docker 并在您的系统上运行。
  • 您有 GNU Make。
  • 您有 git
  • 您有足够的磁盘空间。构建环境的 docker 镜像有点大,因此需要几个 GiB 来容纳所有这些。
  • 您有互联网连接。

从那里,以下命令序列将检出、构建和测试 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]

或者:

  • 您已手动验证 兼容性矩阵 对于您想使用的 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.rsrust_icu_sys/bindgen/run_bindgen.sh,然后将适当的行添加到 BINDGEN_SOURCE_MODULES,接着是 BINDGEN_ALLOWLIST_FUNCTIONSBINDGEN_ALLOWLIST_TYPES

开启特定功能集进行测试

以下是在 ICU 67 上运行 docker 测试的示例,开启了 icu_version_in_envrenaming 功能,而不是默认设置。请注意,参数大多通过环境变量传递到运行 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 文件的新版本。创建 pull request 并进行检查。

有关为什么需要此内容的更多信息,请参阅 bindgen README.md

依赖项

~0.4–1.1MB
~24K SLoC