I have a project that links a C library with a C app using Emscripten. I would like to replace the C library with a library written in Rust. How can this be accomplished?
I know that there are two relevant WASM targets in Rust, the normal wasm32-unknown-unknown
one and the wasm32-unknown-emscripten
one. I'm guessing the latter target is necessary for it to work with the Emscripten compiler? But how do I tell Emscripten to use a .wasm library rather than a .a library?
There may be other ways of linking Rust and C code together into a .wasm but I think I do need to stick with Emscripten as I require its Asyncify feature (and in the future will use its WASMFS system too.)
This is actually quite straightforward!
So first, make sure your Rust project is set to build a static library:
[lib]
crate-type=["staticlib"]
Then compile your Rust project with the correct target, wasm32-unknown-emscripten
:
cargo build --target=wasm32-unknown-emscripten
Then you can simply link the static lib into your C/C++ app. Note that you'll probably want to use a variable to handle the different paths for dev and release builds. I'm using CMake:
if (${CMAKE_BUILD_TYPE} STREQUAL Release)
set(REMGLK_RS_LIB_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}/remglk/target/wasm32-unknown-emscripten/release)
else()
set(REMGLK_RS_LIB_FOLDER ${CMAKE_CURRENT_SOURCE_DIR}/remglk/target/wasm32-unknown-emscripten/debug)
endif()
target_link_libraries(app_target ${REMGLK_RS_LIB_FOLDER}/libremglk_capi.a)
Lastly, I needed to change the linker language to C++, as otherwise using panic!()
seems to result in exception errors when the final app is only C, not C++. Depending on what features of Rust you use this may not be necessary.
set_target_properties(app_target PROPERTIES LINKER_LANGUAGE CXX)