Skip to content
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

Help With WASM Build #332

Closed
Pebaz opened this issue Jan 16, 2021 · 19 comments
Closed

Help With WASM Build #332

Pebaz opened this issue Jan 16, 2021 · 19 comments
Assignees
Labels

Comments

@Pebaz
Copy link

Pebaz commented Jan 16, 2021

I'm just starting a second game using Rhai and Macroquad, and I can't get a hello-world example to work in WASM:

use macroquad::*;
use glam::{vec2};
use rhai::*;  // When removed, it works fine in browser


#[macroquad::main("Game")]
async fn main()
{
    let sand1 = load_texture("res/img/Bloxel-Grass1-N.png").await;
    let mut pos = vec2(0.0, 0.0);

    // When Rhai code is removed, it loads and works fine in browser
    let engine = Engine::new();
    let mut scope = Scope::new();
    let source = include_str!("scripts/P1.rhai");
    let script = engine.compile(&source).unwrap();
    engine.eval_ast_with_scope::<()>(&mut scope, &script).unwrap();

    loop
    {
        pos.x += 1.0;
        clear_background(WHITE);
        draw_texture(sand1, pos.x, pos.y, Color::new(1.0, 1.0, 1.0, 1.0));
        next_frame().await
    }
}

Working WASM Build:
image

When using Rhai, here is the error it shows in the browser console:

image

I'm building the game using:

cargo build --target wasm32-unknown-unknown

And serving it the same as without using Rhai:

basic-http-server . -a 0.0.0.0:4000

The HTML to load the bundled game:

<html lang="en">

<head>
    <meta charset="utf-8">
    <title>TITLE</title>
    <style>
        html,
        body,
        canvas {
            margin: 0px;
            padding: 0px;
            width: 100%;
            height: 100%;
            overflow: hidden;
            position: absolute;
            background: black;
            z-index: 0;
        }
    </style>
</head>

<body>
    <canvas id="glcanvas" tabindex='1'></canvas>
    <!-- Minified and statically hosted version of https://github.com/not-fl3/miniquad/blob/master/native/sapp-wasm/js/gl.js -->
    <script src="https://not-fl3.github.io/miniquad-samples/gl.js"></script>
    <script>load("/target/wasm32-unknown-unknown/debug/game.wasm");</script> <!-- Your compiled wasm file -->
</body>

</html>

Rhai version: 0.9.10 (f32_float, only_i32, no_module, unchecked)
Rustc version: rustc 1.49.0-nightly (fd542592f 2020-10-26)

Any help on how to use Rhai with WASM would be appreciated!

@schungx
Copy link
Collaborator

schungx commented Jan 17, 2021

You may look at the playground and how it is done?

@alvinhochun maybe you can give some pointers here as well?

@schungx
Copy link
Collaborator

schungx commented Jan 17, 2021

Just a a wild shot after some Googling: rustwasm/console_error_panic_hook#14

Another wild thought: Notice that all the __wbindgen_ functions do NOT end with two underscores, but the missing function __wbindgen_placeholder__ ends with __...

@alvinhochun
Copy link
Contributor

Hi Pebaz. I should clarify beforehand that I have no experience with using miniquad and/or macroquad, so I don't really know how one is supposed to use it for the web target. It looks like that miniquad is designed to be used without wasm-bindgen, and this is going to cause some complications.

While Rhai itself doesn't directly use wasm-bindgen, its current use of the instant crate does make wasm-bindgen necessary. This means you have to invoke wasm-bindgen somewhere in your build process and then make use of its JS glue, instead of just using the gl.js from miniquad. Another possible solution is that you change Cargo.toml of Rhai to remove this requirement and then modify your gl.js to make the instant crate work. (The readme of instant may help.)

I wonder if @not-fl3 can chime in?

Side note: I wasn't able to set up and compile a project that mimics yours because not all the files are provided.

@not-fl3
Copy link

not-fl3 commented Jan 17, 2021

It is a very common problem with Instant, the solution - use now feature instead of stdweb/wasm-bindgen

https://github.com/sebcrozet/instant#using-the-feature-now-without-stdweb-or-wasm-bindgen

@not-fl3
Copy link

not-fl3 commented Jan 17, 2021

From what I can tell - rhai explicitly depend on wasm-bindgen https://github.com/rhaiscript/rhai/blob/master/Cargo.toml#L102, so it looks like the only way to use it with stdweb or pure wasm32-unknown-unknown target - modify Cargo.toml and rebuild rhai.

Maybe it is possible to make wasm-bindgen optional? Maybe allow users to choose the js interop layer, just like it is done in Instant itself?

Would be nice to use rhai from crates, without Cargo.toml hacks :)

@schungx
Copy link
Collaborator

schungx commented Jan 18, 2021

now seems to to require providing a now function in JavaScript.

