wasm32-wasip1-threads

层级: 2

wasm32-wasip1-threads 目标是一个新的,并且仍然(截至 2023 年 7 月)是实验性的目标。此目标是 wasm32-wasip1 目标的扩展,最初称为 wasm32-wasi。它通过一组标准化的系统调用扩展了原始目标,这些系统调用旨在为 WebAssembly 二进制文件提供本机多线程功能。

注意:在 2024 年 3 月之前,此目标被称为 wasm32-wasi-preview1-threads,更早之前它被称为 wasm32-wasi-threads

目标维护者

  • Georgii Rylov,https://github.com/g0djan
  • Alex Crichton,https://github.com/alexcrichton
  • Andrew Brown,https://github.com/abrown
  • Marcin Kolny,https://github.com/loganek

要求

此目标是交叉编译的。该目标完全支持 std

此处的 Rust 目标定义在几个方面很有趣。我们希望通过此目标满足两个用例。

  • 首先,我们希望 Rust 使用该目标尽可能地轻松,理想情况下避免需要配置和安装本地 wasm32-wasip1-threads 工具链。
  • 其次,LLVM 新的 wasm 后端和 LLD 中的 wasm 支持的主要用例之一是,任何编译语言都可以与任何其他语言互操作。wasm32-wasip1-threads 目标是第一个具有可行的 C 标准库和 sysroot 通用定义的目标,因此我们希望 Rust 和 C/C++ 代码在编译为 wasm32-unknown-unknown 时能够互操作。

但是,您会注意到,上面提到的两个目标在某种程度上是相互矛盾的。为了尝试一次性解决这两个用例,我们定义了一个目标,它(滥用)了 crt-static 目标功能来指示您处于哪种情况。

不需要与 C 互操作

默认情况下,crt-static 目标功能是启用的,启用后,这意味着将使用 liblibc.rlib 中找到的 libc.a 的捆绑版本。这实际上并非旨在用于与 C 互操作,因为 Rust 的捆绑 C 库可能与外部编译的 C 库不兼容。但是,在此用例中,我们使用 rust-lld 和一些复制的 crt 启动对象文件,以确保您可以下载 Rust 的 wasi 目标,并且您就可以开始使用,无需进一步配置。总而言之,默认情况下,不需要外部依赖项。您可以直接从盒子里编译 wasm32-wasip1-threads 二进制文件。但是,您无法在此模式下可靠地与 C 代码互操作(尚未)。

需要与 C 互操作

对于第二个目标,我们重新利用了 target-feature 标志,这意味着您需要做一些事情才能使 C/Rust 代码互操作。

  1. 所有 Rust 代码都需要使用 -C target-feature=-crt-static 进行编译,这表明不会使用 Rust sysroot 中捆绑的 C 标准库。
  2. 如果您使用 rustc 构建链接的工件,那么您需要将 -C linker 指定为支持 wasm32-wasip1-threads 并且已配置了 wasm32-wasip1-threads sysroot 的 clang 二进制文件。这将导致 Rust 代码与指定的 clang 提供的 libc.a 链接。
  3. 如果您正在构建静态库并在其他地方集成 Rust 代码,那么使用 -C target-feature=-crt-static 进行编译就是您需要做的全部工作。

总而言之,默认情况下,不需要外部依赖项。您可以直接从盒子里编译 wasm32-wasip1-threads 二进制文件。但是,您无法在此模式下可靠地与 C 代码互操作(尚未)。

还要注意,目前 wasm32-wasip1-threads 目标假设存在其他合并的 wasm 提案,例如(及其 LLVM 特性标志):

  • 批量内存 - +bulk-memory
  • 可变导入全局变量 - +mutable-globals
  • 原子操作 - +atomics

此目标需要 LLVM 16。原因与链接器标志有关:在 LLVM 16 之前,不允许同时使用 --import-memory 和 --export-memory。两者都需要的原因是 WASI 当前做事方式的产物;有关更多详细信息,请参见 https://github.com/WebAssembly/WASI/issues/502。

该目标旨在与其 "C" ABI 的相应 Clang 目标匹配。

注意:由于此目标处于相对早期的阶段,因此在使用此目标时,您可能会遇到 LLVM 错误。如果遇到断言命中或发现错误,建议您在 rust-lang/rust 或理想情况下在 LLVM 本身中打开一个问题。

平台要求

运行时应支持与任何其他支持的 wasi 目标相同的 API 集,以通过 WASI 标准与主机环境进行交互。运行时还应实现 wasi-threads 提案

此目标不是稳定目标。这意味着有一些引擎实现了 wasi-threads 功能,如果它们确实实现了,则可能位于标志后面,例如

  • Wasmtime - --wasm-features=threads --wasi-modules=experimental-wasi-threads
  • WAMR - 需要使用 WAMR_BUILD_LIB_WASI_THREADS=1 构建

构建目标

用户需要安装或构建 wasi-sdk,版本为 20.0 或更高,https://github.com/WebAssembly/wasi-sdk/releases/tag/wasi-sdk-20,并指定 wasi-root 的路径到 .cargo/config.toml

[target.wasm32-wasip1-threads]
wasi-root = ".../wasi-libc/sysroot"

之后,用户可以通过将其添加到 config.toml 中的 target 列表中,或使用 -Zbuild-std 来构建它。

构建 Rust 程序

从 Rust Nightly 1.71.1(2023-08-03)开始,工件已预编译。

rustup target add wasm32-wasip1-threads --toolchain nightly

可以为该目标构建 Rust 程序。

rustc --target wasm32-wasip1-threads your-code.rs

交叉编译

此目标可以从任何主机交叉编译。

测试

目前,wasm32-wasip1-threads 的测试支持度不高,Rust 项目没有针对此目标运行任何测试。但是,可以按照以下说明手动运行 UI 测试套件。

  1. 确保已安装 wamrwasmtime 或其他支持 wasi-threads 的引擎,并且可以在 $PATH 环境变量中找到它。
  2. 克隆主分支。
  3. 应用此类 更改,并使用步骤 1 中的引擎。
  4. 运行 ./x.py test --target wasm32-wasip1-threads tests/ui 并保存失败测试的列表。
  5. 检出包含您更改的分支。
  6. 应用此类 更改,并使用步骤 1 中的引擎。
  7. 运行 ./x.py test --target wasm32-wasip1-threads tests/ui 并保存失败测试的列表。
  8. 对于两个失败测试列表,运行 cat list | sort > sorted_list 并使用 diff sorted_list1 sorted_list2 进行比较。