mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-07 05:08:19 +00:00
Add CLI handling to wasmer_main.c
This commit is contained in:
@@ -373,7 +373,7 @@ fn conpile_atoms(
|
|||||||
|
|
||||||
/// Compile the C code.
|
/// Compile the C code.
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn run_c_compile(path_to_c_src: &Path, output_name: &Path, target: Triple) -> anyhow::Result<()> {
|
fn run_c_compile(path_to_c_src: &Path, output_name: &Path, target: &Triple) -> anyhow::Result<()> {
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
let c_compiler = "cc";
|
let c_compiler = "cc";
|
||||||
// We must use a C++ compiler on Windows because wasm.h uses `static_assert`
|
// We must use a C++ compiler on Windows because wasm.h uses `static_assert`
|
||||||
@@ -551,22 +551,38 @@ fn link_exe_from_dir(
|
|||||||
return Err(anyhow::anyhow!("file has no atoms to compile"));
|
return Err(anyhow::anyhow!("file has no atoms to compile"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let zig_binary_path = cross_compilation
|
let wasmer_main_c = generate_wasmer_main_c(&entrypoint).map_err(|e| {
|
||||||
.zig_binary_path
|
anyhow::anyhow!(
|
||||||
.as_ref()
|
"could not generate wasmer_main.c in dir {}: {e}",
|
||||||
.ok_or_else(|| anyhow::anyhow!("zig binary not found in $PATH"))?;
|
directory.display()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
std::fs::write(directory.join("wasmer_main.c"), wasmer_main_c.as_bytes()).map_err(|e| {
|
||||||
|
anyhow::anyhow!(
|
||||||
|
"could not write wasmer_main.c in dir {}: {e}",
|
||||||
|
directory.display()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
let library_path = cross_compilation
|
let library_path = cross_compilation
|
||||||
.library
|
.library
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.ok_or_else(|| anyhow::anyhow!("libwasmer.a / wasmer.lib not found"))?;
|
.ok_or_else(|| anyhow::anyhow!("libwasmer.a / wasmer.lib not found"))?;
|
||||||
|
|
||||||
match entrypoint.object_format {
|
let mut object_paths = entrypoint
|
||||||
ObjectFormat::Serialized => {
|
.atoms
|
||||||
return Err(anyhow::anyhow!(
|
.iter()
|
||||||
"ObjectFormat::Serialized + cross compilation not implemented"
|
.filter_map(|a| directory.join(&a.path).canonicalize().ok())
|
||||||
));
|
.collect::<Vec<_>>();
|
||||||
}
|
|
||||||
ObjectFormat::Symbols => {
|
object_paths.extend(
|
||||||
|
entrypoint
|
||||||
|
.volumes
|
||||||
|
.iter()
|
||||||
|
.filter_map(|v| directory.join(&v.obj_file).canonicalize().ok()),
|
||||||
|
);
|
||||||
|
|
||||||
let zig_triple = utils::triple_to_zig_triple(&cross_compilation.target);
|
let zig_triple = utils::triple_to_zig_triple(&cross_compilation.target);
|
||||||
let include_dirs = entrypoint
|
let include_dirs = entrypoint
|
||||||
.atoms
|
.atoms
|
||||||
@@ -582,17 +598,36 @@ fn link_exe_from_dir(
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let mut object_paths = entrypoint
|
|
||||||
.atoms
|
match entrypoint.object_format {
|
||||||
.iter()
|
ObjectFormat::Serialized => {
|
||||||
.filter_map(|a| directory.join(&a.path).canonicalize().ok())
|
if cross_compilation.target == Triple::host() {
|
||||||
.collect::<Vec<_>>();
|
run_c_compile(
|
||||||
object_paths.extend(
|
&directory.join("wasmer_main.c"),
|
||||||
entrypoint
|
&directory.join("wasmer_main.o"),
|
||||||
.volumes
|
&cross_compilation.target,
|
||||||
.iter()
|
)
|
||||||
.filter_map(|v| directory.join(&v.obj_file).canonicalize().ok()),
|
.map_err(|e| {
|
||||||
);
|
anyhow::anyhow!(
|
||||||
|
"could not write wasmer_main.c in dir {}: {e}",
|
||||||
|
directory.display()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
link_c_compilation()
|
||||||
|
} else {
|
||||||
|
Err(anyhow::anyhow!(
|
||||||
|
"ObjectFormat::Serialized + cross compilation not implemented"
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ObjectFormat::Symbols => {
|
||||||
|
let zig_binary_path = cross_compilation.zig_binary_path.as_ref().ok_or_else(|| {
|
||||||
|
anyhow::anyhow!(
|
||||||
|
"could not write wasmer_main.c in dir {}",
|
||||||
|
directory.display()
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
|
||||||
let mut cmd = Command::new(&zig_binary_path);
|
let mut cmd = Command::new(&zig_binary_path);
|
||||||
cmd.arg("build-exe");
|
cmd.arg("build-exe");
|
||||||
@@ -654,10 +689,101 @@ fn link_exe_from_dir(
|
|||||||
output_path.display()
|
output_path.display()
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Link compiled objects together using the system linker
|
||||||
|
fn link_c_compilation() -> Result<(), anyhow::Error> {
|
||||||
|
// TODO
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate the wasmer_main.c that links all object files together
|
||||||
|
/// (depending on the object format / atoms number)
|
||||||
|
fn generate_wasmer_main_c(entrypoint: &Entrypoint) -> Result<String, anyhow::Error> {
|
||||||
|
const WASMER_MAIN_C_SOURCE: &str = include_str!("wasmer_create_exe_main.c");
|
||||||
|
|
||||||
|
match entrypoint.object_format {
|
||||||
|
ObjectFormat::Serialized => {
|
||||||
|
Ok(WASMER_MAIN_C_SOURCE.replace("// WASI_DEFINES", "#define WASI"))
|
||||||
|
}
|
||||||
|
ObjectFormat::Symbols => {
|
||||||
|
let atom_names = entrypoint
|
||||||
|
.atoms
|
||||||
|
.iter()
|
||||||
|
.map(|a| &a.command)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let mut c_code_to_add = String::new();
|
||||||
|
let mut c_code_to_instantiate = String::new();
|
||||||
|
let mut deallocate_module = String::new();
|
||||||
|
|
||||||
|
for a in atom_names.iter() {
|
||||||
|
let atom_name = utils::normalize_atom_name(&a);
|
||||||
|
let atom_name_uppercase = atom_name.to_uppercase();
|
||||||
|
|
||||||
|
c_code_to_add.push_str(&format!(
|
||||||
|
"
|
||||||
|
extern size_t {atom_name_uppercase}_LENGTH asm(\"{atom_name_uppercase}_LENGTH\");
|
||||||
|
extern char {atom_name_uppercase}_DATA asm(\"{atom_name_uppercase}_DATA\");
|
||||||
|
"
|
||||||
|
));
|
||||||
|
|
||||||
|
c_code_to_instantiate.push_str(&format!("
|
||||||
|
wasm_byte_vec_t atom_{atom_name}_byte_vec = {{
|
||||||
|
.size = {atom_name_uppercase}_LENGTH,
|
||||||
|
.data = &{atom_name_uppercase}_DATA,
|
||||||
|
}};
|
||||||
|
wasm_module_t *atom_{atom_name} = wasm_module_deserialize(store, &atom_{atom_name}_byte_vec);
|
||||||
|
if (!atom_{atom_name}) {{
|
||||||
|
fprintf(stderr, \"Failed to create module from atom \\\"{atom_name}\\\"\\n\");
|
||||||
|
print_wasmer_error();
|
||||||
|
return -1;
|
||||||
|
}}
|
||||||
|
"));
|
||||||
|
deallocate_module.push_str(&format!("wasm_module_delete(atom_{atom_name});"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let return_str = WASMER_MAIN_C_SOURCE
|
||||||
|
.replace("#define WASI", "#define WASI\r\n#define WASI_PIRITA")
|
||||||
|
.replace("// DECLARE_MODULES", &c_code_to_add)
|
||||||
|
.replace("wasm_module_delete(module);", &deallocate_module);
|
||||||
|
|
||||||
|
if atom_names.len() == 1 {
|
||||||
|
let atom_to_run = &atom_names[0];
|
||||||
|
c_code_to_instantiate.push_str(&format!("module = atom_{atom_to_run};"));
|
||||||
|
} else {
|
||||||
|
for a in atom_names.iter() {
|
||||||
|
c_code_to_instantiate.push_str(&format!(
|
||||||
|
"if (strcmp(selected_atom, \"{a}\") == 0) {{ module = atom_{}; }}\n",
|
||||||
|
utils::normalize_atom_name(a)
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
c_code_to_instantiate.push_str(&format!(
|
||||||
|
"
|
||||||
|
if (!module) {{
|
||||||
|
fprintf(stderr, \"No --command given, available commands are:\\n\");
|
||||||
|
fprintf(stderr, \"\\n\");
|
||||||
|
{commands}
|
||||||
|
print_wasmer_error();
|
||||||
|
return -1;
|
||||||
|
}}
|
||||||
|
",
|
||||||
|
commands = atom_names
|
||||||
|
.iter()
|
||||||
|
.map(|a| format!("fprintf(stderr, \"{a}\\n\");"))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n")
|
||||||
|
));
|
||||||
|
|
||||||
|
Ok(return_str.replace("// INSTANTIATE_MODULES", &c_code_to_instantiate))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
|||||||
@@ -17,8 +17,6 @@ use wasmer_object::{emit_serialized, get_object_for_target};
|
|||||||
#[cfg(feature = "webc_runner")]
|
#[cfg(feature = "webc_runner")]
|
||||||
use webc::{ParseOptions, WebCMmap};
|
use webc::{ParseOptions, WebCMmap};
|
||||||
|
|
||||||
const WASMER_SERIALIZED_HEADER: &[u8] = include_bytes!("wasmer_create_exe.h");
|
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
/// The options for the `wasmer create-exe` subcommand
|
/// The options for the `wasmer create-exe` subcommand
|
||||||
pub struct CreateObj {
|
pub struct CreateObj {
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
#include "wasmer.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern size_t WASMER_MODULE_LENGTH asm("WASMER_MODULE_LENGTH");
|
|
||||||
extern char WASMER_MODULE_DATA asm("WASMER_MODULE_DATA");
|
|
||||||
|
|
||||||
wasm_module_t* wasmer_object_module_new(wasm_store_t* store, const char* wasm_name) {
|
|
||||||
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);
|
|
||||||
|
|
||||||
return module;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -100,22 +100,17 @@ int main(int argc, char *argv[]) {
|
|||||||
wasm_config_t *config = wasm_config_new();
|
wasm_config_t *config = wasm_config_new();
|
||||||
wasm_engine_t *engine = wasm_engine_new_with_config(config);
|
wasm_engine_t *engine = wasm_engine_new_with_config(config);
|
||||||
wasm_store_t *store = wasm_store_new(engine);
|
wasm_store_t *store = wasm_store_new(engine);
|
||||||
|
wasm_module_t *module = NULL;
|
||||||
|
|
||||||
#ifdef WASI_PIRITA
|
const char* selected_atom = "main";
|
||||||
// INSTANTIATE_MODULES
|
for (int i = 1; i < argc; i++) {
|
||||||
#else
|
if (strcmp(argv[i], "--command") == 0 && i + 1 < argc) {
|
||||||
wasm_byte_vec_t module_byte_vec = {
|
selected_atom = argv[i + 1];
|
||||||
.size = WASMER_MODULE_LENGTH,
|
break;
|
||||||
.data = &WASMER_MODULE_DATA,
|
|
||||||
};
|
|
||||||
wasm_module_t *module = wasm_module_deserialize(store, &module_byte_vec);
|
|
||||||
|
|
||||||
if (!module) {
|
|
||||||
fprintf(stderr, "Failed to create module\n");
|
|
||||||
print_wasmer_error();
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
// INSTANTIATE_MODULES
|
||||||
|
|
||||||
// We have now finished the memory buffer book keeping and we have a valid
|
// We have now finished the memory buffer book keeping and we have a valid
|
||||||
// Module.
|
// Module.
|
||||||
@@ -142,7 +137,7 @@ int main(int argc, char *argv[]) {
|
|||||||
module,
|
module,
|
||||||
filesystem,
|
filesystem,
|
||||||
&imports,
|
&imports,
|
||||||
"##atom-name##"
|
selected_atom,
|
||||||
);
|
);
|
||||||
if (!wasi_env) {
|
if (!wasi_env) {
|
||||||
printf("Error setting filesystem\n");
|
printf("Error setting filesystem\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user