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

sys rust_icu_sys

Unicode ICU4C 库的本地绑定

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日

#406 in 国际化 (i18n)

Download history 398/week @ 2024-03-13 382/week @ 2024-03-20 328/week @ 2024-03-27 483/week @ 2024-04-03 368/week @ 2024-04-10 347/week @ 2024-04-17 407/week @ 2024-04-24 302/week @ 2024-05-01 574/week @ 2024-05-08 388/week @ 2024-05-15 374/week @ 2024-05-22 229/week @ 2024-05-29 380/week @ 2024-06-05 187/week @ 2024-06-12 348/week @ 2024-06-19 333/week @ 2024-06-26

1,295 每月下载量
用于 27 个crate (25 直接)

Apache-2.0

1MB
43K 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 上找到。

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

为什么包装ICU(而不是做其他任何事情)?

  • Rust语言的国际化页面确认,Rust中的ICU支持不太一致,因此拥有一个功能齐全的包装器有助于推进技术进步。

  • Fuchsia这样的项目已经依赖于ICU,并且通过Rust绑定提供了一种简单的方法来使用Unicode算法,而不需要承担更多依赖。

  • 与ICU4X等项目的接口合作可能允许未来实现无缝过渡到全Rust实现。

仓库结构

该仓库组织为一个Rust包的工作空间。每个包对应于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版本,以确保包装器的稳定性。

兼容性

兼容性保证如下:

  1. 对所有感兴趣的功能组合执行针对过去三个主要ICU库版本的自动测试。
  2. 对文档.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文件中执行一些库检测,并调整构建过程以适应您的构建环境。然而,由于不是每个开发环境都会使用相同的设置,我们选择提供以下某些功能作为配置选项。

虽然我们的意图是保持以下功能列表与实际列表保持更新,但该列表可能偶尔会过时。

要使用任何功能,您需要在您打算使用的所有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功能未使用时才有意义;否则它不起作用。
静态 如果设置,将静态链接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用户指南

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

    有关安装说明,请参阅 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

请参阅上方的 可选依赖部分

要运行基于 Docker 的 rust_icu 源代码的密封构建和测试,请执行以下命令

make docker-test

这将运行在您本地机器上基于 Docker 的源代码构建和测试。这是一个测试您的代码是否与 ICU 的特定参考版本兼容的好方法。

先验知识

已经考虑了许多先验知识。

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

另请参阅

假设

对于 ICU 绑定有几种竞争方法。但是,根据至少基于 rust 的 RFC 存储库中的信息,Rust 中的 ICU 支持工作仍在进行中。

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

  • 我们需要一个完整、可重用且无需痛点的 ICU 低级库。

    这意味着我们必须依赖于外部 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镜像有点大,因此需要几个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方法,就应该能够为ICU库的新版本生成库包装器,前提是底层的C API没有太大差异。

为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 文件的新版本。提交一个拉取请求并检查它们。

有关为什么需要此操作的信息,请参阅 bindgen README.md

依赖关系