curiousdannii
curiousdannii

Reputation: 2010

How can you link a Rust library with a C app into one WASM file using Emscripten?

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.)

Upvotes: 2

Views: 661

Answers (1)

curiousdannii
curiousdannii

Reputation: 2010

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)

Upvotes: 2

Related Questions