在 Windows 上使用 emscripten 将 Rust 编译为 WebAssembly 时出错

koc*_*fan 4 windows rust emscripten webassembly rustup

我只是尝试在 Windows 上使用 emscripten 将 Rust 示例项目编译为 WebAssembly,但它会导致错误。我该如何修复它?

我做了什么:

  1. 安装emscripten
>git clone https://github.com/emscripten-core/emsdk.git
>cd emsdk
>git pull
>emsdk install latest
>emsdk activate latest
>emsdk_env.bat
Run Code Online (Sandbox Code Playgroud)
  1. 安装 rustup 从https://www.rust-lang.org/ja/tools/install下载 rustup-init.exe 并运行它
  2. 通过 rustup 安装 wasm32 目标
>rustup target add wasm32-unknown-emscripten
Run Code Online (Sandbox Code Playgroud)
  1. 创建示例项目
>cargo new --bin web_assembly
>cd web_assembly
Run Code Online (Sandbox Code Playgroud)
  1. 尝试编译,但出现错误
>cargo build --target wasm32-unknown-emscripten
   Compiling web_assembly v0.1.0 (F:\github\rusttest\web_assembly)
error: linking with `emcc.bat` failed: exit code: 1
  |
  = note: "cmd" "/c" "emcc.bat" "-s" "DISABLE_EXCEPTION_CATCHING=0" "-L" "C:\\Users\\Username\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\wasm32-unknown-emscripten\\lib" "-L" "C:\\Users\\Username\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\wasm32-unknown-emscripten\\lib\\self-contained" "F:\\github\\rusttest\\web_assembly\\target\\wasm32-unknown-emscripten\\debug\\deps\\web_assembly.web_assembly.egwz9uoo-cgu.0.rcgu.o" "F:\\github\\rusttest\\web_assembly\\target\\wasm32-unknown-emscripten\\debug\\deps\\web_assembly.web_assembly.egwz9uoo-cgu.1.rcgu.o" "F:\\github\\rusttest\\web_assembly\\target\\wasm32-unknown-emscripten\\debug\\deps\\web_assembly.web_assembly.egwz9uoo-cgu.2.rcgu.o" "F:\\github\\rusttest\\web_assembly\\target\\wasm32-unknown-emscripten\\debug\\deps\\web_assembly.web_assembly.egwz9uoo-cgu.3.rcgu.o" "F:\\github\\rusttest\\web_assembly\\target\\wasm32-unknown-emscripten\\debug\\deps\\web_assembly.web_assembly.egwz9uoo-cgu.4.rcgu.o" "F:\\github\\rusttest\\web_assembly\\target\\wasm32-unknown-emscripten\\debug\\deps\\web_assembly.web_assembly.egwz9uoo-cgu.5.rcgu.o" "F:\\github\\rusttest\\web_assembly\\target\\wasm32-unknown-emscripten\\debug\\deps\\web_assembly.web_assembly.egwz9uoo-cgu.6.rcgu.o" "F:\\github\\rusttest\\web_assembly\\target\\wasm32-unknown-emscripten\\debug\\deps\\web_assembly.web_assembly.egwz9uoo-cgu.7.rcgu.o" "-o" "F:\\github\\rusttest\\web_assembly\\target\\wasm32-unknown-emscripten\\debug\\deps\\web_assembly.js" "-s" "EXPORTED_FUNCTIONS=[\"_main\",\"_rust_eh_personality\"]" "F:\\github\\rusttest\\web_assembly\\target\\wasm32-unknown-emscripten\\debug\\deps\\web_assembly.3a2jxscq1lvbzwaf.rcgu.o" "-O0" "--memory-init-file" "0" "-g4" "-s" "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]" "-L" "F:\\github\\rusttest\\web_assembly\\target\\wasm32-unknown-emscripten\\debug\\deps" "-L" "F:\\github\\rusttest\\web_assembly\\target\\debug\\deps" "-L" "C:\\Users\\Username\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\wasm32-unknown-emscripten\\lib" "C:\\Users\\Username\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\wasm32-unknown-emscripten\\lib\\libstd-28368703ab79076a.rlib" "C:\\Users\\Username\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\wasm32-unknown-emscripten\\lib\\libpanic_unwind-c6cbccdff18b55f7.rlib" "C:\\Users\\Username\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\wasm32-unknown-emscripten\\lib\\librustc_demangle-a5ffc5310c14c91c.rlib" "C:\\Users\\Username\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\wasm32-unknown-emscripten\\lib\\libhashbrown-08c349e57dac68c0.rlib" "C:\\Users\\Username\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\wasm32-unknown-emscripten\\lib\\librustc_std_workspace_alloc-ce3363c7b27912b6.rlib" "C:\\Users\\Username\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\wasm32-unknown-emscripten\\lib\\libunwind-686deac84d1c117a.rlib" "C:\\Users\\Username\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\wasm32-unknown-emscripten\\lib\\libcfg_if-1aefc0615f4a87c4.rlib" "C:\\Users\\Username\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\wasm32-unknown-emscripten\\lib\\liblibc-35a51890c8428321.rlib" "C:\\Users\\Username\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\wasm32-unknown-emscripten\\lib\\liballoc-d41456f5d5a426f6.rlib" "C:\\Users\\Username\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\wasm32-unknown-emscripten\\lib\\librustc_std_workspace_core-2a7cc4e4deb2c4e8.rlib" "C:\\Users\\Username\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\wasm32-unknown-emscripten\\lib\\libcore-997b7450818c8186.rlib" "C:\\Users\\Username\\.rustup\\toolchains\\stable-x86_64-pc-windows-msvc\\lib\\rustlib\\wasm32-unknown-emscripten\\lib\\libcompiler_builtins-68f9d21fef2c27f2.rlib" "-l" "c" "-s" "ERROR_ON_UNDEFINED_SYMBOLS=1" "-s" "ASSERTIONS=1" "-s" "ABORTING_MALLOC=0" "-Wl,--fatal-warnings"
  = note: shared:INFO: (Emscripten: Running sanity checks)
          emcc: warning: please replace -g4 with -gsource-map [-Wdeprecated]
          error: undefined symbol: __gxx_personality_v0 (referenced by top-level compiled C/C++ code)
          warning: Link with `-s LLD_REPORT_UNDEFINED` to get more information on undefined symbols
          warning: To disable errors for undefined symbols use `-s ERROR_ON_UNDEFINED_SYMBOLS=0`
          warning: ___gxx_personality_v0 may need to be added to EXPORTED_FUNCTIONS if it arrives from a system library
          Error: Aborting compilation due to previous errors
          emcc: error: 'F:/github/emsdk/node/14.15.5_64bit/bin/node.exe F:\github\emsdk\upstream\emscripten\src\compiler.js C:\Users\Username\AppData\Local\Temp\tmpang8muuo.txt' failed (1)


