diff --git a/lib/cli/src/c_gen/staticlib_header.rs b/lib/cli/src/c_gen/staticlib_header.rs index bd203c644..6449ef8b4 100644 --- a/lib/cli/src/c_gen/staticlib_header.rs +++ b/lib/cli/src/c_gen/staticlib_header.rs @@ -58,8 +58,8 @@ wasm_byte_vec_t generate_serialized_data() { return module_byte_vec; } -wasm_module_t* wasmer_static_module_new(wasm_store_t* store, const char* wasm_name) { - // wasm_name intentionally unused for now: will be used in the future. +wasm_module_t* wasmer_object_module_new(wasm_store_t* store, const char* module_name) { + // module_name intentionally unused for now: will be used in the future. wasm_byte_vec_t module_byte_vec = generate_serialized_data(); wasm_module_t* module = wasm_module_deserialize(store, &module_byte_vec); free(module_byte_vec.data); diff --git a/lib/cli/src/commands/create_exe.rs b/lib/cli/src/commands/create_exe.rs index 69b9abb42..470dd96a6 100644 --- a/lib/cli/src/commands/create_exe.rs +++ b/lib/cli/src/commands/create_exe.rs @@ -21,8 +21,7 @@ use wasmer_object::{emit_serialized, get_object_for_target}; pub type PrefixerFn = Box String + Send>; const WASMER_MAIN_C_SOURCE: &[u8] = include_bytes!("wasmer_create_exe_main.c"); -#[cfg(feature = "static-artifact-create")] -const WASMER_STATIC_MAIN_C_SOURCE: &[u8] = include_bytes!("wasmer_static_create_exe_main.c"); +const WASMER_DESERIALIZE_HEADER: &str = include_str!("wasmer_deserialize_module.h"); #[derive(Debug, Clone)] struct CrossCompile { @@ -307,9 +306,39 @@ impl CreateExe { .map_err(|err| anyhow::anyhow!(err.to_string()))?; writer.flush()?; drop(writer); + // Write down header file that includes deserialize function + { + let mut writer = BufWriter::new(File::create("static_defs.h")?); + writer.write_all(WASMER_DESERIALIZE_HEADER.as_bytes())?; + writer.flush()?; + } - let cli_given_triple = self.target_triple.clone(); - self.compile_c(wasm_object_path, cli_given_triple, output_path)?; + // 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")?; + c_src_file.write_all(WASMER_MAIN_C_SOURCE)?; + } + run_c_compile(c_src_path, &c_src_obj, self.target_triple.clone()) + .context("Failed to compile C source code")?; + LinkCode { + object_paths: vec![c_src_obj, wasm_object_path], + output_path, + additional_libraries: self.libraries.clone(), + target: self.target_triple.clone(), + ..Default::default() + } + .run() + .context("Failed to link objects together")?; } #[cfg(not(feature = "static-artifact-create"))] ObjectFormat::Symbols => { @@ -379,42 +408,6 @@ impl CreateExe { Ok(()) } - fn compile_c( - &self, - wasm_object_path: PathBuf, - target_triple: Option, - output_path: PathBuf, - ) -> anyhow::Result<()> { - // 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")?; - c_src_file.write_all(WASMER_MAIN_C_SOURCE)?; - } - run_c_compile(c_src_path, &c_src_obj, target_triple.clone()) - .context("Failed to compile C source code")?; - LinkCode { - object_paths: vec![c_src_obj, wasm_object_path], - output_path, - additional_libraries: self.libraries.clone(), - target: target_triple, - ..Default::default() - } - .run() - .context("Failed to link objects together")?; - - Ok(()) - } - fn compile_zig( &self, output_path: PathBuf, @@ -449,7 +442,7 @@ impl CreateExe { .write(true) .open(&c_src_path) .context("Failed to open C source code file")?; - c_src_file.write_all(WASMER_STATIC_MAIN_C_SOURCE)?; + c_src_file.write_all(WASMER_MAIN_C_SOURCE)?; } if !header_code_path.is_dir() { @@ -531,7 +524,7 @@ impl CreateExe { .write(true) .open(&c_src_path) .context("Failed to open C source code file")?; - c_src_file.write_all(WASMER_STATIC_MAIN_C_SOURCE)?; + c_src_file.write_all(WASMER_MAIN_C_SOURCE)?; } if !header_code_path.is_dir() { @@ -666,6 +659,7 @@ fn run_c_compile( .arg("-O2") .arg("-c") .arg(path_to_c_src) + .arg("-I.") .arg("-I") .arg(get_wasmer_include_directory()?); diff --git a/lib/cli/src/commands/create_obj.rs b/lib/cli/src/commands/create_obj.rs index f9113e45f..c8e3534ba 100644 --- a/lib/cli/src/commands/create_obj.rs +++ b/lib/cli/src/commands/create_obj.rs @@ -15,7 +15,7 @@ use std::process::Command; use wasmer::*; use wasmer_object::{emit_serialized, get_object_for_target}; -const WASMER_SERIALIZED_HEADER: &[u8] = include_bytes!("wasmer_create_exe.h"); +const WASMER_SERIALIZED_HEADER: &[u8] = include_bytes!("wasmer_deserialize_module.h"); #[derive(Debug, Parser)] /// The options for the `wasmer create-exe` subcommand @@ -152,6 +152,16 @@ impl CreateObj { self.output.display(), header_output.display(), ); + eprintln!("\n---\n"); + eprintln!( + r#"To use, link the object file to your executable and call the `wasmer_object_module_new` function defined in the header file. For example, in the C language: + + #include "{}" + + wasm_module_t *module = wasmer_object_module_new(store, "my_module_name"); + "#, + header_output.display(), + ); Ok(()) } diff --git a/lib/cli/src/commands/wasmer_create_exe_main.c b/lib/cli/src/commands/wasmer_create_exe_main.c index a58fb5c73..3fe98f62c 100644 --- a/lib/cli/src/commands/wasmer_create_exe_main.c +++ b/lib/cli/src/commands/wasmer_create_exe_main.c @@ -1,7 +1,5 @@ - #include "wasmer.h" -//#include "my_wasm.h" - +#include "static_defs.h" #include #include #include @@ -11,8 +9,8 @@ // TODO: make this define templated so that the Rust code can toggle it on/off #define WASI -extern size_t WASMER_MODULE_LENGTH asm("WASMER_MODULE_LENGTH"); -extern char WASMER_MODULE_DATA asm("WASMER_MODULE_DATA"); +extern wasm_module_t* wasmer_object_module_new(wasm_store_t* store, const char* module_name) asm("wasmer_object_module_new"); + static void print_wasmer_error() { int error_len = wasmer_last_error_length(); @@ -95,11 +93,7 @@ int main(int argc, char *argv[]) { wasm_engine_t *engine = wasm_engine_new_with_config(config); wasm_store_t *store = wasm_store_new(engine); - wasm_byte_vec_t module_byte_vec = { - .size = WASMER_MODULE_LENGTH, - .data = (const char*)&WASMER_MODULE_DATA, - }; - wasm_module_t *module = wasm_module_deserialize(store, &module_byte_vec); + wasm_module_t *module = wasmer_object_module_new(store, "module"); if (!module) { fprintf(stderr, "Failed to create module\n"); diff --git a/lib/cli/src/commands/wasmer_create_exe.h b/lib/cli/src/commands/wasmer_deserialize_module.h similarity index 84% rename from lib/cli/src/commands/wasmer_create_exe.h rename to lib/cli/src/commands/wasmer_deserialize_module.h index 98705d4fc..f0ef229aa 100644 --- a/lib/cli/src/commands/wasmer_create_exe.h +++ b/lib/cli/src/commands/wasmer_deserialize_module.h @@ -10,7 +10,7 @@ extern "C" { extern size_t WASMER_MODULE_LENGTH asm("WASMER_MODULE_LENGTH"); extern char WASMER_MODULE_DATA asm("WASMER_MODULE_DATA"); -wasm_module_t* wasmer_module_new(wasm_store_t* store, const char* wasm_name) { +wasm_module_t* wasmer_object_module_new(wasm_store_t* store, const char* module_name) { wasm_byte_vec_t module_byte_vec = { .size = WASMER_MODULE_LENGTH, .data = (const char*)&WASMER_MODULE_DATA, diff --git a/lib/cli/src/commands/wasmer_static_create_exe_main.c b/lib/cli/src/commands/wasmer_static_create_exe_main.c deleted file mode 100644 index 2276ed3bc..000000000 --- a/lib/cli/src/commands/wasmer_static_create_exe_main.c +++ /dev/null @@ -1,192 +0,0 @@ -#include "wasmer.h" -#include "static_defs.h" -#include -#include -#include - -#define own - -// TODO: make this define templated so that the Rust code can toggle it on/off -#define WASI - -extern wasm_module_t* wasmer_module_new(wasm_store_t* store) asm("wasmer_module_new"); -extern wasm_module_t* wasmer_static_module_new(wasm_store_t* store,const char* wasm_name) asm("wasmer_static_module_new"); - - -static 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("%s\n", error_str); - free(error_str); -} - -#ifdef WASI -static void pass_mapdir_arg(wasi_config_t *wasi_config, char *mapdir) { - int colon_location = strchr(mapdir, ':') - mapdir; - if (colon_location == 0) { - // error malformed argument - fprintf(stderr, "Expected mapdir argument of the form alias:directory\n"); - exit(-1); - } - - char *alias = (char *)malloc(colon_location + 1); - memcpy(alias, mapdir, colon_location); - alias[colon_location] = '\0'; - - int dir_len = strlen(mapdir) - colon_location; - char *dir = (char *)malloc(dir_len + 1); - memcpy(dir, &mapdir[colon_location + 1], dir_len); - dir[dir_len] = '\0'; - - wasi_config_mapdir(wasi_config, alias, dir); - free(alias); - free(dir); -} - -// We try to parse out `--dir` and `--mapdir` ahead of time and process those -// specially. All other arguments are passed to the guest program. -static void handle_arguments(wasi_config_t *wasi_config, int argc, - char *argv[]) { - for (int i = 1; i < argc; ++i) { - // We probably want special args like `--dir` and `--mapdir` to not be - // passed directly - if (strcmp(argv[i], "--dir") == 0) { - // next arg is a preopen directory - if ((i + 1) < argc) { - i++; - wasi_config_preopen_dir(wasi_config, argv[i]); - } else { - fprintf(stderr, "--dir expects a following argument specifying which " - "directory to preopen\n"); - exit(-1); - } - } else if (strcmp(argv[i], "--mapdir") == 0) { - // next arg is a mapdir - if ((i + 1) < argc) { - i++; - pass_mapdir_arg(wasi_config, argv[i]); - } else { - fprintf(stderr, - "--mapdir expects a following argument specifying which " - "directory to preopen in the form alias:directory\n"); - exit(-1); - } - } else if (strncmp(argv[i], "--dir=", strlen("--dir=")) == 0) { - // this arg is a preopen dir - char *dir = argv[i] + strlen("--dir="); - wasi_config_preopen_dir(wasi_config, dir); - } else if (strncmp(argv[i], "--mapdir=", strlen("--mapdir=")) == 0) { - // this arg is a mapdir - char *mapdir = argv[i] + strlen("--mapdir="); - pass_mapdir_arg(wasi_config, mapdir); - } else { - // guest argument - wasi_config_arg(wasi_config, argv[i]); - } - } -} -#endif - -int main(int argc, char *argv[]) { - wasm_config_t *config = wasm_config_new(); - wasm_engine_t *engine = wasm_engine_new_with_config(config); - wasm_store_t *store = wasm_store_new(engine); - - wasm_module_t *module = wasmer_static_module_new(store, "module"); - - if (!module) { - fprintf(stderr, "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. - -#ifdef WASI - wasi_config_t *wasi_config = wasi_config_new(argv[0]); - handle_arguments(wasi_config, argc, argv); - - wasi_env_t *wasi_env = wasi_env_new(store, wasi_config); - if (!wasi_env) { - fprintf(stderr, "Error building WASI env!\n"); - print_wasmer_error(); - return 1; - } -#endif - - wasm_importtype_vec_t import_types; - wasm_module_imports(module, &import_types); - - wasm_extern_vec_t imports; - wasm_extern_vec_new_uninitialized(&imports, import_types.size); - wasm_importtype_vec_delete(&import_types); - -#ifdef WASI - bool get_imports_result = wasi_get_imports(store, wasi_env, module, &imports); - - if (!get_imports_result) { - fprintf(stderr, "Error getting WASI imports!\n"); - print_wasmer_error(); - - return 1; - } -#endif - - wasm_instance_t *instance = wasm_instance_new(store, module, &imports, NULL); - - if (!instance) { - fprintf(stderr, "Failed to create instance\n"); - print_wasmer_error(); - return -1; - } - -#ifdef WASI - // Read the exports. - wasm_extern_vec_t exports; - wasm_instance_exports(instance, &exports); - wasm_memory_t* mem = NULL; - for (size_t i = 0; i < exports.size; i++) { - mem = wasm_extern_as_memory(exports.data[i]); - if (mem) { - break; - } - } - - if (!mem) { - fprintf(stderr, "Failed to create instance: Could not find memory in exports\n"); - print_wasmer_error(); - return -1; - } - wasi_env_set_memory(wasi_env, mem); - - own wasm_func_t *start_function = wasi_get_start_function(instance); - if (!start_function) { - fprintf(stderr, "`_start` function not found\n"); - print_wasmer_error(); - return -1; - } - - wasm_val_vec_t args = WASM_EMPTY_VEC; - wasm_val_vec_t results = WASM_EMPTY_VEC; - own wasm_trap_t *trap = wasm_func_call(start_function, &args, &results); - if (trap) { - fprintf(stderr, "Trap is not NULL: TODO:\n"); - return -1; - } -#endif - - // TODO: handle non-WASI start (maybe with invoke?) - -#ifdef WASI - wasi_env_delete(wasi_env); - wasm_extern_vec_delete(&exports); -#endif - wasm_instance_delete(instance); - wasm_module_delete(module); - wasm_store_delete(store); - wasm_engine_delete(engine); - return 0; -}