Rust journey

165 views
Skip to first unread message

Александр Гурьянов

unread,
Dec 24, 2021, 9:16:23 AM12/24/21
to emscripte...@googlegroups.com
Hi! Just want to share my experiment with using Rust and WebAssembly. I tried to port Vange-rs project (rust + wgpu) to browser. I used emscripten and unknown platforms. Both finally works, but have lot of obstacles. I am very sad about support level of emscripten in Rust, hope it will change at some day.

Floh

unread,
Dec 25, 2021, 9:01:58 AM12/25/21
to emscripten-discuss
Ah, language and toolchain interoperability, one of my favourite topics ;)

Zig has nearly the same problems as Rust: it allows to compile to WASM, it has both a WASI and Emscripten target, with the WASI target working out of the box, but I gave up on the Emscripten target because I just couldn't get it to work.

IMHO it would be great if the Javascript shims and interop could be somehow split out of the Emscripten SDK into a separate, smaller "webapi-wasm-tools" SDK which could be better integrated with other language toolchains. The goal should be that other programming languages can benefit from the work that went into the Emscripten SDK to access web APIs like WebGL, WebGPU, WebAudio etc... up to "EM_JS()" functionality, instead of having to duplicate this work, or requiring a separate installation of the whole Emscripten SDK.

There's a very promising project https://github.com/schellingb/wajic by Bernhard Schelling which has the same goals and which was used to port Mattias Gustavsson's DOS-like library to the web: https://mattiasgustavsson.com/wasm/

Anyway... just my 2 cents :)
-Floh.

Alon Zakai

unread,
Jan 12, 2022, 1:24:24 PM1/12/22
to emscripte...@googlegroups.com
Very interesting writeup, thanks!

It is sad that things don't work better here. The Emscripten side is focused on C/C++ obviously and on native API support while the Rust side is focused on either pure computation or on calling Web APIs. For something like Vange-rs you really want native APIs + Rust, so neither side is really enough.

I keep hoping that someone will have an important enough use case for them to spend time on getting Emscripten+Rust working well, but so far that hasn't come up. As more native apps get written in Rust though perhaps eventually it will.

On Fri, Dec 24, 2021 at 6:16 AM Александр Гурьянов <caii...@gmail.com> wrote:
Hi! Just want to share my experiment with using Rust and WebAssembly. I tried to port Vange-rs project (rust + wgpu) to browser. I used emscripten and unknown platforms. Both finally works, but have lot of obstacles. I am very sad about support level of emscripten in Rust, hope it will change at some day.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-disc...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/emscripten-discuss/CAKOm%3DVF2wUiuKH1%3DivMhfjuAFdtMwvHxc0YaS4V%2BGoGfBWuy6w%40mail.gmail.com.

Alon Zakai

unread,
Jan 12, 2022, 1:32:04 PM1/12/22
to emscripte...@googlegroups.com
On Sat, Dec 25, 2021 at 6:02 AM Floh <flo...@gmail.com> wrote:
Ah, language and toolchain interoperability, one of my favourite topics ;)

Zig has nearly the same problems as Rust: it allows to compile to WASM, it has both a WASI and Emscripten target, with the WASI target working out of the box, but I gave up on the Emscripten target because I just couldn't get it to work.

I wrote up a demo of Zig + Emscripten here:


That uses GLES3 and Asyncify from Emscripten, so it's a small program but it uses interesting features.

The gist also shows using C in the same way, where Emscripten is just the linker, not the frontend.

I've been meaning to do the same with Rust and write a blogpost about all 3 but haven't found the time...

- Alon

 

IMHO it would be great if the Javascript shims and interop could be somehow split out of the Emscripten SDK into a separate, smaller "webapi-wasm-tools" SDK which could be better integrated with other language toolchains. The goal should be that other programming languages can benefit from the work that went into the Emscripten SDK to access web APIs like WebGL, WebGPU, WebAudio etc... up to "EM_JS()" functionality, instead of having to duplicate this work, or requiring a separate installation of the whole Emscripten SDK.

There's a very promising project https://github.com/schellingb/wajic by Bernhard Schelling which has the same goals and which was used to port Mattias Gustavsson's DOS-like library to the web: https://mattiasgustavsson.com/wasm/

Anyway... just my 2 cents :)
-Floh.
On Friday, 24 December 2021 at 15:16:23 UTC+1 caiiiycuk wrote:
Hi! Just want to share my experiment with using Rust and WebAssembly. I tried to port Vange-rs project (rust + wgpu) to browser. I used emscripten and unknown platforms. Both finally works, but have lot of obstacles. I am very sad about support level of emscripten in Rust, hope it will change at some day.

--
You received this message because you are subscribed to the Google Groups "emscripten-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to emscripten-disc...@googlegroups.com.

Floh

