Comments (14)
@segeljakt Yes -- please add wasmtime-wasi
to your Cargo.toml and use https://docs.rs/wasmtime-wasi/17.0.1/wasmtime_wasi/sync/fn.add_to_linker.html prior to instantiating the component. See e.g. https://github.com/bytecodealliance/wasmtime/blob/main/src/commands/run.rs for an example, including how to implement WasiView
, create a WasiCtx
using WasiCtxBuilder
, etc.
from componentize-py.
@segeljakt I just posted a PR that fixes the tests: segeljakt/wasm-component-test#1
For compiling Rust, I thought it was possible to use wit-bindgen instead of cargo-component. Should I switch to cargo-component?
Yes, you can use wit-bindgen
directly if you prefer, but you'll also need to provide a Preview 1->2 adapter when using wit-component
to generate a component from the module, which cargo-component
takes care of automatically.
I enabled async, and now it seems like I need to call Linker::instantiate_async which returns a future, instead of Linker::instantiate. Do you need an async runtime like Tokio to run WASI?
wasmtime_wasi::preview2::command::add_to_linker
uses Wasmtime's async
API, but you can use wasmtime_wasi::preview2::command::sync::add_to_linker
instead if you want to use the synchronous API.
from componentize-py.
Okay, I'm ready to close this out. The whole reason it wasn't working for me was that I was using wasmtime 15 in the host but wasmtime 17 to build the Python component. @segeljakt I'm glad you got your example working too.
from componentize-py.
Thanks for reporting this, @kyleconroy.
I think it's a duplicate of #33, and the same answer I gave there applies here. There's no built-in way to prevent componentize-py
from producing components with WASI imports, but you can use WASI-Virt to convert the output of componentize-py
to a component that doesn't require WASI.
from componentize-py.
Do you have experience with WASI-Virt? I've followed the README but the component that's generated also does not work, erroring out inside get-arguments
.
% wasi-virt hello.component.wasm -o virt.component.wasm
% ./target/release/wasmtime-test hello.python.wasm
Error: error while executing at wasm backtrace:
0: 0x2136650 - <unknown>!<wasm function 24>
1: 0x6a99 - <unknown>!<wasm function 111>
2: 0x211aef5 - wit-component:shim!indirect-wasi:cli/[email protected]
3: 0xa93808 - libcomponentize_py_runtime.so!componentize_py_runtime::wasi::cli::environment::get_arguments::he1e861194172045e
4: 0xa92ef2 - libcomponentize_py_runtime.so!std::sys::pal::wasi::once::Once::call::h02a7e37fdd2f75c4
5: 0xa8a8aa - libcomponentize_py_runtime.so!componentize-py#Dispatch
6: 0x210f192 - libcomponentize_py_bindings.so!hello
Caused by:
wasm trap: wasm `unreachable` instruction executed
from componentize-py.
In the README.md, it says:
By default the virtualization will deny all subsystems, and will panic on any attempt to use any subsystem.
So it seems to be behaving as advertised, though clearly not useful for our purposes. Ideally, it would give us an option to return an empty or statically-defined list from wasi:cli/environment/get-arguments
(analogous to what it does for wasi:cli/environment/get-environment
), but it doesn't appear to have that capability yet: https://github.com/bytecodealliance/WASI-Virt/blob/fd2fae04342ea58aab2426ca041da68be046b030/virtual-adapter/src/env.rs#L84.
The code causing that panic is https://github.com/bytecodealliance/componentize-py/blob/main/runtime/src/lib.rs#L414. We could potentially add an option to componentize-py
to skip that, but I think it would be more appropriate to address this in WASI-Virt.
from componentize-py.
I ran into the same problem when trying to load a Python component from Rust:
const PYTHON_COMPONENT: &[u8] = include_bytes!("python-component.wasm");
fn main() -> anyhow::Result<()> {
let engine = Engine::default();
let mut store = Store::new(&engine, ());
let linker = Linker::new(&engine);
let component = Component::from_binary(&engine, &PYTHON_COMPONENT)?;
let instance = linker.instantiate(&mut store, &component)?; // panic here
Ok(())
}
Is there any way to configure wasmtime inside Rust to make it work?
from componentize-py.
@kyleconroy When I get a chance, I'll see if I can add the features to wasi-virt
necessary to use it with componentize-py
and add an example to the examples directory in this repo.
from componentize-py.
@dicej Hmm ok, I think I almost got it working:
use wasmtime::component::Component;
use wasmtime::component::Linker;
use wasmtime::component::ResourceTable;
use wasmtime::Config;
use wasmtime::Engine;
use wasmtime::Store;
use wasmtime_wasi::preview2::WasiCtxBuilder;
use wit_component::ComponentEncoder;
const WASI_MODULE: &[u8] = include_bytes!(concat!(
env!("CARGO_MANIFEST_DIR"),
"/../guest/target/wasm32-wasi/debug/guest.wasm"
));
struct Host {
ctx: wasmtime_wasi::preview2::WasiCtx,
table: ResourceTable,
adapter: wasmtime_wasi::preview2::preview1::WasiPreview1Adapter,
}
impl wasmtime_wasi::preview2::WasiView for Host {
fn table(&mut self) -> &mut ResourceTable {
&mut self.table
}
fn ctx(&mut self) -> &mut wasmtime_wasi::preview2::WasiCtx {
&mut self.ctx
}
}
impl wasmtime_wasi::preview2::preview1::WasiPreview1View for Host {
fn adapter(&self) -> &wasmtime_wasi::preview2::preview1::WasiPreview1Adapter {
&self.adapter
}
fn adapter_mut(&mut self) -> &mut wasmtime_wasi::preview2::preview1::WasiPreview1Adapter {
&mut self.adapter
}
}
impl Host {
fn new() -> Self {
let ctx = wasmtime_wasi::preview2::WasiCtxBuilder::new().build();
let table = ResourceTable::new();
let adapter = wasmtime_wasi::preview2::preview1::WasiPreview1Adapter::new();
Self {
ctx,
table,
adapter,
}
}
}
fn main() -> anyhow::Result<()> {
let mut config = Config::new();
config.async_support(true);
let engine = Engine::new(&config)?;
let host = Host::new();
let store = Store::new(&engine, host);
let mut linker = Linker::new(&engine);
wasmtime_wasi::preview2::command::add_to_linker::<Host>(&mut linker)?;
let component = ComponentEncoder::default()
.module(WASI_MODULE)?
.validate(true)
.encode()?;
let component = Component::from_binary(&engine, &component)?;
}
When I try to run it I get:
Error: module requires an import interface named `wasi_snapshot_preview1`
I'm not sure if I'm doing something wrong when building my Guest wasm project (I use cargo build --target=wasm32-wasi
), or if I should be doing something like:
let component = ComponentEncoder::default()
.module(WASI_MODULE)?
.adapter("wasi_snapshot_preview1", <bytes>)
.validate(true)
.encode()?;
Do you have any tips?
from componentize-py.
@segeljakt Given that you're using cargo
to build the guest, I'm not seeing how this relates to componentize-py
. I'm also not clear on whether you're trying to target WASI Preview 1 or Preview 2.
If you want to target Preview 1, you'll want to build using cargo build --target=wasm32-wasi
then load the resulting module using wasmtime::{Module, Linker, ...}
along with https://docs.rs/wasi-common/18.0.1/wasi_common/sync/fn.add_to_linker.html. If you want to target Preview 2, you'll want to use cargo-component
(which will take care of componentizing the module produced by cargo
and add the Preview 1->2 adapter automatically), and use wasmtime::component::{Component, Linker, ...}
along with https://docs.rs/wasmtime-wasi/18.0.1/wasmtime_wasi/preview2/command/sync/fn.add_to_linker.html. You should not need to use any part of wasmtime_wasi::preview2::preview1
.
Perhaps you could explain in more detail what you're trying to do, and push what you have to a GitHub repo with steps to reproduce the issue(s) you're seeing?
from componentize-py.
@dicej Sorry I got a bit derailed. I forgot to mention that I have been trying to compile both Python and Rust to WebAssembly components. Here is a repo with the current code: https://github.com/segeljakt/wasm-component-test
The first test which targets WASM without WASI works right now, but the other two fail:
running 3 tests
Image resized and saved to cat_resized.png
test wasm_test::test_rs_guest ... ok
Error: module requires an import interface named `wasi_snapshot_preview1`
test wasm_wasi_test::test_rs_guest ... FAILED
thread 'wasm_wasi_test::test_py_guest' panicked at /Users/klasseg/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasmtime-18.0.1/src/runtime/component/linker.rs:296:9:
must use async instantiation when async support is enabled
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
test wasm_wasi_test::test_py_guest ... FAILED
For compiling Rust, I thought it was possible to use wit-bindgen
instead of cargo-component
. Should I switch to cargo-component
?
When instantiating the Python WASI component, I first got an error:
cannot use `func_wrap_async` without enabling async support in the config
I enabled async, and now it seems like I need to call Linker::instantiate_async
which returns a future, instead of Linker::instantiate
. Do you need an async runtime like Tokio to run WASI?
from componentize-py.
@dicej Wow, thanks a lot! It works perfectly. I am now going to try to setup a Javascript Guest 👀
from componentize-py.
Yeah, if you don't mind using wasmtime-wasi
(and making sure the versions line up), that's your best bet to ensure that Python's standard libraries and third party libraries work as expected, using host features like the filesystem, environment variables, random numbers, etc. as appropriate.
That said, I do think there's value in an example of using wasi-virt
to virtualize some or all of the WASI features a componentize-py
-generated component uses, so I still plan to add one at some point.
from componentize-py.
If other people are looking for examples on calling the hello.component.wasm
from Rust, my change to upgrade to wasmtime 17 was merged here bytecodealliance/ComponentizeJS#86
from componentize-py.
Related Issues (20)
- Add interface version support HOT 1
- Remove init function and types from the final output
- Use interface package as part of module name in generated bindings HOT 1
- Use `wasi-virt`-based VFS to store Python code
- Download dependencies automatically
- Add support for type aliases
- Optionally produce component which imports libpython311.so, libc.so, etc. instead of bundling them
- time.sleep sleeps indefinitely HOT 3
- re-init random seed(s) on resume
- pyo3_runtime.PanicException: internal error: entered unreachable code HOT 3
- Running component without WASI HOT 2
- Run MyPy on all test code and bindings HOT 1
- Running example HOT 3
- Question: Current types limitation HOT 6
- Matrix-math example - ImportError... HOT 4
- List errors which might be raised in function docstrings
- Make the types generated for WIT resources context managers
- feature: add zlib to cpython build HOT 1
- Create more actionable error for disallowed name for a Python module
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from componentize-py.