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:
Pat Hickey
2020-12-11 15:00:19 -08:00
parent 73058658f4
commit 22db10e643
8 changed files with 238 additions and 0 deletions

View File

@@ -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"

View File

@@ -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());
} }

View File

@@ -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
}
}

View File

@@ -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
View 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!()
}
}

View 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" }

View 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);
}

View 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)
}