Skip to content

Cross-compiling from Rust doesn't work as expected #867

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
chicoxyzzy opened this issue Jan 3, 2017 · 6 comments
Closed

Cross-compiling from Rust doesn't work as expected #867

chicoxyzzy opened this issue Jan 3, 2017 · 6 comments

Comments

@chicoxyzzy
Copy link
Member

chicoxyzzy commented Jan 3, 2017

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 <script src="the.js"></script> 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:

@kripken
Copy link
Member

kripken commented Jan 4, 2017

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

@chicoxyzzy
Copy link
Member Author

chicoxyzzy commented Jan 4, 2017

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 :(

@kripken
Copy link
Member

kripken commented Jan 4, 2017

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.

@chicoxyzzy
Copy link
Member Author

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.

@chicoxyzzy
Copy link
Member Author

chicoxyzzy commented Jan 4, 2017

@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

@m4b
Copy link

m4b commented Jan 10, 2017

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants