This repository has been archived by the owner on Jul 16, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This demo is the trivial approach to implementing a custom WASI. It contains a copy of the wasmtime-wasi implementation, which is rather a short-term solution and not sustainable any longer than a few iterations. As a demo customization, it redirects all output from fd=2 (stderr) to fd=1 (stdout).
- Loading branch information
Showing
15 changed files
with
3,032 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
[package] | ||
name = "wasmtime-wasi-custom" | ||
version = "0.1.0" | ||
authors = ["Stefan Junker <[email protected]>"] | ||
edition = "2018" | ||
build = "build.rs" | ||
|
||
[dependencies] | ||
wasmtime-api = { git = "https://github.com/CraneStation/wasmtime", package = "wasmtime-api", rev = "9c747db4293192dffe659ed741070716caeb43b0" } | ||
wasmtime-jit = { git = "https://github.com/CraneStation/wasmtime", package = "wasmtime-jit", rev = "9c747db4293192dffe659ed741070716caeb43b0" } | ||
wasmtime-interface-types = { git = "https://github.com/CraneStation/wasmtime", package = "wasmtime-interface-types", rev = "9c747db4293192dffe659ed741070716caeb43b0" } | ||
|
||
# wasmtime-api = { path = "/home/steveej/src/job-redhat/enarx/github_cranestation_wasmtime/wasmtime-api" } | ||
# wasmtime-jit = { path = "/home/steveej/src/job-redhat/enarx/github_cranestation_wasmtime/wasmtime-jit" } | ||
# wasmtime-interface-types = { path = "/home/steveej/src/job-redhat/enarx/github_cranestation_wasmtime/wasmtime-interface-types" } | ||
|
||
# A copy of wasmtime-wasi at v0.3.0 made for customisation purposes | ||
wasmtime-wasi = { path = "wasmtime-wasi" } | ||
# wasmtime-wasi = { path = "/home/steveej/src/job-redhat/enarx/github_cranestation_wasmtime/wasmtime-wasi" } | ||
|
||
log = "0.4" | ||
env_logger = "0.6" | ||
|
||
[features] | ||
default = ["rust"] | ||
|
||
c = [] | ||
rust = [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Wasmtime Custom WASI Demo | ||
This is an example crate demonstrating how Enarx may use Wasmtime, a Rust-powered JIT, to natively run programs from several different source languages (Rust/C/C++) compiled to WASI-compliant WASM. | ||
|
||
## Running the demo | ||
|
||
By default, the Rust demo should run with `cargo run` out of the box. | ||
|
||
If you wish to compile the C demo, you'll need to install `lld` . On Fedora, this can be accomplished with `sudo dnf install lld`. | ||
|
||
### Switching Languages | ||
|
||
The WASM binary used for the demo can be compiled from either Rust or C. Compilation of this binary happens at build time, and the source language can be controlled via Cargo features. | ||
|
||
Rust is compiled by default. If C is desired, the appropriate feature can be invoked via the `cargo` command: | ||
|
||
``` | ||
cargo run --no-default-features --features c | ||
``` | ||
|
||
Or, alternatively, by changing the `default` feature in `Cargo.toml` from `["rust"]` to `["c"]`. | ||
|
||
## Changelog | ||
This demo is expected to evolve over time. | ||
|
||
### v0.1.0 | ||
Customizes `fd_write` so that all writes to fd=2 (stdin) are redirected to fd=1 (stdout). | ||
Uses an in-tree copy of `wasmtime-wasi` with customizations to the glue code. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
use std::process::Command; | ||
|
||
fn main() { | ||
let out = std::env::var("OUT_DIR").unwrap(); | ||
|
||
if cfg!(feature = "c") { | ||
println!("Compiling C app to WASM..."); | ||
let cc = std::env::var("CC").unwrap_or("clang".to_owned()); | ||
assert!(Command::new(cc) | ||
.args(&["-o", &format!("{}/app.wasm", out)]) | ||
.arg("--target=wasm32-unknown-wasi") | ||
.arg("-Wl,--export-all") | ||
.arg("-Wl,--no-entry") | ||
.arg("-nostdlib") | ||
.arg("-O3") | ||
.arg("src/app.c") | ||
.status() | ||
.expect("failed to compile WASM module") | ||
.success()); | ||
} | ||
|
||
if cfg!(feature = "rust") { | ||
println!("Compiling Rust app to WASM..."); | ||
assert!(Command::new("rustc") | ||
// .args(&["-C", "lto"]) | ||
// .args(&["-C", "opt-level=3"]) | ||
// .args(&["--target", "wasm32-unknown-unknown"]) | ||
.args(&["--target", "wasm32-wasi"]) | ||
.args(&["-o", &format!("{}/app.wasm", out)]) | ||
.arg("src/app.rs") | ||
.status() | ||
.expect("failed to compile WASM module") | ||
.success()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
int add(int l, int r) { | ||
return l + r; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
fn main() {} | ||
|
||
#[no_mangle] | ||
pub extern fn hello_world() { | ||
println!("Hello, world!"); | ||
eprintln!("Hello, stderr!"); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
use log::{info, trace}; | ||
use std::collections::HashMap; | ||
use std::error::Error; | ||
use std::fs::read; | ||
use wasmtime_api::{self, HostRef}; | ||
|
||
fn main() -> Result<(), Box<dyn Error>> { | ||
let _ = env_logger::try_init_from_env(env_logger::Env::default()); | ||
|
||
// Before we begin, it'll be heplful to know which source language we're | ||
// running, so let's print it out. | ||
if cfg!(feature = "c") { | ||
info!("WASM application binary has been compiled from C."); | ||
} | ||
if cfg!(feature = "rust") { | ||
info!("WASM appliation binary has been compiled from Rust."); | ||
} | ||
|
||
// Load and instnatiate the WASM app | ||
info!("Loading WASM application binary..."); | ||
let app_wasm = read(concat!(env!("OUT_DIR"), "/app.wasm")).unwrap(); | ||
info!("WASM application binary loaded."); | ||
|
||
// wasmtime-api variables | ||
let engine = HostRef::new(wasmtime_api::Engine::default()); | ||
let store = HostRef::new(wasmtime_api::Store::new(engine)); | ||
let mut module_registry: HashMap<String, (wasmtime_api::Instance, HashMap<String, usize>)> = | ||
HashMap::new(); | ||
|
||
// Instantiate WASI | ||
let custom_wasi = wasmtime_wasi::instantiate_wasi( | ||
// prefix: &str, | ||
"", | ||
// global_exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>, | ||
store.borrow().global_exports().clone(), | ||
// preopened_dirs: &[(String, File)], | ||
Default::default(), | ||
// argv: &[String], | ||
Default::default(), | ||
// environ: &[(String, String)], | ||
Default::default(), | ||
) | ||
.expect("could nt instantiate WASI"); | ||
module_registry.insert( | ||
"wasi_unstable".to_string(), | ||
wasmtime_api::Instance::from_handle(store.clone(), custom_wasi)?, | ||
); | ||
|
||
let app_module = HostRef::new(wasmtime_api::Module::new(store.clone(), &app_wasm)?); | ||
|
||
// Resolve import using module_registry. | ||
let imports = { | ||
// let module_borrow: std::cell::Ref<'_, wasmtime_api::Module> = app_module.borrow(); | ||
|
||
app_module | ||
.borrow() | ||
.imports() | ||
.iter() | ||
.map(|i| { | ||
let module_name = i.module().to_string(); | ||
if let Some((instance, map)) = module_registry.get(&module_name) { | ||
let field_name = i.name().to_string(); | ||
if let Some(export_index) = map.get(&field_name) { | ||
trace!("found export: {}/{}", field_name, module_name); | ||
Ok(instance.exports()[*export_index].clone()) | ||
} else { | ||
Err(format!( | ||
"Import {} was not found in module {}", | ||
field_name, module_name | ||
)) | ||
} | ||
} else { | ||
Err(format!("Import module {} was not found", module_name)) | ||
} | ||
}) | ||
.collect::<Result<Vec<_>, _>>()? | ||
}; | ||
|
||
let instance = HostRef::new(wasmtime_api::Instance::new( | ||
store.clone(), | ||
app_module.clone(), | ||
&imports, | ||
)?); | ||
|
||
let mut handle = instance.borrow().handle().clone(); | ||
let mut context = store.borrow().engine().borrow().create_wasmtime_context(); | ||
let module_data = wasmtime_interface_types::ModuleData::new(&app_wasm)?; | ||
|
||
// Invoke the function | ||
module_data.invoke(&mut context, &mut handle, "hello_world", Default::default())?; | ||
|
||
Ok(()) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
[package] | ||
name = "wasmtime-wasi" | ||
version = "0.2.0" | ||
authors = ["The Cranelift Project Developers"] | ||
description = "WASI API support for Wasmtime" | ||
categories = ["wasm"] | ||
repository = "https://github.com/CraneStation/wasmtime" | ||
license = "Apache-2.0 WITH LLVM-exception" | ||
readme = "README.md" | ||
edition = "2018" | ||
|
||
[dependencies] | ||
# wasmtime-runtime = { path = "../wasmtime-runtime" } | ||
wasmtime-runtime = { git = "https://github.com/CraneStation/wasmtime", package = "wasmtime-runtime", rev = "9c747db4293192dffe659ed741070716caeb43b0" } | ||
# wasmtime-environ = { path = "../wasmtime-environ" } | ||
wasmtime-environ = { git = "https://github.com/CraneStation/wasmtime", package = "wasmtime-environ", rev = "9c747db4293192dffe659ed741070716caeb43b0" } | ||
# wasmtime-jit = { path = "../wasmtime-jit" } | ||
wasmtime-jit = { git = "https://github.com/CraneStation/wasmtime", package = "wasmtime-jit", rev = "9c747db4293192dffe659ed741070716caeb43b0" } | ||
wasi-common = { git = "https://github.com/CraneStation/wasi-common", rev = "8ea7a983d8b1364e5f62d2adf0e74b3b8db1c9b3" } | ||
cranelift-codegen = { version = "0.41.0", features = ["enable-serde"] } | ||
cranelift-entity = { version = "0.41.0", features = ["enable-serde"] } | ||
cranelift-wasm = { version = "0.41.0", features = ["enable-serde"] } | ||
target-lexicon = "0.4.0" | ||
log = { version = "0.4.8", default-features = false } | ||
|
||
[badges] | ||
maintenance = { status = "experimental" } | ||
travis-ci = { repository = "CraneStation/wasmtime" } |
Oops, something went wrong.