Add first draft of wasmer create-exe

This commit is contained in:
Mark McCaskey
2020-10-08 14:13:54 -07:00
parent 6d2b55f64d
commit 65265dbd73
9 changed files with 543 additions and 128 deletions

1
Cargo.lock generated
View File

@@ -2213,6 +2213,7 @@ dependencies = [
"fern", "fern",
"log", "log",
"structopt", "structopt",
"tempfile",
"wasmer", "wasmer",
"wasmer-cache", "wasmer-cache",
"wasmer-compiler", "wasmer-compiler",

View File

@@ -28,6 +28,9 @@
# define DEPRECATED(message) __declspec(deprecated(message)) # define DEPRECATED(message) __declspec(deprecated(message))
#endif #endif
// The `jit` feature has been enabled for this build.
#define WASMER_JIT_ENABLED
// The `compiler` feature has been enabled for this build. // The `compiler` feature has been enabled for this build.
#define WASMER_COMPILER_ENABLED #define WASMER_COMPILER_ENABLED

View File

@@ -45,6 +45,7 @@ cfg-if = "0.1"
# For debug feature # For debug feature
fern = { version = "0.6", features = ["colored"], optional = true } fern = { version = "0.6", features = ["colored"], optional = true }
log = { version = "0.4", optional = true } log = { version = "0.4", optional = true }
tempfile = "3"
[features] [features]
# Don't add the compiler features in default, please add them on the Makefile # Don't add the compiler features in default, please add them on the Makefile

View File

@@ -1,4 +1,6 @@
use anyhow::Result; use anyhow::Result;
#[cfg(feature = "object-file")]
use wasmer_cli::commands::CreateExe;
#[cfg(feature = "wast")] #[cfg(feature = "wast")]
use wasmer_cli::commands::Wast; use wasmer_cli::commands::Wast;
use wasmer_cli::commands::{Cache, Compile, Config, Inspect, Run, SelfUpdate, Validate}; use wasmer_cli::commands::{Cache, Compile, Config, Inspect, Run, SelfUpdate, Validate};
@@ -26,6 +28,11 @@ enum WasmerCLIOptions {
#[structopt(name = "compile")] #[structopt(name = "compile")]
Compile(Compile), Compile(Compile),
/// Compile a WebAssembly binary into a native executable
#[cfg(feature = "object-file")]
#[structopt(name = "create-exe")]
CreateExe(CreateExe),
/// Get various configuration information needed /// Get various configuration information needed
/// to compile programs which use Wasmer /// to compile programs which use Wasmer
#[structopt(name = "config")] #[structopt(name = "config")]
@@ -53,6 +60,8 @@ impl WasmerCLIOptions {
Self::Cache(cache) => cache.execute(), Self::Cache(cache) => cache.execute(),
Self::Validate(validate) => validate.execute(), Self::Validate(validate) => validate.execute(),
Self::Compile(compile) => compile.execute(), Self::Compile(compile) => compile.execute(),
#[cfg(feature = "object-file")]
Self::CreateExe(create_exe) => create_exe.execute(),
Self::Config(config) => config.execute(), Self::Config(config) => config.execute(),
Self::Inspect(inspect) => inspect.execute(), Self::Inspect(inspect) => inspect.execute(),
#[cfg(feature = "wast")] #[cfg(feature = "wast")]

View File

@@ -2,6 +2,8 @@
mod cache; mod cache;
mod compile; mod compile;
mod config; mod config;
#[cfg(feature = "object-file")]
mod create_exe;
mod inspect; mod inspect;
mod run; mod run;
mod self_update; mod self_update;
@@ -9,6 +11,8 @@ mod validate;
#[cfg(feature = "wast")] #[cfg(feature = "wast")]
mod wast; mod wast;
#[cfg(feature = "object-file")]
pub use create_exe::*;
#[cfg(feature = "wast")] #[cfg(feature = "wast")]
pub use wast::*; pub use wast::*;
pub use {cache::*, compile::*, config::*, inspect::*, run::*, self_update::*, validate::*}; pub use {cache::*, compile::*, config::*, inspect::*, run::*, self_update::*, validate::*};

View File

@@ -38,8 +38,7 @@ impl Compile {
.context(format!("failed to compile `{}`", self.path.display())) .context(format!("failed to compile `{}`", self.path.display()))
} }
fn get_recommend_extension( pub(crate) fn get_recommend_extension(
&self,
engine_type: &EngineType, engine_type: &EngineType,
target_triple: &Triple, target_triple: &Triple,
) -> &'static str { ) -> &'static str {
@@ -82,7 +81,7 @@ impl Compile {
.file_stem() .file_stem()
.map(|osstr| osstr.to_string_lossy().to_string()) .map(|osstr| osstr.to_string_lossy().to_string())
.unwrap_or_default(); .unwrap_or_default();
let recommended_extension = self.get_recommend_extension(&engine_type, target.triple()); let recommended_extension = Self::get_recommend_extension(&engine_type, target.triple());
match self.output.extension() { match self.output.extension() {
Some(ext) => { Some(ext) => {
if ext != recommended_extension { if ext != recommended_extension {

View File

@@ -0,0 +1,273 @@
//! Create a standalone native executable for a given Wasm file.
use crate::store::{CompilerOptions, EngineType};
use anyhow::{Context, Result};
use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::Command;
use structopt::StructOpt;
use wasmer::*;
const WASMER_MAIN_C_SOURCE: &[u8] = include_bytes!("wasmer_create_exe_main.c");
// TODO: to get this working locally I had to add wasmer_wasm.h and wasm.h to `.wasmer/include` manually.
// this needs to be fixed before we can ship this.
#[derive(Debug, StructOpt)]
/// The options for the `wasmer create-exe` subcommand
pub struct CreateExe {
/// Input file
#[structopt(name = "FILE", parse(from_os_str))]
path: PathBuf,
/// Output file
#[structopt(name = "OUTPUT PATH", short = "o", parse(from_os_str))]
output: PathBuf,
/// Compilation Target triple
#[structopt(long = "target")]
target_triple: Option<Triple>,
#[structopt(flatten)]
compiler: CompilerOptions,
#[structopt(short = "m", multiple = true)]
cpu_features: Vec<CpuFeature>,
/// Additional libraries to link against.
/// This is useful for fixing linker errors that may occur on some systems.
#[structopt(short = "l", multiple = true)]
libraries: Vec<String>,
}
impl CreateExe {
/// Runs logic for the `compile` subcommand
pub fn execute(&self) -> Result<()> {
let target = self
.target_triple
.as_ref()
.map(|target_triple| {
let mut features = self
.cpu_features
.clone()
.into_iter()
.fold(CpuFeature::set(), |a, b| a | b);
// Cranelift requires SSE2, so we have this "hack" for now to facilitate
// usage
features |= CpuFeature::SSE2;
Target::new(target_triple.clone(), features)
})
.unwrap_or_default();
let engine_type = EngineType::ObjectFile;
let (store, compiler_type) = self
.compiler
.get_store_for_target_and_engine(target.clone(), engine_type)?;
println!("Engine: {}", engine_type.to_string());
println!("Compiler: {}", compiler_type.to_string());
println!("Target: {}", target.triple());
let working_dir = tempfile::tempdir()?;
let starting_cd = env::current_dir()?;
let output_path = starting_cd.join(&self.output);
env::set_current_dir(&working_dir)?;
// TODO: encapsulate compile code
#[cfg(not(windows))]
let wasm_object_path = PathBuf::from("wasm.o");
#[cfg(windows)]
let wasm_object_path = PathBuf::from("wasm.obj");
let wasm_module_path = starting_cd.join(&self.path);
let header_file_path = Path::new("my_wasm.h");
let module =
Module::from_file(&store, &wasm_module_path).context("failed to compile Wasm")?;
let _ = module.serialize_to_file(&wasm_object_path)?;
let artifact: &wasmer_engine_object_file::ObjectFileArtifact =
module.artifact().as_ref().downcast_ref().context(
"Engine type is ObjectFile but could not downcast artifact into ObjectFileArtifact",
)?;
let symbol_registry = artifact.symbol_registry();
let metadata_length = artifact.metadata_length();
let module_info = module.info();
let header_file_src = crate::c_gen::object_file_header::generate_header_file(
module_info,
symbol_registry,
metadata_length,
);
let header_path = header_file_path.clone();
// for C code
let mut header = std::fs::OpenOptions::new()
.create(true)
.truncate(true)
.write(true)
.open(&header_path)?;
use std::io::Write;
header.write(header_file_src.as_bytes())?;
// auto compilation
//
// write C src to disk
let c_src_path = Path::new("wasmer_main.c");
#[cfg(not(windows))]
let c_src_obj = PathBuf::from("wasmer_main.o");
#[cfg(windows)]
let c_src_obj = PathBuf::from("wasmer_main.obj");
{
let mut c_src_file = fs::OpenOptions::new()
.create_new(true)
.write(true)
.open(&c_src_path)
.context("Failed to open C source code file")?;
// TODO:
c_src_file.write_all(WASMER_MAIN_C_SOURCE)?;
}
run_c_compile(&c_src_path, &c_src_obj).context("Failed to compile C source code")?;
LinkCode {
object_paths: vec![c_src_obj, wasm_object_path],
output_path,
additional_libraries: self.libraries.clone(),
..Default::default()
}
.run()
.context("Failed to link objects together")?;
eprintln!(
"✔ Native executable compiled successfully to `{}`.",
self.output.display(),
);
Ok(())
}
}
fn get_wasmer_include_directory() -> anyhow::Result<PathBuf> {
let mut path = PathBuf::from(env::var("WASMER_DIR")?);
path.push("include");
Ok(path)
}
fn get_libwasmer_path() -> anyhow::Result<PathBuf> {
let mut path = PathBuf::from(env::var("WASMER_DIR")?);
path.push("lib");
#[cfg(not(windows))]
path.push("libwasmer.a");
#[cfg(windows)]
path.push("libwasmer.lib");
Ok(path)
}
/// Compile the C code.
fn run_c_compile(path_to_c_src: &Path, output_name: &Path) -> anyhow::Result<()> {
#[cfg(not(windows))]
let c_compiler = "cc";
#[cfg(windows)]
let c_compiler = "clang++";
let output = Command::new(c_compiler)
.arg("-O2")
.arg("-c")
.arg(path_to_c_src)
.arg("-I")
.arg(get_wasmer_include_directory()?)
.arg("-o")
.arg(output_name)
.output()?;
if !output.status.success() {
bail!(
"C code compile failed with: stdout: {}\n\nstderr: {}",
std::str::from_utf8(&output.stdout)
.expect("stdout is not utf8! need to handle arbitrary bytes"),
std::str::from_utf8(&output.stderr)
.expect("stderr is not utf8! need to handle arbitrary bytes")
);
}
Ok(())
}
/// Data used to run a linking command for generated artifacts.
#[derive(Debug)]
struct LinkCode {
/// Path to the linker used to run the linking command.
linker_path: PathBuf,
/// String used as an optimization flag.
optimization_flag: String,
/// Paths of objects to link.
object_paths: Vec<PathBuf>,
/// Additional libraries to link against.
additional_libraries: Vec<String>,
/// Path to the output target.
output_path: PathBuf,
/// Path to the static libwasmer library.
libwasmer_path: PathBuf,
}
impl Default for LinkCode {
fn default() -> Self {
#[cfg(not(windows))]
let linker = "cc";
#[cfg(windows)]
let linker = "clang";
Self {
linker_path: PathBuf::from(linker),
optimization_flag: String::from("-O2"),
object_paths: vec![],
additional_libraries: vec![],
output_path: PathBuf::from("a.out"),
libwasmer_path: get_libwasmer_path().unwrap(),
}
}
}
impl LinkCode {
// TODO: `wasmer create-exe` needs a command line flag for extra libraries to link aganist
// or perhaps we just want to add a flag for passing things to the linker
fn run(&self) -> anyhow::Result<()> {
let mut command = Command::new(&self.linker_path);
let command = command
.arg(&self.optimization_flag)
.args(
self.object_paths
.iter()
.map(|path| path.canonicalize().unwrap()),
)
.arg(
&self
.libwasmer_path
.canonicalize()
.context("Failed to find libwasmer")?,
);
#[cfg(windows)]
let command = command.arg("-luserenv").arg("-lWs2_32").arg("-ladvapi32");
#[cfg(not(windows))]
let command = command.arg("-ldl").arg("-lm").arg("-pthread");
let link_aganist_extra_libs = self
.additional_libraries
.iter()
.map(|lib| format!("-l{}", lib));
let command = command.args(link_aganist_extra_libs);
let output = command.arg("-o").arg(&self.output_path).output()?;
if !output.status.success() {
bail!(
"linking failed with: stdout: {}\n\nstderr: {}",
std::str::from_utf8(&output.stdout)
.expect("stdout is not utf8! need to handle arbitrary bytes"),
std::str::from_utf8(&output.stderr)
.expect("stderr is not utf8! need to handle arbitrary bytes")
);
}
Ok(())
}
}

View File

@@ -0,0 +1,89 @@
#ifdef __cplusplus
extern "C" {
#endif
#include "wasmer_wasm.h"
#include "wasm.h"
#include "my_wasm.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef __cplusplus
}
#endif
void print_wasmer_error()
{
int error_len = wasmer_last_error_length();
printf("Error len: `%d`\n", error_len);
char* error_str = (char*) malloc(error_len);
wasmer_last_error_message(error_str, error_len);
printf("Error str: `%s`\n", error_str);
}
int main() {
printf("Initializing...\n");
wasm_config_t* config = wasm_config_new();
wasm_config_set_engine(config, OBJECT_FILE);
wasm_engine_t* engine = wasm_engine_new_with_config(config);
wasm_store_t* store = wasm_store_new(engine);
wasm_module_t* module = wasmer_object_file_engine_new(store, "qjs.wasm");
if (! module) {
printf("Failed to create module\n");
print_wasmer_error();
return -1;
}
// We have now finished the memory buffer book keeping and we have a valid Module.
// In this example we're passing some JavaScript source code as a command line argument
// to a WASI module that can evaluate JavaScript.
wasi_config_t* wasi_config = wasi_config_new("constant_value_here");
const char* js_string = "function greet(name) { return JSON.stringify('Hello, ' + name); }; print(greet('World'));";
wasi_config_arg(wasi_config, "--eval");
wasi_config_arg(wasi_config, js_string);
wasi_env_t* wasi_env = wasi_env_new(wasi_config);
if (!wasi_env) {
printf("> Error building WASI env!\n");
print_wasmer_error();
return 1;
}
wasm_importtype_vec_t import_types;
wasm_module_imports(module, &import_types);
int num_imports = import_types.size;
wasm_extern_t** imports = (wasm_extern_t**) malloc(num_imports * sizeof(wasm_extern_t*));
wasm_importtype_vec_delete(&import_types);
bool get_imports_result = wasi_get_imports(store, module, wasi_env, imports);
if (!get_imports_result) {
printf("> Error getting WASI imports!\n");
print_wasmer_error();
return 1;
}
wasm_instance_t* instance = wasm_instance_new(store, module, (const wasm_extern_t* const*) imports, NULL);
if (! instance) {
printf("Failed to create instance\n");
print_wasmer_error();
return -1;
}
wasi_env_set_instance(wasi_env, instance);
// WASI is now set up.
void* vmctx = wasm_instance_get_vmctx_ptr(instance);
wasm_val_t* inout[2] = { NULL, NULL };
fflush(stdout);
// We're able to call our compiled function directly through a trampoline.
wasmer_trampoline_function_call__1(vmctx, wasmer_function__1, &inout);
wasm_instance_delete(instance);
wasm_module_delete(module);
wasm_store_delete(store);
wasm_engine_delete(engine);
return 0;
}

View File

@@ -14,8 +14,27 @@ use wasmer::*;
use wasmer_compiler::CompilerConfig; use wasmer_compiler::CompilerConfig;
#[derive(Debug, Clone, StructOpt)] #[derive(Debug, Clone, StructOpt)]
/// The compiler options /// The compiler and engine options
pub struct StoreOptions { pub struct StoreOptions {
#[structopt(flatten)]
compiler: CompilerOptions,
/// Use JIT Engine.
#[structopt(long, conflicts_with_all = &["native", "object_file"])]
jit: bool,
/// Use Native Engine.
#[structopt(long, conflicts_with_all = &["jit", "object_file"])]
native: bool,
/// Use ObjectFile Engine.
#[structopt(long, conflicts_with_all = &["jit", "native"])]
object_file: bool,
}
#[derive(Debug, Clone, StructOpt)]
/// The compiler options
pub struct CompilerOptions {
/// Use Singlepass compiler. /// Use Singlepass compiler.
#[structopt(long, conflicts_with_all = &["cranelift", "llvm", "backend"])] #[structopt(long, conflicts_with_all = &["cranelift", "llvm", "backend"])]
singlepass: bool, singlepass: bool,
@@ -36,19 +55,7 @@ pub struct StoreOptions {
#[structopt(long, parse(from_os_str))] #[structopt(long, parse(from_os_str))]
llvm_debug_dir: Option<PathBuf>, llvm_debug_dir: Option<PathBuf>,
/// Use JIT Engine. /// The deprecated backend flag - Please do not use
#[structopt(long, conflicts_with_all = &["native", "object_file"])]
jit: bool,
/// Use Native Engine.
#[structopt(long, conflicts_with_all = &["jit", "object_file"])]
native: bool,
/// Use ObjectFile Engine.
#[structopt(long, conflicts_with_all = &["jit", "native"])]
object_file: bool,
/// The deprecated backend flag - Please not use
#[structopt(long = "backend", hidden = true, conflicts_with_all = &["singlepass", "cranelift", "llvm"])] #[structopt(long = "backend", hidden = true, conflicts_with_all = &["singlepass", "cranelift", "llvm"])]
backend: Option<String>, backend: Option<String>,
@@ -56,80 +63,8 @@ pub struct StoreOptions {
features: WasmFeatures, features: WasmFeatures,
} }
/// The compiler used for the store #[cfg(feature = "compiler")]
#[derive(Debug, PartialEq, Eq)] impl CompilerOptions {
pub enum CompilerType {
/// Singlepass compiler
Singlepass,
/// Cranelift compiler
Cranelift,
/// LLVM compiler
LLVM,
/// Headless compiler
Headless,
}
impl CompilerType {
/// Return all enabled compilers
pub fn enabled() -> Vec<CompilerType> {
vec![
#[cfg(feature = "singlepass")]
Self::Singlepass,
#[cfg(feature = "cranelift")]
Self::Cranelift,
#[cfg(feature = "llvm")]
Self::LLVM,
]
}
}
impl ToString for CompilerType {
fn to_string(&self) -> String {
match self {
Self::Singlepass => "singlepass".to_string(),
Self::Cranelift => "cranelift".to_string(),
Self::LLVM => "llvm".to_string(),
Self::Headless => "headless".to_string(),
}
}
}
impl FromStr for CompilerType {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s {
"singlepass" => Ok(Self::Singlepass),
"cranelift" => Ok(Self::Cranelift),
"llvm" => Ok(Self::LLVM),
"headless" => Ok(Self::Headless),
backend => bail!("The `{}` compiler does not exist.", backend),
}
}
}
/// The engine used for the store
#[derive(Debug, PartialEq, Eq)]
pub enum EngineType {
/// JIT Engine
JIT,
/// Native Engine
Native,
/// Object File Engine
ObjectFile,
}
impl ToString for EngineType {
fn to_string(&self) -> String {
match self {
Self::JIT => "jit".to_string(),
Self::Native => "native".to_string(),
Self::ObjectFile => "objectfile".to_string(),
}
}
}
#[cfg(all(feature = "compiler", feature = "engine"))]
impl StoreOptions {
fn get_compiler(&self) -> Result<CompilerType> { fn get_compiler(&self) -> Result<CompilerType> {
if self.cranelift { if self.cranelift {
Ok(CompilerType::Cranelift) Ok(CompilerType::Cranelift)
@@ -161,7 +96,7 @@ impl StoreOptions {
} }
} }
/// Get the Target architecture /// Get the enaled Wasm features.
pub fn get_features(&self, mut features: Features) -> Result<Features> { pub fn get_features(&self, mut features: Features) -> Result<Features> {
if self.features.threads || self.features.all { if self.features.threads || self.features.all {
features.threads(true); features.threads(true);
@@ -181,6 +116,63 @@ impl StoreOptions {
Ok(features) Ok(features)
} }
/// Gets the Store for a given target and engine.
pub fn get_store_for_target_and_engine(
&self,
target: Target,
engine_type: EngineType,
) -> Result<(Store, CompilerType)> {
let (compiler_config, compiler_type) = self.get_compiler_config()?;
let engine = self.get_engine_by_type(target, compiler_config, engine_type)?;
let store = Store::new(&*engine);
Ok((store, compiler_type))
}
fn get_engine_by_type(
&self,
target: Target,
compiler_config: Box<dyn CompilerConfig>,
engine_type: EngineType,
) -> Result<Box<dyn Engine + Send + Sync>> {
let features = self.get_features(compiler_config.default_features_for_target(&target))?;
let engine: Box<dyn Engine + Send + Sync> = match engine_type {
#[cfg(feature = "jit")]
EngineType::JIT => Box::new(
wasmer_engine_jit::JIT::new(&*compiler_config)
.features(features)
.target(target)
.engine(),
),
#[cfg(feature = "native")]
EngineType::Native => {
let mut compiler_config = compiler_config;
Box::new(
wasmer_engine_native::Native::new(&mut *compiler_config)
.target(target)
.features(features)
.engine(),
)
}
#[cfg(feature = "object-file")]
EngineType::ObjectFile => {
let mut compiler_config = compiler_config;
Box::new(
wasmer_engine_object_file::ObjectFile::new(&mut *compiler_config)
.target(target)
.features(features)
.engine(),
)
}
#[cfg(not(all(feature = "jit", feature = "native", feature = "object-file")))]
engine => bail!(
"The `{}` engine is not included in this binary.",
engine.to_string()
),
};
Ok(engine)
}
/// Get the Compiler Config for the current options /// Get the Compiler Config for the current options
#[allow(unused_variables)] #[allow(unused_variables)]
pub(crate) fn get_compiler_config(&self) -> Result<(Box<dyn CompilerConfig>, CompilerType)> { pub(crate) fn get_compiler_config(&self) -> Result<(Box<dyn CompilerConfig>, CompilerType)> {
@@ -315,7 +307,82 @@ impl StoreOptions {
#[allow(unreachable_code)] #[allow(unreachable_code)]
Ok((compiler_config, compiler)) Ok((compiler_config, compiler))
} }
}
/// The compiler used for the store
#[derive(Debug, PartialEq, Eq)]
pub enum CompilerType {
/// Singlepass compiler
Singlepass,
/// Cranelift compiler
Cranelift,
/// LLVM compiler
LLVM,
/// Headless compiler
Headless,
}
impl CompilerType {
/// Return all enabled compilers
pub fn enabled() -> Vec<CompilerType> {
vec![
#[cfg(feature = "singlepass")]
Self::Singlepass,
#[cfg(feature = "cranelift")]
Self::Cranelift,
#[cfg(feature = "llvm")]
Self::LLVM,
]
}
}
impl ToString for CompilerType {
fn to_string(&self) -> String {
match self {
Self::Singlepass => "singlepass".to_string(),
Self::Cranelift => "cranelift".to_string(),
Self::LLVM => "llvm".to_string(),
Self::Headless => "headless".to_string(),
}
}
}
impl FromStr for CompilerType {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
match s {
"singlepass" => Ok(Self::Singlepass),
"cranelift" => Ok(Self::Cranelift),
"llvm" => Ok(Self::LLVM),
"headless" => Ok(Self::Headless),
backend => bail!("The `{}` compiler does not exist.", backend),
}
}
}
/// The engine used for the store
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum EngineType {
/// JIT Engine
JIT,
/// Native Engine
Native,
/// Object File Engine
ObjectFile,
}
impl ToString for EngineType {
fn to_string(&self) -> String {
match self {
Self::JIT => "jit".to_string(),
Self::Native => "native".to_string(),
Self::ObjectFile => "objectfile".to_string(),
}
}
}
#[cfg(all(feature = "compiler", feature = "engine"))]
impl StoreOptions {
/// Gets the store for the host target, with the engine name and compiler name selected /// Gets the store for the host target, with the engine name and compiler name selected
pub fn get_store(&self) -> Result<(Store, EngineType, CompilerType)> { pub fn get_store(&self) -> Result<(Store, EngineType, CompilerType)> {
let target = Target::default(); let target = Target::default();
@@ -327,7 +394,7 @@ impl StoreOptions {
&self, &self,
target: Target, target: Target,
) -> Result<(Store, EngineType, CompilerType)> { ) -> Result<(Store, EngineType, CompilerType)> {
let (compiler_config, compiler_type) = self.get_compiler_config()?; let (compiler_config, compiler_type) = self.compiler.get_compiler_config()?;
let (engine, engine_type) = self.get_engine_with_compiler(target, compiler_config)?; let (engine, engine_type) = self.get_engine_with_compiler(target, compiler_config)?;
let store = Store::new(&*engine); let store = Store::new(&*engine);
Ok((store, engine_type, compiler_type)) Ok((store, engine_type, compiler_type))
@@ -339,41 +406,10 @@ impl StoreOptions {
compiler_config: Box<dyn CompilerConfig>, compiler_config: Box<dyn CompilerConfig>,
) -> Result<(Box<dyn Engine + Send + Sync>, EngineType)> { ) -> Result<(Box<dyn Engine + Send + Sync>, EngineType)> {
let engine_type = self.get_engine()?; let engine_type = self.get_engine()?;
let features = self.get_features(compiler_config.default_features_for_target(&target))?; let engine = self
let engine: Box<dyn Engine + Send + Sync> = match engine_type { .compiler
#[cfg(feature = "jit")] .get_engine_by_type(target, compiler_config, engine_type)?;
EngineType::JIT => Box::new(
wasmer_engine_jit::JIT::new(&*compiler_config)
.features(features)
.target(target)
.engine(),
),
#[cfg(feature = "native")]
EngineType::Native => {
let mut compiler_config = compiler_config;
Box::new(
wasmer_engine_native::Native::new(&mut *compiler_config)
.target(target)
.features(features)
.engine(),
)
}
#[cfg(feature = "object-file")]
EngineType::ObjectFile => {
let mut compiler_config = compiler_config;
Box::new(
wasmer_engine_object_file::ObjectFile::new(&mut *compiler_config)
.target(target)
.features(features)
.engine(),
)
}
#[cfg(not(all(feature = "jit", feature = "native", feature = "object-file")))]
engine => bail!(
"The `{}` engine is not included in this binary.",
engine.to_string()
),
};
Ok((engine, engine_type)) Ok((engine, engine_type))
} }
} }