error: aborting due to previous error

error: could not compile `web_assembly`

To learn more, run the command again with --verbose.
Run Code Online (Sandbox Code Playgroud)

工具版本:

>emcc.bat --version
emcc (Emscripten gcc/clang-like replacement + linker emulating GNU ld) 2.0.20-git (8ed0f4fee2abd04923c2fd2bf44835169ce2ac2e)
Copyright (C) 2014 the Emscripten authors (see AUTHORS.txt)
This is free and open source software under the MIT license.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

>rustup --version
rustup 1.24.1 (a01bd6b0d 2021-04-27)
info: This is the version for the rustup toolchain manager, not the rustc compiler.
info: The currently active `rustc` version is `rustc 1.52.1 (9bc8c42bb 2021-05-09)`
Run Code Online (Sandbox Code Playgroud)

nos*_*-cz 9

如果您想要/需要 emscripten(使用基于 c 或 c++ 的板条箱或享受工作矮人调试),这里是如何修复构建错误。

错误原因描述如下:https://github.com/rust-lang/rust/issues/85821

解决方法是:

为缺失的函数创建存根(保存为文件 gxx_personality_v0_stub.cpp):

#include "unwind.h"
#include "stdint.h"

extern "C" _Unwind_Reason_Code __gxx_personality_v0   (int version, _Unwind_Action actions, uint64_t exceptionClass, _Unwind_Exception* unwind_exception, _Unwind_Context* context) {
    return  _URC_NO_REASON;
}
Run Code Online (Sandbox Code Playgroud)

使用 emcc 构建:

emcc -c gxx_personality_v0_stub.cpp
Run Code Online (Sandbox Code Playgroud)

创建/修改 .cargo/config 文件:

[build]
rustflags = ["-C", "link-args=gxx_personality_v0_stub.o"]
Run Code Online (Sandbox Code Playgroud)

享受最新的 Rust(使用 v1.55.0 测试)和 emscripten (v2.0.29)

注意:恐慌时堆栈展开不适用于此存根。但由于该函数无论如何都在 emscripten 中被存根,因此您不会丢失任何功能。


cai*_*cuk 7

您还可以使用EMCC_CFLAGS作为解决方法:

EMCC_CFLAGS="-s ERROR_ON_UNDEFINED_SYMBOLS=0 --no-entry" cargo build --target wasm32-unknown-emscripten
Run Code Online (Sandbox Code Playgroud)

在旧版本中,此标志称为EMMAKEN_CFLAGS

EMMAKEN_CFLAGS="-s ERROR_ON_UNDEFINED_SYMBOLS=0 --no-entry" cargo build --target wasm32-unknown-emscripten
Run Code Online (Sandbox Code Playgroud)


小智 5

Emscripten 使用树尖 LLVM,这可能与 Rust 使用的更稳定的 LLVM 版本不兼容。这意味着您必须使用特定版本的 Emscripten 和与 Rust 的 LLVM 版本密切匹配的 LLVM,而不是使用latest.

自 Rust 52 以来,与 Rust 的 LLVM 最匹配的 Emscripten 版本是 Emscripten 2.0.13,所以我会尝试使用它。

记录和跟踪 Emscripten 最佳使用版本的最佳资源是https://blog.therocode.net/2020/10/a-guide-to-rust-sdl2-emscripten,尽管它尚未针对 Rust 52 进行更新+。