#icu #localization #unicode #native-bindings #build-environment

rust_icu_ustring

Unicode ICU4C 库的原生绑定。ustring.h

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 日

#78国际化(i18n)

Download history 375/week @ 2024-03-13 326/week @ 2024-03-20 284/week @ 2024-03-27 450/week @ 2024-04-03 335/week @ 2024-04-10 323/week @ 2024-04-17 380/week @ 2024-04-24 269/week @ 2024-05-01 541/week @ 2024-05-08 365/week @ 2024-05-15 349/week @ 2024-05-22 210/week @ 2024-05-29 349/week @ 2024-06-05 160/week @ 2024-06-12 316/week @ 2024-06-19 317/week @ 2024-06-26

1,188 每月下载次数
用于 19 个 Crates(17 个直接使用)

Apache-2.0

1.5MB
44K 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)的 Unicode 国际组件(ICU)库提供的底层原生 Rust 语言绑定的库。

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

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

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

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

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

该库提供的绑定适用性有限,这意味着它可能有时不能直接使用。如果您遇到此类情况,请随时提交错误报告给我们修复。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_*crates中激活该功能。未执行此操作将导致编译结果混乱。

功能 默认值? 描述
use-bindgen 如果设置,cargo将运行bindgen根据安装的ICU库生成绑定。程序icu-config必须在$PATH中才能工作。未来可能有其他方法用于自动检测库,例如通过pkg-config
重命名 如果设置,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。

可选

  • 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。如果有人想尝试重新实现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]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.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,以刷新目录 rust_icu_sys/bindgen 中的静态生成的 bindgen 文件(命名格式为 lib_XX.rs,其中 XX 是 ICU 版本,例如 67),这些文件在关闭 bindgen 功能时使用。

调用此 make 目标将修改 lib_XX.rs 文件的新版本。创建一个 pull request 并检查它们。

有关为何需要此操作的更多信息,请参阅 bindgen README.md

依赖项

~0.4–1.1MB
~25K SLoC