add wasmtime adapter and stdio wrappers
the stdio wrappers will not work on windows, but thats a whole other can of worms anyway
This commit is contained in:
@@ -13,6 +13,11 @@ include = ["src/**/*", "LICENSE", "build.rs"]
|
|||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
|
# This doesn't actually link to a native library, but it allows us to set env
|
||||||
|
# vars like `DEP_WASI_C2_19_*` for crates that have build scripts and depend
|
||||||
|
# on this crate, allowing other crates to use the same witx files.
|
||||||
|
links = "wasi-c2-19"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
let cwd = std::env::current_dir().unwrap();
|
let cwd = std::env::current_dir().unwrap();
|
||||||
let wasi = cwd.join("..").join("wasi-common").join("WASI");
|
let wasi = cwd.join("..").join("wasi-common").join("WASI");
|
||||||
|
// this will be available to dependent crates via the DEP_WASI_C2_19_WASI env var:
|
||||||
println!("cargo:wasi={}", wasi.display());
|
println!("cargo:wasi={}", wasi.display());
|
||||||
|
// and available to our own crate as WASI_ROOT:
|
||||||
println!("cargo:rustc-env=WASI_ROOT={}", wasi.display());
|
println!("cargo:rustc-env=WASI_ROOT={}", wasi.display());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use crate::dir::{DirCaps, DirEntry, WasiDir};
|
use crate::dir::{DirCaps, DirEntry, WasiDir};
|
||||||
use crate::file::{FileCaps, FileEntry, WasiFile};
|
use crate::file::{FileCaps, FileEntry, WasiFile};
|
||||||
use crate::table::Table;
|
use crate::table::Table;
|
||||||
|
use crate::Error;
|
||||||
use std::cell::{RefCell, RefMut};
|
use std::cell::{RefCell, RefMut};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@@ -10,6 +11,10 @@ pub struct WasiCtx {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WasiCtx {
|
impl WasiCtx {
|
||||||
|
pub fn builder() -> WasiCtxBuilder {
|
||||||
|
WasiCtxBuilder(WasiCtx::new())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
WasiCtx {
|
WasiCtx {
|
||||||
table: Rc::new(RefCell::new(Table::new())),
|
table: Rc::new(RefCell::new(Table::new())),
|
||||||
@@ -52,3 +57,36 @@ impl WasiCtx {
|
|||||||
self.table.borrow_mut()
|
self.table.borrow_mut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct WasiCtxBuilder(WasiCtx);
|
||||||
|
|
||||||
|
impl WasiCtxBuilder {
|
||||||
|
pub fn build(self) -> Result<WasiCtx, Error> {
|
||||||
|
Ok(self.0)
|
||||||
|
}
|
||||||
|
pub fn arg(&mut self, _arg: &str) -> &mut Self {
|
||||||
|
// Intentionally left blank. We do not handle arguments yet.
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub fn inherit_stdio(&mut self) -> &mut Self {
|
||||||
|
self.0.insert_file(
|
||||||
|
0,
|
||||||
|
Box::new(crate::stdio::stdin()),
|
||||||
|
FileCaps::READ,
|
||||||
|
FileCaps::READ,
|
||||||
|
);
|
||||||
|
self.0.insert_file(
|
||||||
|
1,
|
||||||
|
Box::new(crate::stdio::stdout()),
|
||||||
|
FileCaps::WRITE,
|
||||||
|
FileCaps::WRITE,
|
||||||
|
);
|
||||||
|
self.0.insert_file(
|
||||||
|
2,
|
||||||
|
Box::new(crate::stdio::stderr()),
|
||||||
|
FileCaps::WRITE,
|
||||||
|
FileCaps::WRITE,
|
||||||
|
);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ mod dir;
|
|||||||
mod error;
|
mod error;
|
||||||
mod file;
|
mod file;
|
||||||
pub mod snapshots;
|
pub mod snapshots;
|
||||||
|
pub mod stdio;
|
||||||
pub mod table;
|
pub mod table;
|
||||||
|
|
||||||
pub use ctx::WasiCtx;
|
pub use ctx::WasiCtx;
|
||||||
|
pub use dir::{DirCaps, WasiDir};
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
|
pub use file::{FileCaps, WasiFile};
|
||||||
|
|||||||
124
crates/wasi-c2/src/stdio.rs
Normal file
124
crates/wasi-c2/src/stdio.rs
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
use crate::file::{FdFlags, Filestat, Filetype, OFlags, WasiFile};
|
||||||
|
use crate::Error;
|
||||||
|
#[cfg(unix)]
|
||||||
|
use std::os::unix::io::{AsRawFd, RawFd};
|
||||||
|
|
||||||
|
pub struct Stdin(std::io::Stdin);
|
||||||
|
|
||||||
|
pub fn stdin() -> Stdin {
|
||||||
|
Stdin(std::io::stdin())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
impl AsRawFd for Stdin {
|
||||||
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
|
self.0.as_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WasiFile for Stdin {
|
||||||
|
fn datasync(&self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn sync(&self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn get_filetype(&self) -> Result<Filetype, Error> {
|
||||||
|
Ok(Filetype::CharacterDevice)
|
||||||
|
}
|
||||||
|
fn get_fdflags(&self) -> Result<FdFlags, Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn get_oflags(&self) -> Result<OFlags, Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn set_oflags(&self, _flags: OFlags) -> Result<(), Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn get_filestat(&self) -> Result<Filestat, Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn set_filestat_size(&self, _size: u64) -> Result<(), Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Stdout(std::io::Stdout);
|
||||||
|
|
||||||
|
pub fn stdout() -> Stdout {
|
||||||
|
Stdout(std::io::stdout())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
impl AsRawFd for Stdout {
|
||||||
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
|
self.0.as_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WasiFile for Stdout {
|
||||||
|
fn datasync(&self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn sync(&self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn get_filetype(&self) -> Result<Filetype, Error> {
|
||||||
|
Ok(Filetype::CharacterDevice)
|
||||||
|
}
|
||||||
|
fn get_fdflags(&self) -> Result<FdFlags, Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn get_oflags(&self) -> Result<OFlags, Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn set_oflags(&self, _flags: OFlags) -> Result<(), Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn get_filestat(&self) -> Result<Filestat, Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn set_filestat_size(&self, _size: u64) -> Result<(), Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Stderr(std::io::Stderr);
|
||||||
|
|
||||||
|
pub fn stderr() -> Stderr {
|
||||||
|
Stderr(std::io::stderr())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
impl AsRawFd for Stderr {
|
||||||
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
|
self.0.as_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WasiFile for Stderr {
|
||||||
|
fn datasync(&self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn sync(&self) -> Result<(), Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn get_filetype(&self) -> Result<Filetype, Error> {
|
||||||
|
Ok(Filetype::CharacterDevice)
|
||||||
|
}
|
||||||
|
fn get_fdflags(&self) -> Result<FdFlags, Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn get_oflags(&self) -> Result<OFlags, Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn set_oflags(&self, _flags: OFlags) -> Result<(), Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn get_filestat(&self) -> Result<Filestat, Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
fn set_filestat_size(&self, _size: u64) -> Result<(), Error> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
23
crates/wasi-c2/wasmtime/Cargo.toml
Normal file
23
crates/wasi-c2/wasmtime/Cargo.toml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
[package]
|
||||||
|
name = "wasi-c2-wasmtime"
|
||||||
|
version = "0.21.0"
|
||||||
|
authors = ["The Wasmtime Project Developers"]
|
||||||
|
description = "WASI implementation in Rust"
|
||||||
|
license = "Apache-2.0 WITH LLVM-exception"
|
||||||
|
categories = ["wasm"]
|
||||||
|
keywords = ["webassembly", "wasm"]
|
||||||
|
repository = "https://github.com/bytecodealliance/wasmtime"
|
||||||
|
readme = "README.md"
|
||||||
|
edition = "2018"
|
||||||
|
include = ["src/**/*", "LICENSE", "build.rs"]
|
||||||
|
build = "build.rs"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
wasi-c2 = { path = "../" }
|
||||||
|
wiggle = { path = "../../wiggle", default-features = false, version = "0.21.0" }
|
||||||
|
wasmtime-wiggle = { path = "../../wiggle/wasmtime", default-features = false, version = "0.21.0" }
|
||||||
|
cap-std = "0.7"
|
||||||
|
anyhow = "*"
|
||||||
|
wasmtime = { path = "../../wasmtime" }
|
||||||
|
|
||||||
6
crates/wasi-c2/wasmtime/build.rs
Normal file
6
crates/wasi-c2/wasmtime/build.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
fn main() {
|
||||||
|
// wasi-c2's links & build.rs ensure this variable points to the wasi root:
|
||||||
|
let wasi_root = std::env::var("DEP_WASI_C2_19_WASI").unwrap();
|
||||||
|
// Make it available as WASI_ROOT:
|
||||||
|
println!("cargo:rustc-env=WASI_ROOT={}", wasi_root);
|
||||||
|
}
|
||||||
37
crates/wasi-c2/wasmtime/src/lib.rs
Normal file
37
crates/wasi-c2/wasmtime/src/lib.rs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
pub use wasi_c2::WasiCtx;
|
||||||
|
|
||||||
|
// Defines a `struct Wasi` with member fields and appropriate APIs for dealing
|
||||||
|
// with all the various WASI exports.
|
||||||
|
wasmtime_wiggle::wasmtime_integration!({
|
||||||
|
// The wiggle code to integrate with lives here:
|
||||||
|
target: wasi_c2::snapshots::preview_1,
|
||||||
|
// This must be the same witx document as used above. This should be ensured by
|
||||||
|
// the `WASI_ROOT` env variable, which is set in wasi-common's `build.rs`.
|
||||||
|
witx: ["$WASI_ROOT/phases/snapshot/witx/wasi_snapshot_preview1.witx"],
|
||||||
|
// This must be the same ctx type as used for the target:
|
||||||
|
ctx: WasiCtx,
|
||||||
|
// This macro will emit a struct to represent the instance,
|
||||||
|
// with this name and docs:
|
||||||
|
modules: { wasi_snapshot_preview1 =>
|
||||||
|
{ name: Wasi,
|
||||||
|
docs: "An instantiated instance of the wasi exports.
|
||||||
|
|
||||||
|
This represents a wasi module which can be used to instantiate other wasm
|
||||||
|
modules. This structure exports all that various fields of the wasi instance
|
||||||
|
as fields which can be used to implement your own instantiation logic, if
|
||||||
|
necessary. Additionally [`Wasi::get_export`] can be used to do name-based
|
||||||
|
resolution.",
|
||||||
|
// Don't use the wiggle generated code to implement proc_exit, we need
|
||||||
|
// to hook directly into the runtime there:
|
||||||
|
function_override: {
|
||||||
|
proc_exit => wasi_proc_exit
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Error to return when caller module is missing memory export:
|
||||||
|
missing_memory: { wasi_c2::snapshots::preview_1::types::Errno::Inval },
|
||||||
|
});
|
||||||
|
|
||||||
|
fn wasi_proc_exit(code: i32) {
|
||||||
|
panic!("stubbed out: wasi proc exit with code {}", code)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user