Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can you compile a Rust library to target asm.js?

I've got a Rust library with the following usual structure:

Cargo.toml
src
 |--lib.rs
.cargo
 |--config (specifies target=asmjs-unknown-emscripten)
target
 |......

When I do cargo build, I get a new directory under target called asmjs-unknown-emscripten, but the .js files that I'd expect are not there.

As this user notes, you've got to do something special to export functions to asm.js besides marking them public:

Basically you have this boilerplate right now:

#[link_args = "-s EXPORTED_FUNCTIONS=['_hello_world']"]
extern {}

fn main() {}

#[no_mangle]
pub extern fn hello_world(n: c_int) -> c_int {
    n + 1
}

Then you can use this in your javascript to access and call the function:

var hello_world = cwrap('hello_world', 'number', ['number']);

console.log(hello_world(41));

However, Rust complains about the #[link_args...] directive as deprecated. Is there any documentation out there that can explain how this works?

like image 982
user1935361 Avatar asked Jan 05 '17 19:01

user1935361


1 Answers

Very interesting question! I was running into similar dependency issues with fable.

I have checked Compiling Rust to your Browser - Call from JavaScript, Advanced Linking - Link args and How to pass cargo linker args however was not able to use cargo in the same way as rustc --target asmjs-unknown-emscripten call-into-lib.rs.

The closer I was able to get was to run both cargo and rustc like

cd lib1
cargo build --target asmjs-unknown-emscripten
rustc --target=asmjs-unknown-emscripten src\lib.rs
cd ..

cd lib2
cargo build --target asmjs-unknown-emscripten
rustc --target=asmjs-unknown-emscripten src\lib.rs --extern lib1=..\lib1\target\asmjs-unknown-emscripten\debug\liblib1.rlib
cd ..

cd lib3
cargo build --target asmjs-unknown-emscripten
rem rustc --target=asmjs-unknown-emscripten src\lib.rs --extern webplatform=..\lib3\target\asmjs-unknown-emscripten\debug\deps\libwebplatform-80d107ece17b262d.rlib
rem the line above fails with "error[E0460]: found possibly newer version of crate `libc` which `webplatform` depends on"
cd ..

cd app
cargo build --target asmjs-unknown-emscripten
cd ..

see the so-41492672-rust-js-structure. It allows to have several libraries that compile together to the JavaScript in the final application.

I still think some manual linking would help. Would be interested to know.

P.S. to see what rustc uses to link, you can pass -Z print-link-args to it.

like image 195
davidpodhola Avatar answered Nov 01 '22 13:11

davidpodhola