The best solution right now seems to be to add two new features, wasm-bindgen and stdweb that maps to instant/wasm-bindgen and instant/stdweb.

@schungx
Copy link
Collaborator

schungx commented Jan 18, 2021

@Pebaz The latest drop in master includes the wasm-bindgen and stdweb features. Try pulling from here and specify stdweb feature.

@Pebaz
Copy link
Author

Pebaz commented Jan 18, 2021

@schungx thank you so much I'll give this a shot as soon as possible!

@alvinhochun
Copy link
Contributor

Try pulling from here and specify stdweb feature.

Nah, the stdweb feature wouldn't work because it will require using the matching cargo-web tool to generate its own JS glue, which gives the same problem as with wasm-bindgen.

now seems to to require providing a now function in JavaScript.

As far as I can tell, there is no other way around it if one wants to avoid both wasm-bindgen and stdweb.

Luckily for @Pebaz, it looks like the gl.js glue code already includes it: https://github.com/not-fl3/miniquad/blob/a06b019f9387ba3e5f337a6a4fd177db84c764b3/native/sapp-wasm/js/gl.js#L597

@alvinhochun
Copy link
Contributor

It is a very common problem with Instant, the solution - use now feature instead of stdweb/wasm-bindgen

https://github.com/sebcrozet/instant#using-the-feature-now-without-stdweb-or-wasm-bindgen

Actually, from looking at the code it seems that the now feature is only needed if you want to call the free function instant::now() directly. instant::Instant::new() is available even without it (but you'd still need to provide the now function from JS when not using either wasm-bindgen or stdweb).

@schungx
Copy link
Collaborator

schungx commented Jan 18, 2021

According to the documentation of instant, it specifies that either wasm-bindgen or stdweb must be used in order to have a WASM-friendly implementation of Instant. I am not sure if it works without either...

@schungx
Copy link
Collaborator

schungx commented Jan 18, 2021

OK, from code, it seems that instant only looks at target and doesn't really depend on the wasm-bindgen or stdweb features. That's good.

Instant::now() creates the Instant type so technically speaking we need it. However, another good news is that, without either wasm-bindgen or stdweb, Instant::now() falls back to external JS now. As @alvinhochun mentions, the feature now is only required to call the now function directly.

Therefore, @Pebaz you can try building for WASM without either wasm-bindgen or stdweb!

@not-fl3
Copy link

not-fl3 commented Jan 18, 2021

now seems to to require providing a now function in JavaScript.

yes, exactly, and that is how instant suppose to works for the users who do not want to use either wasm-bindgen and stdweb.

So I believe exposing instant's now feature is equally important as exporting isntant's stdweb and wasm-bindgen feature :)

@Pebaz
Copy link
Author

Pebaz commented Jan 18, 2021

@schungx @alvinhochun @not-fl3 due to all your help I was able to successfully evaluate a Rhai script in the browser!

I forked Rhai, re-exported instant's now feature, complied it, and it worked in the browser!

Here is the change that was recommended by you guys!

I believe that it is working due to gl.js already including a now() function as @alvinhochun discovered, so a small note directing users to instant's docs might be helpful.

Thank you so much guys! I feel that you all have gone above and beyond to help me and I appreciate it greatly!

I'll definitely be evangelizing about Rhai and it's awesome maintainers! 🦀

@Pebaz Pebaz closed this as completed Jan 18, 2021
@not-fl3
Copy link

not-fl3 commented Jan 18, 2021

But it would be really nice to use crates version of rhai instead of custom a fork.
So maybe keep it open for others willing to use rhai without wasm-bindgen/stdweb?
The only change needed to make this happen - re-export instant's now feature :)

@Pebaz
Copy link
Author

Pebaz commented Jan 18, 2021

I definitely agree, if possible, it would be amazing to have the change that worked in Rhai itself rather than the custom fork! 🙂

@schungx
Copy link
Collaborator

schungx commented Jan 19, 2021

But it would be really nice to use crates version of rhai instead of custom a fork.
So maybe keep it open for others willing to use rhai without wasm-bindgen/stdweb?
The only change needed to make this happen - re-export instant's now feature :)

From the code it doesn't seem the now feature is needed because Rhai only calls Instant::now(). If neither wasm-bindgen nor stdweb are specified, it defaults to the now feature.

@Pebaz you can try pulling from this repo instead. It should work.

@not-fl3
Copy link

not-fl3 commented Jan 19, 2021

From the code it doesn't seem the now feature is needed because Rhai only calls Instant::now(). If neither wasm-bindgen nor stdweb are specified, it defaults to the now feature.

My bad, I forgot about the now fallback in instant.
I agree, it should works now, thanks for the effort in fixing this!

@Pebaz
Copy link
Author

Pebaz commented Jan 19, 2021

@schungx @not-fl3 This worked! I am pulling from master in Cargo.toml and it still works!

Thanks for all your help!

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

No branches or pull requests

4 participants