Hi
Could I do this:
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() { }
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() { }
@Alexey Melnikov Easiest way is https://github.com/bytecodealliance/wasmtime/blob/master/examples/linking.rs
notice that eventually you have manage common memory between into modules -- that's where things are getting tricky
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?
preload might not work as Linker
, also see the above note about memory
@Alexey Melnikov is going via wasmtime-cli
your requirement, or you allowed to use embedding/create your executable ?
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
?)?
CLI is somewhat limited how it resolves the dependent modules
So you are saying that using wasmtime-cli
tool is your requirement?
(FWIW crate "e" is a normal way to embed wasmtime
and provide a customized module linking logic)
$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
that's correct, looks like wasmtime-cli
does not support linking yet (preload != linking)
Excuse me, what is preload
?
afaik preload
was introduced to support custom wasi modules
its logic at https://github.com/bytecodealliance/wasmtime/blob/master/src/commands/run.rs#L189
Thank you for the notes.
just out of curiosity, why not use "e"-crate method?
If there are many modules with different dependencies then automatic linking may be usefull for server-side development.
agree, but there will be an issue in describing linking via command line
as well as resolution of module name to wasm file/bytecode
will it be easier to control that via custom logic/embedding?
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?
I closed my issue after I've found a solution with e
-crate.
okay
Of course, custom linking looks more reliable.
automatic/deterministic linking is still a proposal and will be better defined in interface types proposal
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.
it is possible to address some of these issue, e.g. via --import-memory
for LLD or #[link(wasm_import_module = "...")]
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.
So, auto linking has rights to live.
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
.
@Alexey Melnikov while it may not necessarily be get_instance
we could add Linker::get_export
in the same manner as Instance::get_export
the Linker
version would just take a module/name instead of just a name
and would otherwise work the same way API-wise
So, the code may look like:
let run = linker.get_export("env", "funca").and_then(|e| e.func()).unwrap();
?
well to be clear that API doesn't exist today
but yeah such an API could be added
Should I open an issue on github to start work?
@Alexey Melnikov sure! (A PR would also be fine!)
Thanks @Alex Crichton for a quick merge (of labelling PR)!
is there a way to pass Cranelift CLI options to wasmtime's runner?
hmm it seems not
Last updated: Dec 23 2024 at 13:07 UTC