Binaryen: Cross-compiling from Rust doesn't work as expected

Created on 4 Jan 2017  路  6Comments  路  Source: WebAssembly/binaryen

I was following instructions from https://users.rust-lang.org/t/compiling-to-the-web-with-rust-and-emscripten/7627 and had no luck in generating working example.

  • Resulting JS file doesn't work on node. Error is
no binaryen method succeeded. consider enabling more options, like interpreting, if you want that: https://github.com/kripken/emscripten/wiki/WebAssembly#binaryen-methods
  • Running wasm file on Node doesn't work because latest Node doesn't expose Memory property of WebAssembly object
  • Looking into wast file I don't see "Hello, Emscripten!" string anywhere
  • Then I've created index.html with such content:
<script type='text/javascript'>
 fetch('hello.wasm')
  .then(response => response.arrayBuffer())
  .then(buffer => WebAssembly.compile(buffer))
  .then(console.log)
</script>

and ran Python's SimpleHTTPServer. Running this in latest Chrome Canary with WebAssembly enabled doesn't do anything while not throwing errors and showing an empty wasm module object.

So I'm not sure if Rust code cross-compiles to correct wasm module at all for now (using rustc 1.14.0 and emcc 1.37.0 / 1.37.1). Am I doing something wrong?

@kripken's answer (from here)

In general you can open an issue on the binaryen tracker (often it's the right place, if not that's fine too). Regarding your issues:

  • Yes, node.js doesn't have wasm support yet. You can use SpiderMonkey or V8 shells (very latest versions), or nightly/canary versions of the browsers. Or, enable the interpreter, which will work everywhere.
  • You should see the string in the wast, that is surprising. It should be in the memory segments, near the top of the file. Are there no memory segments? Earlier binaryen versions didn't use them, but we should now.
  • You can't load the wasm by yourself - it isn't standalone (there is work towards standalone wasm, which perhaps rust can use eventually). The JS code knows how to load it and run it. Try to just create an html page with in it.

@kripken I've tried to run generated JS file in browser and there is an error

Assertion failed: on the web, we need the wasm binary to be preloaded and set on Module['wasmBinary']. emcc.py will do that for you when generating HTML (but not JS)

Also there is no "Hello, Emscripten!" in generated JS file. And there are no memory segments in wast as far as I can see.

Rust source file:

Generated files:

All 6 comments

I think the string is in the (data line, it's just encoded so it doesn't look normal. If you open the wasm (binary) in an editor, though, you will see it.

For that assertion, we should be improving it soon, but meanwhile if you can emit HTML instead of JS, it will work (the html will set up the binary for you; alternatively, you can set it up yourself manually).

Thank you for your answer!

In fact my goal is to create a wasm module (using Rust) with simple function exported to use from JS via JavaScript API in Canary / FF Nightly

Maybe there are some articles / docs / blog posts which can help?


BTW, how can I emit HTML? Should I call rustc with some Binaryen flags passed to it somehow?


Sorry for my newbie questions :(

To emit html, you just call emcc with -o output.html, the suffix tells it what to emit. Not sure where that fits in with rustc though.

If all you want is a wasm module that you use directly, and it doesn't need JS integration, and it doesn't need libc or other system libs (which often needs JS, e.g. to print), then you can read the "standalone wasm". It has a full example, that maybe you can connect rustc to? But the standalone stuff is experimental, so expect breakage.

To emit html, you just call emcc with -o output.html, the suffix tells it what to emit. Not sure where that fits in with rustc though.

It was as simple as

rustc --target=wasm32-unknown-emscripten hello.rs -o output.html

馃帀

it doesn't need libc or other system libs

I just need arithmetic operations without any I/O. Standalone wasm is exactly what I need. Thank you! I'll try it.

@brson is there any way to pass -s option to emcc? I believe that -s "BINARYEN_METHOD='interpret-binary'" should be passed to run compiled JS in Node.js

@chicoxyzzy no i don't think so, this is the same old tired issue of not being able to pass link arguments to the "system" linker (in this case emcc) via cargo.

Of course, you can:

  1. run the cargo command with -vv
  2. cause it to fail
  3. copy the "linker" command
  4. add your -s "BINARYEN_METHOD='interpret-binary'" to the "link line"
  5. hit enter and it should work

Alternatively, you can perform some path hackery and have emcc automatically pass -s along with rest of the arguments.

PS: your your suggestion works by the way, thank you, I couldn't seem to find this mentioned anywhere obviously...

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ashleygwilliams picture ashleygwilliams  路  6Comments

tsangint picture tsangint  路  5Comments

Razican picture Razican  路  12Comments

kripken picture kripken  路  11Comments

MaxGraey picture MaxGraey  路  7Comments