unread,
Jan 13, 2022, 4:46:05 AM1/13/22
to emscripten-discuss
That's a very useful gist, Alon! I think that blog post would be much appreciated by a lot of people who like to tinker with other languages :)

Александр Гурьянов

unread,
Jan 13, 2022, 5:06:13 AM1/13/22
to emscripte...@googlegroups.com
+1 for blog post. Not clear how I can use it with rust, e.g. can I compile static lib with target --wasm32-unknown-unknown and then link using emscripten? The main problem with RUST is that it even can't compile with --wasm32-unknown-emscipten (because of lib dependencies that not support emscripten)

чт, 13 янв. 2022 г. в 16:46, Floh <flo...@gmail.com>:

Alon Zakai

unread,
Jan 13, 2022, 7:54:37 PM1/13/22
to emscripte...@googlegroups.com
Thanks, good to know at least 2 people would read a post about this :) I'll try to find time for it.

About Rust, I haven't had time to look into it yet. My general hope is that the same model as for C and Zig could work:

1. Tell Rust to use the emscripten wasm triple.
2. Tell Rust to compile to object files (or a static library, basically), and *not* to link them.
3. The user runs emcc on those object files, linking them.

The nice thing in this model is that C/Zig/Rust does not need to be aware of emcc at all here (aside from telling LLVM to use the emscripten triple). And it's easy to do this, at least in C and Zig (although there are some subtle ABI questions).

This is actually the main thing I wanted to do before writing the post - ideally I'd have a Rust demo alongside C and Zig - so if someone figures that out, let me know!

- Alon


Александр Гурьянов

unread,
Jan 14, 2022, 2:08:33 PM1/14/22
to emscripte...@googlegroups.com
Let's look closer to my case. I ported C++ game Vangers to the web (https://www.gamepix.com/play/vangers). Vangers community did big work to integrate vange-rs (rust 3d render, based on wgpu) and Vangers game. It works as follow:
1. Vange-rs provide c ffi interface
2. Vange-rs compiled with rust to static library
3. Vangers linked with Vanger-rs to executable

Now I want to port  vangers + (vange-rs render) to the web. wgpu didn't support wasm32-unknown-emscripten, I added experimental support for emscripten and it works. BUT, wgpu is developing to fast, so my changes become outdated very fast :)

When I implement support for emscripten, I only disabling wasm32-unknown rules and uses native code paths everywhere. So, it's little bit strange, to work with emscripten you need to disable workarounds for wasm32. emscripten emulates native platform, so code that correctly uses posix system should work also in emscripten.

Maybe there is any way to just use native static library and link it with emscripten? Like this:
1. Compile vange-rs static library (with native triple)
2. Compile vangers project with emscripten
3. Link 1+2 with emscripten

for (1.) I can't use emscripten triple because of #[cfg] rules for wasm32 target, they select wrong code path (non-native).

пт, 14 янв. 2022 г. в 07:54, Alon Zakai <alon...@gmail.com>:

Alon Zakai

unread,
Jan 18, 2022, 12:36:56 PM1/18/22
to emscripte...@googlegroups.com
On Fri, Jan 14, 2022 at 11:08 AM Александр Гурьянов <caii...@gmail.com> wrote:
Let's look closer to my case. I ported C++ game Vangers to the web (https://www.gamepix.com/play/vangers). Vangers community did big work to integrate vange-rs (rust 3d render, based on wgpu) and Vangers game. It works as follow:
1. Vange-rs provide c ffi interface
2. Vange-rs compiled with rust to static library
3. Vangers linked with Vanger-rs to executable

Now I want to port  vangers + (vange-rs render) to the web. wgpu didn't support wasm32-unknown-emscripten, I added experimental support for emscripten and it works. BUT, wgpu is developing to fast, so my changes become outdated very fast :)

When I implement support for emscripten, I only disabling wasm32-unknown rules and uses native code paths everywhere. So, it's little bit strange, to work with emscripten you need to disable workarounds for wasm32. emscripten emulates native platform, so code that correctly uses posix system should work also in emscripten.

Maybe there is any way to just use native static library and link it with emscripten? Like this:
1. Compile vange-rs static library (with native triple)
2. Compile vangers project with emscripten
3. Link 1+2 with emscripten


(1) would compile to x86, though, I think? We have to have wasm to link with emscripten.
 
for (1.) I can't use emscripten triple because of #[cfg] rules for wasm32 target, they select wrong code path (non-native).


Hmm, I don't know enough rust to know what fixing that would mean...

Overall for an emscripten port I think we would want to use a native build as much as possible? That is, ideally you would *not* use vange-rs/WebGPU, but one of the native rendering paths (OpenGL of some flavor? Or perhaps they have Dawn/WebGPU support?). And you would need to tell rust to use the emscripten triple while doing so.

