Stream: general

Topic: (no topic)


view this post on Zulip Alexey Melnikov (Mar 31 2020 at 14:33):

Hi
Could I do this:

  1. create in Rust crate a.wasm with function funca()
$cat a/src/lib.rs

#[no_mangle]
pub extern "C" fn funca() {
   println!("funca");
}
#[no_mangle]
pub extern "C" fn _start() {
}
  1. create in Rust crate b.wasm with function funcb(), which calls funca() from a.wasm
$cat b/src/lib.rs

extern "C" {
    fn funca();
}
#[no_mangle]
pub extern "C" fn funcb() {
    println!("funcb");
    unsafe {
        funca();
    }
}
#[no_mangle]
pub extern "C" fn _start() {
}
  1. run $wasmtime --preload a.wasm --invoke funcb b.wasm
    and wasmtime will load a.wasm and automatic link funca() to b.wasm
    ?

view this post on Zulip Yury Delendik (Mar 31 2020 at 14:35):

@Alexey Melnikov Easiest way is https://github.com/bytecodealliance/wasmtime/blob/master/examples/linking.rs

Standalone JIT-style runtime for WebAssembly, using Cranelift - bytecodealliance/wasmtime

view this post on Zulip Yury Delendik (Mar 31 2020 at 14:37):

notice that eventually you have manage common memory between into modules -- that's where things are getting tricky

view this post on Zulip Alexey Melnikov (Mar 31 2020 at 14:39):

I've made this by linking. By it's a not easiest way. Because I have to develop the third crate to link the first and the second. I would like to see how this may work with preload option. Is it possible?

view this post on Zulip Yury Delendik (Mar 31 2020 at 14:43):

preload might not work as Linker, also see the above note about memory

view this post on Zulip Yury Delendik (Mar 31 2020 at 14:45):

@Alexey Melnikov is going via wasmtime-cli your requirement, or you allowed to use embedding/create your executable ?

view this post on Zulip Alexey Melnikov (Mar 31 2020 at 14:46):

So, what I mean.
My current variant is:

$cat a/src/lib.rs

#[no_mangle]
pub extern "C" fn funca() {
   println!("funca");
}
#[no_mangle]
pub extern "C" fn _start() {
}

2.

$cat b/src/lib.rs

extern "C" {
    fn funca();
}
#[no_mangle]
pub extern "C" fn funcb() {
    println!("funcb");
    unsafe {
        funca();
    }
}
#[no_mangle]
pub extern "C" fn _start() {
}

3.

$cat e/src/main.rs

use anyhow::Result;
use wasmtime::*;
use wasmtime_wasi::{Wasi, WasiCtx};

fn main() -> Result<()> {
    // store & wasi
    let store = Store::default();
    let wasi = Wasi::new(&store, WasiCtx::new(std::env::args())?);

    // linker
    let mut linker = Linker::new(&store);
    wasi.add_to_linker(&mut linker)?;

    // module1
    let module1 = Module::from_file(&store, "/at/rust/wasmer/a/target/wasm32-wasi/release/a.wasm")?;
    let instance1 = linker.instantiate(&module1)?;
    linker.instance("env", &instance1)?;
    let run = instance1.get_export("funca").and_then(|e| e.func()).unwrap();
    let run = run.get0::<()>()?;
    run()?;

    // module2
    let module2 = Module::from_file(&store, "/at/rust/wasmer/b/target/wasm32-wasi/release/b.wasm")?;
    let instance2 = linker.instantiate(&module2)?;
    linker.instance("env2", &instance2)?;
    let run = instance2.get_export("funcb").and_then(|e| e.func()).unwrap();
    let run = run.get0::<()>()?;
    run()?;

    Ok(())
}

OK! It's works. But how to rewrite this variant to using preload option (and without crate e ?)?

view this post on Zulip Yury Delendik (Mar 31 2020 at 14:46):

CLI is somewhat limited how it resolves the dependent modules

view this post on Zulip Yury Delendik (Mar 31 2020 at 14:48):

So you are saying that using wasmtime-cli tool is your requirement?

view this post on Zulip Yury Delendik (Mar 31 2020 at 14:50):

(FWIW crate "e" is a normal way to embed wasmtime and provide a customized module linking logic)

view this post on Zulip Alexey Melnikov (Mar 31 2020 at 14:53):

$wasmtime run --preload a/target/wasm32-wasi/release/a.wasm --invoke funcb b/target/wasm32-wasi/release/b.wasm
Error: failed to run main module b/target/wasm32-wasi/release/b.wasm
Caused by:
import module env was not found

view this post on Zulip Yury Delendik (Mar 31 2020 at 14:54):

that's correct, looks like wasmtime-cli does not support linking yet (preload != linking)

view this post on Zulip Alexey Melnikov (Mar 31 2020 at 14:55):

Excuse me, what is preload?

view this post on Zulip Yury Delendik (Mar 31 2020 at 14:57):

afaik preload was introduced to support custom wasi modules

view this post on Zulip Yury Delendik (Mar 31 2020 at 14:58):

its logic at https://github.com/bytecodealliance/wasmtime/blob/master/src/commands/run.rs#L189

Standalone JIT-style runtime for WebAssembly, using Cranelift - bytecodealliance/wasmtime

view this post on Zulip Alexey Melnikov (Mar 31 2020 at 14:59):

