Merge pull request #2251 from wasmerio/feature/multiple-wasi-versions-in-li

Allow CLI to exec WASI w/ multiple namespaces
This commit is contained in:
Mark McCaskey
2021-04-28 12:28:55 -04:00
committed by GitHub
5 changed files with 186 additions and 18 deletions

View File

@@ -152,8 +152,28 @@ impl Run {
// If WASI is enabled, try to execute it with it
#[cfg(feature = "wasi")]
{
let wasi_version = Wasi::get_version(&module);
if wasi_version.is_some() {
use std::collections::BTreeSet;
use wasmer_wasi::WasiVersion;
let wasi_versions = Wasi::get_versions(&module);
if let Some(wasi_versions) = wasi_versions {
if wasi_versions.len() >= 2 {
let get_version_list = |versions: &BTreeSet<WasiVersion>| -> String {
versions
.iter()
.map(|v| format!("`{}`", v.get_namespace_str()))
.collect::<Vec<String>>()
.join(", ")
};
if self.wasi.deny_multiple_wasi_versions {
let version_list = get_version_list(&wasi_versions);
bail!("Found more than 1 WASI version in this module ({}) and `--deny-multiple-wasi-versions` is enabled.", version_list);
} else if !self.wasi.allow_multiple_wasi_versions {
let version_list = get_version_list(&wasi_versions);
warning!("Found more than 1 WASI version in this module ({}). If this is intentional, pass `--allow-multiple-wasi-versions` to suppress this warning.", version_list);
}
}
let program_name = self
.command_name
.clone()

View File

@@ -1,8 +1,9 @@
use crate::utils::{parse_envvar, parse_mapdir};
use anyhow::{Context, Result};
use std::collections::BTreeSet;
use std::path::PathBuf;
use wasmer::{Instance, Module};
use wasmer_wasi::{get_wasi_version, WasiError, WasiState, WasiVersion};
use wasmer_wasi::{get_wasi_versions, WasiError, WasiState, WasiVersion};
use clap::Clap;
@@ -13,7 +14,7 @@ pub struct Wasi {
#[clap(long = "dir", name = "DIR", multiple = true, group = "wasi")]
pre_opened_directories: Vec<PathBuf>,
/// Map a host directory to a different location for the wasm module
/// Map a host directory to a different location for the Wasm module
#[clap(long = "mapdir", name = "GUEST_DIR:HOST_DIR", multiple = true, parse(try_from_str = parse_mapdir))]
mapped_dirs: Vec<(String, PathBuf)>,
@@ -25,22 +26,30 @@ pub struct Wasi {
#[cfg(feature = "experimental-io-devices")]
#[clap(long = "enable-experimental-io-devices")]
enable_experimental_io_devices: bool,
/// Allow WASI modules to import multiple versions of WASI without a warning.
#[clap(long = "allow-multiple-wasi-versions")]
pub allow_multiple_wasi_versions: bool,
/// Require WASI modules to only import 1 version of WASI.
#[clap(long = "deny-multiple-wasi-versions")]
pub deny_multiple_wasi_versions: bool,
}
#[allow(dead_code)]
impl Wasi {
/// Gets the WASI version (if any) for the provided module
pub fn get_version(module: &Module) -> Option<WasiVersion> {
pub fn get_versions(module: &Module) -> Option<BTreeSet<WasiVersion>> {
// Get the wasi version in strict mode, so no other imports are
// allowed.
get_wasi_version(&module, true)
get_wasi_versions(&module, true)
}
/// Checks if a given module has any WASI imports at all.
pub fn has_wasi_imports(module: &Module) -> bool {
// Get the wasi version in non-strict mode, so no other imports
// are allowed
get_wasi_version(&module, false).is_some()
get_wasi_versions(&module, false).is_some()
}
/// Helper function for executing Wasi from the `Run` command.
@@ -63,8 +72,8 @@ impl Wasi {
}
let mut wasi_env = wasi_state_builder.finalize()?;
let import_object = wasi_env.import_object(&module)?;
let instance = Instance::new(&module, &import_object)?;
let resolver = wasi_env.import_object_for_all_wasi_versions(&module)?;
let instance = Instance::new(&module, &resolver)?;
let start = instance.exports.get_function("_start")?;
let result = start.call(&[]);