Update from feedback, fix CI issues, update wasi-test

This commit is contained in:
Mark McCaskey 2019-11-21 10:57:04 -08:00
parent 064ffd3938
commit be217e8f8e
7 changed files with 142 additions and 130 deletions

View File

@ -58,8 +58,8 @@ members = [
"lib/wasi-tests",
"lib/emscripten-tests",
"lib/middleware-common-tests",
"examples/plugin-for-example",
"examples/parallel",
"examples/plugin-for-example",
"examples/parallel-guest",
]

View File

@ -16,7 +16,13 @@ fn serializing_works() {
b"GOROOT=$HOME/.cargo/bin".into_iter().cloned().collect(),
];
let wasm_binary = include_bytes!("../wasitests/fd_read.wasm");
let import_object = generate_import_object(
let module = compile(&wasm_binary[..])
.map_err(|e| format!("Can't compile module: {:?}", e))
.unwrap();
let wasi_version = get_wasi_version(&module).expect("WASI module");
let import_object = generate_import_object_for_version(
wasi_version,
args.clone(),
envs.clone(),
vec![],
@ -25,9 +31,6 @@ fn serializing_works() {
std::path::PathBuf::from("wasitests/test_fs/hamlet"),
)],
);
let module = compile(&wasm_binary[..])
.map_err(|e| format!("Can't compile module: {:?}", e))
.unwrap();
let state_bytes = {
let instance = module.instantiate(&import_object).unwrap();

View File

@ -20,9 +20,4 @@ serde = { version = "1", features = ["derive"] }
wasmer-runtime-core = { path = "../runtime-core", version = "0.10.1" }
[target.'cfg(windows)'.dependencies]
winapi = "0.3"
[features]
# Enable support for the older snapshot0 WASI modules
snapshot0 = []
default = ["snapshot0"]
winapi = "0.3"

View File

@ -130,9 +130,24 @@ pub fn generate_import_object(
}
}
#[cfg(feature = "snapshot0")]
/// Creates a Wasi [`ImportObject`] with [`WasiState`] for the given [`WasiVersion`].
pub fn generate_import_object_for_version(
version: WasiVersion,
args: Vec<Vec<u8>>,
envs: Vec<Vec<u8>>,
preopened_files: Vec<PathBuf>,
mapped_dirs: Vec<(String, PathBuf)>,
) -> ImportObject {
match version {
WasiVersion::Snapshot0 => {
generate_import_object_snapshot0(args, envs, preopened_files, mapped_dirs)
}
WasiVersion::Snapshot1 => generate_import_object(args, envs, preopened_files, mapped_dirs),
}
}
/// Creates a legacy Wasi [`ImportObject`] with [`WasiState`].
pub fn generate_import_object_snapshot0(
fn generate_import_object_snapshot0(
args: Vec<Vec<u8>>,
envs: Vec<Vec<u8>>,
preopened_files: Vec<PathBuf>,

View File

@ -2,5 +2,4 @@
//!
//! If you are relying on legacy WASI, please upgrade for the best experience.
#[cfg(feature = "snapshot0")]
pub mod snapshot0;

View File

@ -5,7 +5,6 @@ pub mod unix;
#[cfg(any(target_os = "windows"))]
pub mod windows;
#[cfg(any(feature = "snapshot0"))]
pub mod legacy;
use self::types::*;

View File

@ -26,7 +26,7 @@ use wasmer_clif_backend::CraneliftCompiler;
use wasmer_llvm_backend::{LLVMCompiler, LLVMOptions};
use wasmer_runtime::{
cache::{Cache as BaseCache, FileSystemCache, WasmHash},
Func, Value, VERSION,
Value, VERSION,
};
#[cfg(feature = "managed")]
use wasmer_runtime_core::tiering::{run_tiering, InteractiveShellContext, ShellExitOperation};
@ -41,25 +41,6 @@ use wasmer_singlepass_backend::SinglePassCompiler;
#[cfg(feature = "wasi")]
use wasmer_wasi;
// stub module to make conditional compilation happy
#[cfg(not(feature = "wasi"))]
mod wasmer_wasi {
use wasmer_runtime_core::{import::ImportObject, module::Module};
pub fn is_wasi_module(_module: &Module) -> bool {
false
}
pub fn generate_import_object(
_args: Vec<Vec<u8>>,
_envs: Vec<Vec<u8>>,
_preopened_files: Vec<std::path::PathBuf>,
_mapped_dirs: Vec<(String, std::path::PathBuf)>,
) -> ImportObject {
unimplemented!()
}
}
#[derive(Debug, StructOpt)]
#[structopt(name = "wasmer", about = "Wasm execution runtime.", author)]
/// The options for the wasmer Command Line Interface
@ -308,6 +289,7 @@ fn get_mapped_dirs(input: &[String]) -> Result<Vec<(String, PathBuf)>, String> {
Ok(md)
}
#[cfg(feature = "wasi")]
fn get_env_var_args(input: &[String]) -> Result<Vec<(&str, &str)>, String> {
let mut ev = vec![];
for entry in input.iter() {
@ -323,11 +305,111 @@ fn get_env_var_args(input: &[String]) -> Result<Vec<(&str, &str)>, String> {
Ok(ev)
}
/// Helper function for `execute_wasm` (the `Run` command)
#[cfg(feature = "wasi")]
fn execute_wasi(
wasi_version: wasmer_wasi::WasiVersion,
options: &Run,
env_vars: Vec<(&str, &str)>,
module: wasmer_runtime_core::Module,
mapped_dirs: Vec<(String, PathBuf)>,
) -> Result<(), String> {
let args = if let Some(cn) = &options.command_name {
[cn.clone()]
} else {
[options.path.to_str().unwrap().to_owned()]
}
.iter()
.chain(options.args.iter())
.cloned()
.map(|arg| arg.into_bytes())
.collect();
let envs = env_vars
.into_iter()
.map(|(k, v)| format!("{}={}", k, v).into_bytes())
.collect();
let preopened_files = options.pre_opened_directories.clone();
let import_object = wasmer_wasi::generate_import_object_for_version(
wasi_version,
args,
envs,
preopened_files,
mapped_dirs,
);
#[allow(unused_mut)] // mut used in feature
let mut instance = module
.instantiate(&import_object)
.map_err(|e| format!("Can't instantiate WASI module: {:?}", e))?;
let start: wasmer_runtime::Func<(), ()> =
instance.func("_start").map_err(|e| format!("{:?}", e))?;
#[cfg(feature = "managed")]
{
let start_raw: extern "C" fn(&mut wasmer_runtime_core::vm::Ctx) =
unsafe { ::std::mem::transmute(start.get_vm_func()) };
unsafe {
run_tiering(
module.info(),
&wasm_binary,
if let Some(ref path) = options.resume {
let mut f = File::open(path).unwrap();
let mut out: Vec<u8> = vec![];
f.read_to_end(&mut out).unwrap();
Some(
wasmer_runtime_core::state::InstanceImage::from_bytes(&out)
.expect("failed to decode image"),
)
} else {
None
},
&import_object,
start_raw,
&mut instance,
options
.optimized_backends
.iter()
.map(|&backend| -> Box<dyn Fn() -> Box<dyn Compiler> + Send> {
Box::new(move || get_compiler_by_backend(backend).unwrap())
})
.collect(),
interactive_shell,
)?
};
}
#[cfg(not(feature = "managed"))]
{
use wasmer_runtime::error::RuntimeError;
let result = start.call();
if let Err(ref err) = result {
match err {
RuntimeError::Trap { msg } => return Err(format!("wasm trap occured: {}", msg)),
#[cfg(feature = "wasi")]
RuntimeError::Error { data } => {
if let Some(error_code) = data.downcast_ref::<wasmer_wasi::ExitCode>() {
std::process::exit(error_code.code as i32)
}
}
#[cfg(not(feature = "wasi"))]
RuntimeError::Error { .. } => (),
}
return Err(format!("error: {:?}", err));
}
}
Ok(())
}
/// Execute a wasm/wat file
fn execute_wasm(options: &Run) -> Result<(), String> {
let disable_cache = options.disable_cache;
let mapped_dirs = get_mapped_dirs(&options.mapped_dirs[..])?;
#[cfg(feature = "wasi")]
let env_vars = get_env_var_args(&options.env_vars[..])?;
let wasm_path = &options.path;
@ -582,103 +664,22 @@ fn execute_wasm(options: &Run) -> Result<(), String> {
)
.map_err(|e| format!("{:?}", e))?;
} else {
#[cfg(feature = "wasi")]
let wasi_version = wasmer_wasi::get_wasi_version(&module);
if cfg!(feature = "wasi") && wasi_version.is_some() {
let wasi_version = wasi_version.unwrap();
let args = if let Some(cn) = &options.command_name {
[cn.clone()]
} else {
[options.path.to_str().unwrap().to_owned()]
}
.iter()
.chain(options.args.iter())
.cloned()
.map(|arg| arg.into_bytes())
.collect();
let envs = env_vars
.into_iter()
.map(|(k, v)| format!("{}={}", k, v).into_bytes())
.collect();
let preopened_files = options.pre_opened_directories.clone();
#[cfg(feature = "wasi")]
let is_wasi = wasi_version.is_some();
#[cfg(not(feature = "wasi"))]
let is_wasi = false;
let import_object = match wasi_version {
wasmer_wasi::WasiVersion::Snapshot0 => {
wasmer_wasi::generate_import_object_snapshot0(
args,
envs,
preopened_files,
mapped_dirs,
)
}
wasmer_wasi::WasiVersion::Snapshot1 => {
wasmer_wasi::generate_import_object(args, envs, preopened_files, mapped_dirs)
}
};
#[allow(unused_mut)] // mut used in feature
let mut instance = module
.instantiate(&import_object)
.map_err(|e| format!("Can't instantiate WASI module: {:?}", e))?;
let start: Func<(), ()> = instance.func("_start").map_err(|e| format!("{:?}", e))?;
#[cfg(feature = "managed")]
{
let start_raw: extern "C" fn(&mut wasmer_runtime_core::vm::Ctx) =
unsafe { ::std::mem::transmute(start.get_vm_func()) };
unsafe {
run_tiering(
module.info(),
&wasm_binary,
if let Some(ref path) = options.resume {
let mut f = File::open(path).unwrap();
let mut out: Vec<u8> = vec![];
f.read_to_end(&mut out).unwrap();
Some(
wasmer_runtime_core::state::InstanceImage::from_bytes(&out)
.expect("failed to decode image"),
)
} else {
None
},
&import_object,
start_raw,
&mut instance,
options
.optimized_backends
.iter()
.map(|&backend| -> Box<dyn Fn() -> Box<dyn Compiler> + Send> {
Box::new(move || get_compiler_by_backend(backend).unwrap())
})
.collect(),
interactive_shell,
)?
};
}
#[cfg(not(feature = "managed"))]
{
use wasmer_runtime::error::RuntimeError;
let result = start.call();
if let Err(ref err) = result {
match err {
RuntimeError::Trap { msg } => {
return Err(format!("wasm trap occured: {}", msg))
}
#[cfg(feature = "wasi")]
RuntimeError::Error { data } => {
if let Some(error_code) = data.downcast_ref::<wasmer_wasi::ExitCode>() {
std::process::exit(error_code.code as i32)
}
}
#[cfg(not(feature = "wasi"))]
RuntimeError::Error { .. } => (),
}
return Err(format!("error: {:?}", err));
}
}
if is_wasi {
#[cfg(feature = "wasi")]
execute_wasi(
wasi_version.unwrap(),
options,
env_vars,
module,
mapped_dirs,
)?;
} else {
let import_object = wasmer_runtime_core::import::ImportObject::new();
let instance = module