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 通用定义的目标,因此我们希望在编译到wasm32-unknown-unknown
时,Rust 和 C/C++ 代码可以互操作。
但是,您会注意到,上述两个目标在某种程度上是相互矛盾的。为了尝试一次性解决这两个用例,我们定义了一个目标,它(滥用)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 代码互操作。
- 所有 Rust 代码都需要使用
-C target-feature=-crt-static
进行编译,表明不会使用 Rust sysroot 中捆绑的 C 标准库。 - 如果您正在使用 rustc 构建链接的工件,那么您需要将
-C linker
指定为支持wasm32-wasip1-threads
并配置了wasm32-wasip1-threads
sysroot 的clang
二进制文件。这将导致 Rust 代码链接到指定的clang
提供的 libc.a。 - 如果您正在构建 staticlib 并在其他地方集成 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 的路径 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 测试套件
- 确保已安装 wamr、wasmtime 或其他支持
wasi-threads
的引擎,并且可以在$PATH
环境变量中找到。 - 克隆 master 分支。
- 应用这样的 更改,并使用步骤 1 中的引擎。
- 运行
./x.py test --target wasm32-wasip1-threads tests/ui
并保存失败的测试列表。 - 检出带有更改的分支。
- 应用这样的 更改,并使用步骤 1 中的引擎。
- 运行
./x.py test --target wasm32-wasip1-threads tests/ui
并保存失败的测试列表。 - 对于失败的两个测试列表,运行
cat list | sort > sorted_list
并将其与diff sorted_list1 sorted_list2
进行比较。
有条件地编译代码
建议使用以下方式为此目标有条件地编译代码
#[cfg(all(target_os = "wasi", target_env = "p1", target_feature = "atomics"))]
在 Rust 1.80 之前,未设置 target_env = "p1"
键。目前,target_feature = "atomics"
仅限 Nightly 版本。请注意,随着目标变得更加稳定,检测此目标所需的精确 #[cfg]
可能会发生变化。
启用的 WebAssembly 功能
为编译启用的默认 WebAssembly 功能集除了 wasm32-unknown-unknown
启用的功能外,还包括另外两个功能
bulk-memory
atomics
有关功能的更多信息,请参阅 wasm32-unknown-unknown
的文档,但请注意,LLVM 中的 mvp
CPU 不支持此目标,因为它要求启用 bulk-memory
、atomics
和 mutable-globals
。