wasm32-unknown-emscripten
层级:2
wasm32-unknown-emscripten
目标是一个 WebAssembly 编译目标,它使用 Emscripten 编译器工具链。Emscripten 是一个 C/C++ 工具链,旨在尽可能轻松地将为 Linux 编写的 C/C++ 代码移植到 Web 或其他 JavaScript 运行时(如 Node)上运行。因此,它提供了 POSIX 兼容的 (musl) libc
和 libstd
实现以及许多 Linux API,可以访问 OpenGL 和 SDL API,并且能够运行任意 JavaScript 代码,所有这些都基于使用 JS 胶水代码的 Web API。借助 wasm32-unknown-emscripten
目标,Rust 代码可以与 Emscripten 的生态系统、C/C++ 和 JS 代码以及 Web API 进行互操作。
此目标的一个现有用户是 pyodide
项目,该项目使用 Emscripten 在 WebAssembly 中提供 Python 运行时,并将用 Rust 编写的 Python 扩展模块编译为 wasm32-unknown-emscripten
目标。
如果您想生成不需要访问 Web API 或 Rust 标准库的独立 WebAssembly 二进制文件,那么 wasm32-unknown-unknown
目标可能更适合您。但是,wasm32-unknown-unknown
不(容易)支持与 C/C++ 代码的互操作。如果您想使用此目标与 JavaScript 进行互操作,请参考 wasm-bindgen crate。
与 Emscripten 类似,WASI 目标 wasm32-wasip1
和 wasm32-wasip2
也提供对主机环境的访问,支持与 C/C++(和其他语言)的互操作,并支持大多数 Rust 标准库。虽然 WASI 目标可以在不同的主机(Web 和非 Web)之间移植,但 WASI 没有访问 Web API 的标准方法,而 Emscripten 可以从 WASM 运行任意 JS 并访问许多 Web API。如果您仅以 Web 为目标并且需要访问 Web API,则 wasm32-unknown-emscripten
目标可能更可取。
目标维护者
- Hood Chatham,https://github.com/hoodmane
- Juniper Tyree,https://github.com/juntyr
要求
此目标是交叉编译的。必须安装 Emscripten 编译器工具链 emcc
才能为此目标链接 WASM 二进制文件。您可以使用以下命令安装 emcc
:
git clone https://github.com/emscripten-core/emsdk.git --depth 1
./emsdk/emsdk install 3.1.68
./emsdk/emsdk activate 3.1.68
source ./emsdk/emsdk_env.sh
有关更多详细信息和说明,请参阅 https://emscripten.webassembly.net.cn/docs/getting_started/downloads.html。
构建目标
可以通过以下方式构建此目标:
- 配置要构建的
wasm32-unknown-emscripten
目标。 - 确保 LLVM 中未禁用
WebAssembly
目标后端。
这些都通过 config.toml
选项进行控制。应该可以在任何平台上构建此目标。最小示例配置将是
[llvm]
targets = "WebAssembly"
[build]
build-stage = 1
target = ["wasm32-unknown-emscripten"]
构建 Rust 程序
可以通过 rustup 添加此目标来编译 Rust 程序
$ rustup target add wasm32-unknown-emscripten
然后使用目标进行编译
$ rustc foo.rs --target wasm32-unknown-emscripten
$ file foo.wasm
交叉编译
此目标可以从任何主机进行交叉编译。
Emscripten ABI 兼容性
Emscripten 编译器工具链不遵循语义版本控制方案,该方案清楚地指示何时可以对 ABI 进行重大更改。此外,Emscripten 即使对于单个 Emscripten 版本,也会根据使用的链接器标志(例如 -fexceptions
和 -sWASM_BIGINT
)提供许多不同的 ABI。如果 ABI 不匹配,您的代码可能会表现出未定义的行为。
为确保您的 Rust 代码、Rust 标准库和为 Emscripten 编译的其他代码的 ABI 都匹配,您应该使用本地 Emscripten 版本和设置重建 Rust 标准库:
cargo +nightly -Zbuild-std build
如果您仍然想使用 rustup 中的预编译 std
,则应确保本地 Emscripten 与 Rust 使用的版本匹配,并注意您编译 Rust 代码时使用的任何 -C link-arg
。
测试
此目标在 rust-lang/rust 存储库的 CI 中没有经过广泛测试。例如,可以使用以下命令在本地进行测试:
./x.py test --target wasm32-unknown-emscripten --skip src/tools/linkchecker
要运行这些测试,您的 $PATH
中需要有 emcc
和 node
。例如,您可以通过按照 https://github.com/nvm-sh/nvm#install--update-script 中的说明使用 nvm
安装 node
。
如果您需要测试 一般 WebAssembly 兼容性,建议测试 wasm32-wasip1
目标。
有条件地编译代码
建议使用以下命令为此目标有条件地编译代码:
#[cfg(target_os = "emscripten")]
有时可能需要为 不 使用 emscripten 的 WASM 目标有条件地编译代码,这可以通过以下方式实现:
#[cfg(all(target_family = "wasm", not(target_os = "emscripten)))]
启用的 WebAssembly 功能
WebAssembly 是一个不断发展的标准,它会随着时间的推移添加新的功能,例如新的指令。此目标支持的 WebAssembly 功能的默认集也会随着时间的推移而变化。wasm32-unknown-emscripten
目标继承了 LLVM 的默认设置,该设置通常(但不一定)也与 Emscripten 的默认设置匹配。在链接时,emcc
将链接器配置为使用 Emscripten 的设置。
请参考 wasm32-unknown-unknown
目标的文档,了解 Rust 默认启用哪些 WebAssembly 功能,如何禁用功能以及如何根据启用了哪些功能有条件地编译 Rust 代码。
请注意,除非使用 -Cpanic=abort
编译 Rust 代码,否则为 wasm32-unknown-emscripten
编译的 Rust 代码目前默认启用 -fexceptions
(JS 异常)。-fwasm-exceptions
(WASM 异常) 尚不支持,请参阅 https://github.com/rust-lang/rust/issues/112195。
请参考 Emscripten ABI 兼容性 部分,以确保启用的功能不会导致您的 Rust 代码、预编译的 Rust 标准库和为 Emscripten 编译的其他代码之间出现 ABI 不匹配。