如何使用 Emscripten 编译的程序中的 wasm-bindgen?
Posted
技术标签:
【中文标题】如何使用 Emscripten 编译的程序中的 wasm-bindgen?【英文标题】:How can I use wasm-bindgen from a program compiled with Emscripten? 【发布时间】:2022-01-23 19:07:24 【问题描述】:我正在尝试将包含由 wasm-bindgen 生成的代码的 Rust 库与我想用 Emscripten 编译的用 C 编写的程序链接。我的 MRE 如下:
在 Rust 方面,我有 Cargo.toml
:
[package]
name = "rust_project"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["staticlib"]
[dependencies]
wasm-bindgen="0.2"
在lib.rs
我有:
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C"
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
#[no_mangle]
pub extern "C" fn call_from_c()
log("Hello, World!");
作为第一步,我使用cargo build --target wasm32-unknown-unknown
编译它,生成librust_project.a
。然后我使用main.c
设置了以下C 项目:
/* forward declare the function from Rust */
void call_from_c();
/* call the function from main */
int main()
call_from_c();
return 0;
和CMakeLists.txt
:
cmake_minimum_required(VERSION 3.5)
project(c_project)
add_executable(c_project main.c)
target_link_libraries(c_project /path/to/librust_project.a)
最后,我尝试使用 Emscripten 工具链将它们组合在一起,如下所示:
cmake -DCMAKE_TOOLCHAIN_FILE=path/to/Emscripten.cmake ../
make
这是链接阶段出现问题的地方,emcc
报告 __wbg_log_941ab916ed5a24bd
是一个未定义的符号。我怀疑这个符号(以及其他符号)正在作为优化工作的一部分被删除,但我不确定在哪个阶段或如何禁用此优化。
在 CMake 中添加以下链接器选项会导致编译时出现关于未定义符号的警告:
target_link_libraries(c_project
path/to/librust_project.a
"-s EXPORTED_FUNCTIONS=[\"_main\",\"___wbg_log_941ab916ed5a24bd\"]"
"-s ERROR_ON_UNDEFINED_SYMBOLS=0")
但我认为这些缺少的符号是有问题的,当我在 c_project.wasm
上运行 wasm-bindgen(CLI 工具)时,我收到以下错误:
import of `__wbg_log_941ab916ed5a24bd` doesn't have an adapter listed
如何防止 wasm-bindgen 导入/导出的函数在此过程中被剥离?
【问题讨论】:
【参考方案1】:这是一个正在进行中的答案,希望我能在不久的将来变成一个完整的答案。如果不是,它至少可以作为其他走这条路的人的起点。
我一直致力于通过删除 CMake 和 Emscripten 并直接使用 Clang 进行编译,从而使我的 MWE 更加精简。这已经足够了,因为我不需要担心这个 MWE 中的标准库。
然后我的编译命令变成:
clang -Wall --target=wasm32-unknown-unknown --no-standard-libraries \
-Wl,--export-all \
-Wl,--no-entry \
-Wl,-L/path/to/librust_project_a
-Wl,-lrust_project
-o main.wasm main.c
值得注意的是,我可以通过添加/删除 --export-all
链接器参数来触发以下 wasm-bindgen 错误。建议 LLVM 链接器负责在使用 wasm-bindgen 处理之前删除此部分。
import of `__wbg_log_941ab916ed5a24bd` doesn't have an adapter listed
【讨论】:
以上是关于如何使用 Emscripten 编译的程序中的 wasm-bindgen?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用库导入编译 C 文件到 webassembly 文件(Emscripten)
如何让 JetBrains CLion 中的“cmake”工作来编译 Emscripten/WebAssembly?
Emscripten:我如何编译带有像 immintrin.h 这样的内在头文件的 c 文件?