Thank you for the notes.

view this post on Zulip Yury Delendik (Mar 31 2020 at 15:00):

just out of curiosity, why not use "e"-crate method?

view this post on Zulip Alexey Melnikov (Mar 31 2020 at 15:09):

If there are many modules with different dependencies then automatic linking may be usefull for server-side development.

view this post on Zulip Yury Delendik (Mar 31 2020 at 15:13):

agree, but there will be an issue in describing linking via command line

view this post on Zulip Yury Delendik (Mar 31 2020 at 15:17):

as well as resolution of module name to wasm file/bytecode

view this post on Zulip Yury Delendik (Mar 31 2020 at 15:20):

will it be easier to control that via custom logic/embedding?

view this post on Zulip Yury Delendik (Mar 31 2020 at 15:22):

anyway, but report was warranted here, do you want to re-open https://github.com/bytecodealliance/wasmtime/issues/1440 and define requirements and provide more details?

Hi, please advise me how to make: I created a simple library crate: $cat a/src/lib.rs #[no_mangle] pub extern "C" fn funca() { println!("funca"); } #[no_mangle] pub extern &quot...

view this post on Zulip Alexey Melnikov (Mar 31 2020 at 15:24):

I closed my issue after I've found a solution with e-crate.

view this post on Zulip Yury Delendik (Mar 31 2020 at 15:25):

okay

view this post on Zulip Alexey Melnikov (Mar 31 2020 at 15:31):

Of course, custom linking looks more reliable.

view this post on Zulip Yury Delendik (Mar 31 2020 at 15:34):

automatic/deterministic linking is still a proposal and will be better defined in interface types proposal

view this post on Zulip Yury Delendik (Mar 31 2020 at 15:36):

notice that, a.wasm and b.wasm do not contain right linking info (inspect via wasm2wat), so automatic linking will have trouble to work with it: multiple non-connected memories, all imports come from "env", etc.

view this post on Zulip Yury Delendik (Mar 31 2020 at 15:40):

it is possible to address some of these issue, e.g. via --import-memory for LLD or #[link(wasm_import_module = "...")]

view this post on Zulip Alexey Melnikov (Mar 31 2020 at 16:00):

it's interesting.

This commit stabilizes the #[wasm_import_module] attribute as
#[link(wasm_import_module = "...")]. Tracked by #52090 this new directive in
the #[link] attribute is used to configured the module name that the imports
are listed with. The WebAssembly specification indicates two utf-8 names are
associated with all imported items, one for the module the item comes from and
one for the item itself. The item itself is configurable in Rust via its
identifier or #[link_name = "..."], but the module name was previously not
configurable and defaulted to "env". This commit ensures that this is also
configurable.

view this post on Zulip Alexey Melnikov (Mar 31 2020 at 16:02):

So, auto linking has rights to live.

view this post on Zulip Alexey Melnikov (Apr 01 2020 at 13:05):

Is it possible to change code:

    // module1
    let module1 = Module::from_file(&store, "/at/rust/wasmer/a/target/wasm32-wasi/release/a.wasm")?;
    let instance1 = linker.instantiate(&module1)?;
    linker.instance("env", &instance1)?;
    let run = instance1.get_export("funca").and_then(|e| e.func()).unwrap();
    let run = run.get0::<()>()?;
    run()?;

to

    // module1
    let module1 = Module::from_file(&store, "/at/rust/wasmer/a/target/wasm32-wasi/release/a.wasm")?;
    let instance1 = linker.instantiate(&module1)?;
    linker.instance("env", &instance1)?;
    let run = linker.get_instance("env").get_export("funca").and_then(|e| e.func()).unwrap();
    let run = run.get0::<()>()?;
    run()?;

Need to add the method get_instance() to linker.

view this post on Zulip Alex Crichton (Apr 01 2020 at 13:50):

@Alexey Melnikov while it may not necessarily be get_instance we could add Linker::get_export in the same manner as Instance::get_export

view this post on Zulip Alex Crichton (Apr 01 2020 at 13:50):

the Linker version would just take a module/name instead of just a name

view this post on Zulip Alex Crichton (Apr 01 2020 at 13:50):

and would otherwise work the same way API-wise

view this post on Zulip Alexey Melnikov (Apr 01 2020 at 13:53):

So, the code may look like:
let run = linker.get_export("env", "funca").and_then(|e| e.func()).unwrap();
?

view this post on Zulip Alex Crichton (Apr 01 2020 at 13:55):

well to be clear that API doesn't exist today

view this post on Zulip Alex Crichton (Apr 01 2020 at 13:55):

but yeah such an API could be added

view this post on Zulip Alexey Melnikov (Apr 01 2020 at 13:57):

Should I open an issue on github to start work?

view this post on Zulip Alex Crichton (Apr 01 2020 at 14:13):

@Alexey Melnikov sure! (A PR would also be fine!)

view this post on Zulip Benjamin Bouvier (Apr 21 2020 at 14:13):

Thanks @Alex Crichton for a quick merge (of labelling PR)!

view this post on Zulip Benjamin Bouvier (Apr 30 2020 at 13:10):

is there a way to pass Cranelift CLI options to wasmtime's runner?

view this post on Zulip Benjamin Bouvier (Apr 30 2020 at 13:30):

hmm it seems not


Last updated: Nov 22 2024 at 16:03 UTC