Building with "--target wasm32-unknown-unknown" without building dependencies

To better demonstrate what I'm trying to do, here is a code example:

struct Local {
    a: u64,
    b: u64,
}

extern "C" {
    fn local() -> Local;
}

extern "C" {
    fn dependency() -> tokio::net::TcpStream;
}

#[export_name = "main"]
pub unsafe fn main() {
    let l = local();
    let d = dependency();
}

I want to compile this to a .wasm file. So, what I'm saying is:

  • There are 2 external functions local() & dependency() that will be provided by the WASM host environment.
  • local() returns a structure Local
  • dependency()returns a structure tokio::net::TcpStream

If I remove the dependency() call everything works as expected, but an issue arises when I add tokio as a dependency and try to use the exported structure tokio::net::TcpStream.

Tokio can't be compiled under wasm32-unknown-unknown, but I don't need whole tokio to compile, I just need the structure definitions inside of it.

Is there maybe a better way to approach this issue? Or will I in the end need to copy past all the structure definitions from tokio into my crate?

After thinking a bit more about this, I don't think this would be even possible. This dependency structs need to have their drop methods called once they are not needed anymore. So we need way more information about them than just their size.

I think I will go for a different design, where I return an u64 id for each resource and manage them on the host side.

The typical way you tackle this is by passing around items hidden behind a raw pointer instead of by value. From there the host will need to provide functions for actually doing things with the TcpStream (and functions for working with their results and everything else that you need).

I'm not sure if any of this will work though... If tokio can't be compiled for wasm32-unknown-unknown then how will you get a pointer to some tokio type?

Is the host compiled to wasm32-unknown-unknown as well? If so you're just pushing the problem of compiling tokio onto the host.

If not, that means you'll need to use whatever "host pointer" mechanism your runtime provides (e.g. wasmtime::AnyRef) and make sure the host manages your memory correctly. I haven't played around with wasm runtimes for a while (maybe when I wrote this?), but this may be tricky.

2 Likes

I read your post when doing research for this WASM runtime I'm working on :slightly_smiling_face:. It was really inspiring, thanks for writing it!

No, the host is compiled to regular x86_64. It will not be possible to get the pointer across to the guest, but I could send an index in a collection held by the host. The collection holds the tokio types and expose wrapper functions to the guest that take the index and dereference the actual struct.

Not sure what the best collection would be to hold such data, but I will start with an HashMap and go from there to create an MVP.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.