I have a C program which can send HTTP requests to other services, how can I run it on Wasm now?
I found that even though WasmEdge supports most of the Socket API now, all the mainstream existing C to Wasm compiles don't support compiling Socket API, including Emscripten, Wasi-sdk.
Is there any other way to achieve it? Or maybe we need to wait until the wasi-http or wasi-socket proposals are accepted and implemented in the C to Wasm compiles?
Also, I found that rust compiler supports some key Socket APIs which are not in wasi-preview1, e.g., sock_setsockopt, sock_connect. So I was confused about why the toolchains for Wasm in Rust are more mature than those in C/C++. Is it related to the special features of Rust or what?
Sockets are implemented in wasi-libc
, and while there is a recent issue with wasi-sdk
not having the wasm32-wasip2
target, wasi-sdk
22 has the target now. You'll still need to do some adapting to get there it looks like but it should be possible.
Could you try targeting wasm32-wasip2
target with wasi-sdk
22?
Hi
I have a go program which makes a tcp connection
conn, err := net.Dial("tcp", "216.58.206.46:80")
but this is not executing successfully and I encounter some nil pointer error even though the program executes successfully separately. So is this because of the reason above, that the network calls from a Go program compiled to WebAssembly (Wasm) and executed in a WASI environment will not work because the necessary system calls are not available in WASI Preview 1. Also for compilers like tinyGo and standard Go compiler, they still have limitations to support wasi preview 2?
as of july 2: "It's a milestone day for Gophers and WebAssembly: the wasi-preview-2
feature branch of TinyGo has landed in TinyGo's dev
branch, bringing WASI P2 support to TinyGo!"
Hi
I try to compile with --target=wasm32-wasip2
option using wasi-sdk
and successfully get the wasm code.
But the compiled result cannot successfully run on the existing wasm runtimes.
For WasmEdge, as the HTTP requests are related to wasi-socket proposal, WasmEdge is working for it.
https://github.com/WasmEdge/WasmEdge/issues/2939
For Wasmtime, I open an issue about it.
https://github.com/bytecodealliance/wasmtime/issues/9034
Ralph said:
as of july 2: "It's a milestone day for Gophers and WebAssembly: the
wasi-preview-2
feature branch of TinyGo has landed in TinyGo'sdev
branch, bringing WASI P2 support to TinyGo!"
I have checked out the dev branch of tiny go.I have a go program which attempts to make a tcp connection to an ip. I have compiled this go program to Wasm module using tinyGo (dev branch which has wasip2 support) and target as wasip2. Now I am executing this in wasmtime . But wasmtime throws an error.
Error: failed to parse WebAssembly module
Caused by:
expected a WebAssembly module but was given a WebAssembly component
I thought the problem is because of the network call, so I changed the program to a simple program which does simple file operations. This runs successfully with wasip1 and this same program gives the same error as above with target wasip2. Even though the tinyGo dev branch has wasip2 support it's not running successfully when it comes in integration with wasmtime.
Any idea on this?
can you show what you invoked that gave that error?
Pat Hickey said:
can you show what you invoked that gave that error?
package main
import (
"fmt"
"io/ioutil"
"net/http"
"os"
)
func main() {
fmt.Println("I am from Go app")
// Make a simple HTTP GET request
resp, err := http.Get("http://example.com")
if err != nil {
fmt.Println("Error:", err)
os.Exit(1)
}
// Read the response body
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response body:", err)
os.Exit(1)
}
resp.Body.Close()
fmt.Printf("Response status: %s\n", resp.Status)
fmt.Printf("Response body: %s\n", body)
}
Running this go program separately gives output. but when in conjunction with wasmtime gives error
Error: failed to parse WebAssembly module
Caused by:
expected a WebAssembly module but was given a WebAssembly component
I think we're asking for the wasmtime execution command line you used
wasmtime serve? run? -S common or some other variation
also, would love results of wasmtime --version
I'd also love the tinygo
compilation line -- did I miss that?
Actually I am not using wasmtime cli , I have pulled the latest main branch https://github.com/bytecodealliance/wasmtime
and I am running this. because as part of my project I will have to do some modifications like overwrite wasi calls etc.
So in this codebase I have added a directory under examples for my app and ran the command
cargo run
here is my main.rs file
use anyhow::Result;
use wasi_common::WasiCtx;
use wasi_common::sync::WasiCtxBuilder;
use wasmtime::*;
use wasi_common::sync::{ambient_authority, Dir};
fn main() -> Result<()> {
// Define the WASI functions globally on the `Config`.
let engine = Engine::default();
let mut linker = Linker::new(&engine);
wasi_common::sync::add_to_linker(&mut linker, |s| s)?;
// Create a WASI context and put it in a Store; all instances in the store
// share this context. `WasiCtxBuilder` provides a number of ways to
// configure what the target program will have access to.
let wasi = WasiCtxBuilder::new()
.inherit_stdio()
.inherit_args()?
.build();
let mut store = Store::new(&engine, wasi);
// Load our WebAssembly modules.
let module_rust_app = Module::from_file(&engine, "/Users/celinesantosh/Desktop/sem_5/rust_app/target/wasm32-wasi/release/rust_app.wasm")?;
let module_go_app = Module::from_file(&engine, "/Users/celinesantosh/Desktop/sem_5/go_program/go_app.wasm")?;
// Instantiate the Rust app module.
let instance_rust_app = linker.instantiate(&mut store, &module_rust_app)?;
// Instantiate the Go app module.
let instance_go_app = linker.instantiate(&mut store, &module_go_app)?;
// Get the `_start` function from the Rust app instance.
let start_rust_app = instance_rust_app.get_typed_func::<(), ()>(&mut store, "_start")?;
// Get the `_start` function from the Go app instance.
let start_go_app = instance_go_app.get_typed_func::<(), ()>(&mut store, "_start")?;
// Call the `_start` function on both modules.
start_rust_app.call(&mut store, ())?;
start_go_app.call(&mut store, ())?;
Ok(())
}
TinyGo compilation :
/Users/celinesantosh/Desktop/sem_5/tinygo/build/tinygo build -o go_app.wasm -target=wasip2 main.go
Thanks
In your main.rs
file, you're using the Wasmtime Module
API and the WASIp1 support in wasi_common
. That won't work for WASIp2 components. Please make sure you're using a recent version of Wasmtime and use the wasmtime::component API, along with wasmtime-wasi, which now supports WASIp2 by default.
Search for CliLinker::Component
in this file for an example of how to run a WASIp2 CLI component.
Joel Dice said:
In your
main.rs
file, you're using the WasmtimeModule
API and the WASIp1 support inwasi_common
. That won't work for WASIp2 components. Please make sure you're using a recent version of Wasmtime and use the wasmtime::component API, along with wasmtime-wasi, which now supports WASIp2 by default.Search for
CliLinker::Component
in this file for an example of how to run a WASIp2 CLI component.
Thanks for the explanation.
Are there any examples for creating the main.rs file with wasi preview2?
I can see a lot of examples with wasi preview1 in the repo though.
Rust nightly now supports the wasm32-wasip2
target, so you can consider using that. For Rust stable, you can either use cargo-component (although I don't know of a wasi:cli
example for cargo-component
offhand) or convert the WASIp1 module produced by cargo build --target=wasm32-wasi
into a WASIp2 component using wasm-tools component new --adapt wasi_snapshot_preview1.command.wasm target/wasm32-wasi/release/$APP_NAME.wasm
after downloading wasi_snapshot_preview1.command.wasm.
Last updated: Dec 23 2024 at 12:05 UTC