¿Cómo puedo utilizar wasm-bindgen desde un programa compilado con Emscripten?
Estoy intentando vincular una biblioteca de Rust que contiene código generado por wasm-bindgen con un programa escrito en C que me gustaría compilar con Emscripten. Mi MRE es el siguiente:
En el lado de Rust, tengo Cargo.toml
:
[package]
name = "rust_project"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["staticlib"]
[dependencies]
wasm-bindgen="0.2"
y en lib.rs
tengo:
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!");
}
Como primer paso, compilo esto con cargo build --target wasm32-unknown-unknown
, lo cual produce un librust_project.a
. Luego, configuro el siguiente proyecto en C con main.c
:
/* Declarar la función de Rust */
void call_from_c();
/* Llamar a la función desde main */
int main() {
call_from_c();
return 0;
}
y 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)
Finalmente, intento juntarlo todo utilizando la herramienta Emscripten de la siguiente manera:
cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/Emscripten.cmake ../
make
Aquí es donde algo parece salir mal en la etapa de enlace, ya que emcc
informa que __wbg_log_941ab916ed5a24bd
es un símbolo indefinido. Sospecho que este símbolo (entre otros) se está eliminando como parte de un esfuerzo de optimización, pero no estoy seguro en qué etapa ni cómo puedo desactivar esta optimización.
Agregar las siguientes opciones de enlazador en CMake resulta en una compilación con una advertencia sobre el símbolo indefinido:
target_link_libraries(c_project
/path/to/librust_project.a
"-s EXPORTED_FUNCTIONS=[\"_main\",\"___wbg_log_941ab916ed5a24bd\"]"
"-s ERROR_ON_UNDEFINED_SYMBOLS=0"
)
Pero creo que estos símbolos faltantes son problemáticos y cuando ejecuto wasm-bindgen (la herramienta de línea de comandos) en c_project.wasm
, obtengo el siguiente error:
import of `__wbg_log_941ab916ed5a24bd` doesn't have an adapter listed
¿Cómo puedo evitar que las funciones importadas/exportadas de wasm-bindgen sean eliminadas durante este proceso?
davy.ai
Para evitar que las funciones importadas/exportadas de wasm-bindgen sean eliminadas durante el proceso de enlace, puedes utilizar la bandera del enlazador
--import-memory
y agregarextern wasm_bindgen::__wbindgen_malloc, extern wasm_bindgen::__wbindgen_free
a la lista de funciones exportadas.Para lograr esto, puedes modificar tu archivo
CMakeLists.txt
de la siguiente manera:Este archivo
CMakeLists.txt
establece la arquitectura objetivo enwasm32
y la herramienta de compilación en Emscripten. El comandotarget_link_libraries
incluye la bandera del enlazador--import-memory
y exporta las funciones necesarias de wasm-bindgen (__wbg_log_941ab916ed5a24bd
,__wbindgen_malloc
y__wbindgen_free
) además de la funciónmain
. Por último, el comandoset_target_properties
establece la extensión y formato del archivo de salida como HTML y WebAssembly, respectivamente.Con estas modificaciones, la biblioteca Rust que contiene el código generado por wasm-bindgen debería enlazarse correctamente con el programa C, y las funciones importadas/exportadas de wasm-bindgen no deberían eliminarse durante el proceso de enlace.