That should work, in theory. If it doesn't and Rust has some issues with how it invokes emcc to link, then the workaround could be what I mentioned for Zig and C before: get Rust to link to a static library, and then run emcc manually on that.

(Alternatively, in theory someone could look into supporting wasm-bindgen + emscripten.)

- Alon
 

Александр Гурьянов

unread,
Jan 26, 2022, 1:24:45 PM1/26/22
to emscripte...@googlegroups.com
Okay, I think I almost did the same in Rust what Alon described. vanger-rs now compiles as static library (.a) with emscripten triple. I use this static library to link with original C++ game. So I have *.o files from vangers, and librusty_vangers.a (which provides rendering on wgpu). I link them with emcc, and it produce wasm  without any error!

Also I do the same with native build - it works fine.

However, when I tries to run it fails with assertion.

On RUST side I have the following code:
#[no_mangle]
pub static rv_api_1: i32 = 1;

On C++ side I have the following code:
extern int32_t rv_api_1;
// ...
if(rv_api_1 != 1){
        printf("Invalid libvangers_ffi version expected 1, actual %d\n", rv_api_1);
        // abort();
}

When I run it, I have following output:
Invalid libvangers_ffi version expected 1, actual 0

For me it looks like static initializer from RUST didn't run. Because if I comment the abort(); seems integration works fine. Native build works correctly...
Do you have any idea why so?

ср, 19 янв. 2022 г. в 00:36, Alon Zakai <alon...@gmail.com>:

Sam Clegg

unread,
Jan 26, 2022, 2:31:18 PM1/26/22
to emscripte...@googlegroups.com
Is it valid to simply do `extern int32_t rv_api_1;` in C to refer to a rust variable?  Does that address of `rv_api_1` on the C side look correct?

Does `pub static rv_api_1: i32 = 1;` in rust generate a static initializer function or is it simply static memory (like it would be in C/C++)?

Assuming it is generating a ctor then there are a couple of things that could be going on.   Are you sure your static ctors have been run?  i.e. where is your code running?  Is it inside of main?   Disassembling your final binary should show all static ctors being called from the `__wasm_call_ctors` function.

cheers,
sam


Ingvar Stepanyan

unread,
Jan 26, 2022, 2:42:49 PM1/26/22
to emscripten-discuss
I think it should be `extern "C" int32_t rv_api_1;` on the C++ side, otherwise normal mangling rules apply and it's looking up (or, this case, declaring) a namespaced variable.

Александр Гурьянов

unread,
Jan 26, 2022, 9:32:12 PM1/26/22
to emscripte...@googlegroups.com

чт, 27 янв. 2022 г. в 02:42, 'Ingvar Stepanyan' via emscripten-discuss <emscripte...@googlegroups.com>:

Ingvar Stepanyan

unread,
Jan 27, 2022, 6:11:45 AM1/27/22
to emscripte...@googlegroups.com
But it's not a bug. As I said, you just need to add "C" to your `extern`, because right now you're exposing it from Rust via C FFI, but declaring it as a C++ symbol on the other side.



--
Regards,
Ingvar.

Ingvar Stepanyan

unread,
Jan 27, 2022, 6:16:39 AM1/27/22
to emscripte...@googlegroups.com
Ah sorry, I see you tried and said it doesn't work even with `extern "C"` in the issue description. That's odd, it definitely should.
--
Regards,
Ingvar.

Александр Гурьянов

unread,
Feb 4, 2022, 5:46:25 AM2/4/22
to emscripte...@googlegroups.com
Did it! Also I added support for emscripten in wgpu/wgpu-native, and soon it will be possible to use it with SDL/gflw. Want to add tutorial about it.

This article is about linking Vangers (1998) and vange-rs (wgpu renderer)

чт, 27 янв. 2022 г. в 18:16, 'Ingvar Stepanyan' via emscripten-discuss <emscripte...@googlegroups.com>:

Alon Zakai

unread,
Feb 4, 2022, 12:31:07 PM2/4/22
to emscripte...@googlegroups.com
Wow, great that you got all that working!

I'm also interested in SDL/glfw. I was trying to get glfw working with emscripten/rust and hit several problems, so I'm curious how you got it to work. I filed this issue with my problems:



Александр Гурьянов

unread,
Feb 6, 2022, 10:49:16 AM2/6/22
to emscripte...@googlegroups.com
It's because I don't use glfw from rust. In my case I used c/c++ glfw + wgpu-native (from rust).

So when I say sdl/glfw + wgpu-native, I mean that I will use c/c++ sdl/glfw for windows/events and wgpu-native for graphics.

сб, 5 февр. 2022 г. в 00:31, Alon Zakai <alon...@gmail.com>:

Alon Zakai

unread,
Feb 7, 2022, 6:50:57 PM2/7/22
to emscripte...@googlegroups.com
Reply all
Reply to author
Forward
0 new messages