mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-10 14:48:27 +00:00
Add initial implementation of Entrypoint::Multi
This commit is contained in:
@@ -94,7 +94,7 @@ pub fn generate_header_file(
|
|||||||
CStatement::Declaration {
|
CStatement::Declaration {
|
||||||
name: match module_info.name.as_deref() {
|
name: match module_info.name.as_deref() {
|
||||||
Some(s) => format!("WASMER_METADATA_{}", s.to_uppercase()),
|
Some(s) => format!("WASMER_METADATA_{}", s.to_uppercase()),
|
||||||
None => "WASMER_METADATA".to_string()
|
None => "WASMER_METADATA".to_string(),
|
||||||
},
|
},
|
||||||
is_extern: true,
|
is_extern: true,
|
||||||
is_const: true,
|
is_const: true,
|
||||||
|
|||||||
@@ -28,16 +28,16 @@ pub use compile::*;
|
|||||||
pub use create_exe::*;
|
pub use create_exe::*;
|
||||||
#[cfg(feature = "static-artifact-create")]
|
#[cfg(feature = "static-artifact-create")]
|
||||||
pub use create_obj::*;
|
pub use create_obj::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "wast")]
|
#[cfg(feature = "wast")]
|
||||||
pub use wast::*;
|
pub use wast::*;
|
||||||
pub use {
|
pub use {
|
||||||
add::*, cache::*, config::*, inspect::*, list::*, login::*, run::*, self_update::*,
|
add::*, cache::*, config::*, inspect::*, list::*, login::*, run::*, self_update::*,
|
||||||
validate::*, whoami::*,
|
validate::*, whoami::*,
|
||||||
};
|
};
|
||||||
use serde::{Serialize, Deserialize};
|
|
||||||
|
|
||||||
/// The kind of object format to emit.
|
/// The kind of object format to emit.
|
||||||
#[derive(Debug, Copy, Clone, clap::Parser, Serialize, Deserialize)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, clap::Parser, Serialize, Deserialize)]
|
||||||
#[cfg(any(feature = "static-artifact-create", feature = "wasmer-artifact-create"))]
|
#[cfg(any(feature = "static-artifact-create", feature = "wasmer-artifact-create"))]
|
||||||
pub enum ObjectFormat {
|
pub enum ObjectFormat {
|
||||||
/// Serialize the entire module into an object file.
|
/// Serialize the entire module into an object file.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use super::ObjectFormat;
|
|||||||
use crate::store::CompilerOptions;
|
use crate::store::CompilerOptions;
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fmt::Write as _;
|
use std::fmt::Write as _;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
@@ -47,6 +48,28 @@ pub(crate) struct CrossCompileSetup {
|
|||||||
pub(crate) library: PathBuf,
|
pub(crate) library: PathBuf,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Given a pirita file, determines whether the file has one
|
||||||
|
/// default command as an entrypoint or multiple (need to be specified via --command)
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum Entrypoint {
|
||||||
|
/// Single command name is the entrypoint
|
||||||
|
Single(String),
|
||||||
|
/// File contains multiple entrypoints, has to be specified via --command
|
||||||
|
Multi(Vec<CommandEntrypoint>),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Command entrypoint for multiple commands
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct CommandEntrypoint {
|
||||||
|
/// Atom name
|
||||||
|
pub atom: String,
|
||||||
|
/// Command name
|
||||||
|
pub command: String,
|
||||||
|
/// Type of the object format
|
||||||
|
pub object_type: ObjectFormat,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
/// The options for the `wasmer create-exe` subcommand
|
/// The options for the `wasmer create-exe` subcommand
|
||||||
pub struct CreateExe {
|
pub struct CreateExe {
|
||||||
@@ -180,16 +203,12 @@ impl CreateExe {
|
|||||||
|
|
||||||
#[cfg(feature = "webc_runner")]
|
#[cfg(feature = "webc_runner")]
|
||||||
{
|
{
|
||||||
// let working_dir = tempdir::TempDir::new("testpirita")?;
|
|
||||||
// let working_dir = working_dir.path().to_path_buf();
|
|
||||||
let working_dir = Path::new("./tmptestpirita").to_path_buf();
|
|
||||||
if let Ok(pirita) = WebCMmap::parse(wasm_module_path.clone(), &ParseOptions::default())
|
if let Ok(pirita) = WebCMmap::parse(wasm_module_path.clone(), &ParseOptions::default())
|
||||||
{
|
{
|
||||||
return self.create_exe_pirita(
|
return self.create_exe_pirita(
|
||||||
&pirita,
|
&pirita,
|
||||||
target,
|
target,
|
||||||
cross_compilation,
|
cross_compilation,
|
||||||
&working_dir,
|
|
||||||
output_path,
|
output_path,
|
||||||
self.debug_dir.clone(),
|
self.debug_dir.clone(),
|
||||||
object_format,
|
object_format,
|
||||||
@@ -562,13 +581,30 @@ impl CreateExe {
|
|||||||
&self,
|
&self,
|
||||||
output_path: PathBuf,
|
output_path: PathBuf,
|
||||||
debug_dir: Option<PathBuf>,
|
debug_dir: Option<PathBuf>,
|
||||||
object_paths: &[PathBuf],
|
working_dir: &PathBuf,
|
||||||
header_code_paths: &[PathBuf],
|
entrypoint: &Entrypoint,
|
||||||
setup: &CrossCompileSetup,
|
setup: &CrossCompileSetup,
|
||||||
pirita_atoms: &[String],
|
pirita_atoms: &[String],
|
||||||
pirita_main_atom: Option<&str>,
|
pirita_main_atom: Option<&Entrypoint>,
|
||||||
pirita_volume_path: Option<PathBuf>,
|
pirita_volume_path: Option<PathBuf>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
let entrypoint_str = match entrypoint {
|
||||||
|
Entrypoint::Single(s) => s,
|
||||||
|
Entrypoint::Multi(m) => {
|
||||||
|
return Err(anyhow::anyhow!(
|
||||||
|
"CreateExe::compile_zig: multi-command-exe not yet implemented"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let object_file_path = working_dir
|
||||||
|
.join("atoms")
|
||||||
|
.join(&format!("{entrypoint_str}.o"));
|
||||||
|
let static_defs_file_path = working_dir
|
||||||
|
.join("atoms")
|
||||||
|
.join(&entrypoint_str)
|
||||||
|
.join("static_defs.h");
|
||||||
|
|
||||||
let tempdir = tempdir::TempDir::new("wasmer-static-compile-zig")?;
|
let tempdir = tempdir::TempDir::new("wasmer-static-compile-zig")?;
|
||||||
let tempdir_path = match debug_dir.as_ref() {
|
let tempdir_path = match debug_dir.as_ref() {
|
||||||
Some(s) => s.clone(),
|
Some(s) => s.clone(),
|
||||||
@@ -600,7 +636,7 @@ impl CreateExe {
|
|||||||
println!("Using zig target triple: {}", &zig_triple);
|
println!("Using zig target triple: {}", &zig_triple);
|
||||||
|
|
||||||
if let Some(entrypoint) = pirita_main_atom.as_ref() {
|
if let Some(entrypoint) = pirita_main_atom.as_ref() {
|
||||||
let c_code = Self::generate_pirita_wasmer_main_c_static(pirita_atoms, entrypoint);
|
let c_code = Self::generate_pirita_wasmer_main_c_static(pirita_atoms, entrypoint)?;
|
||||||
std::fs::write(&c_src_path, c_code)?;
|
std::fs::write(&c_src_path, c_code)?;
|
||||||
} else {
|
} else {
|
||||||
std::fs::write(&c_src_path, WASMER_STATIC_MAIN_C_SOURCE)?;
|
std::fs::write(&c_src_path, WASMER_STATIC_MAIN_C_SOURCE)?;
|
||||||
@@ -797,14 +833,22 @@ impl CreateExe {
|
|||||||
if let Some(atom_to_run) = atom_to_run.as_ref() {
|
if let Some(atom_to_run) = atom_to_run.as_ref() {
|
||||||
std::fs::write(output_path.join("entrypoint"), atom_to_run)?;
|
std::fs::write(output_path.join("entrypoint"), atom_to_run)?;
|
||||||
} else if file.manifest.commands.len() > 1 {
|
} else if file.manifest.commands.len() > 1 {
|
||||||
let entrypoint_json = file.manifest.commands.iter().filter_map(|(name, _)| {
|
let entrypoint_json = file
|
||||||
|
.manifest
|
||||||
|
.commands
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(name, _)| {
|
||||||
Some(serde_json::json!({
|
Some(serde_json::json!({
|
||||||
"command": name,
|
"command": name,
|
||||||
"atom": file.get_atom_name_for_command("wasi", name).ok()?,
|
"atom": file.get_atom_name_for_command("wasi", name).ok()?,
|
||||||
"object_type": object_format,
|
"object_type": object_format,
|
||||||
}))
|
}))
|
||||||
}).collect::<Vec<_>>();
|
})
|
||||||
std::fs::write(output_path.join("entrypoint.json"), serde_json::to_string_pretty(&entrypoint_json)?)?;
|
.collect::<Vec<_>>();
|
||||||
|
std::fs::write(
|
||||||
|
output_path.join("entrypoint.json"),
|
||||||
|
serde_json::to_string_pretty(&entrypoint_json)?,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (atom_name, atom_bytes) in file.get_all_atoms() {
|
for (atom_name, atom_bytes) in file.get_all_atoms() {
|
||||||
@@ -892,8 +936,18 @@ impl CreateExe {
|
|||||||
let tempdir = tempdir::TempDir::new("link-exe-from-dir")?;
|
let tempdir = tempdir::TempDir::new("link-exe-from-dir")?;
|
||||||
let tempdir_path = tempdir.path();
|
let tempdir_path = tempdir.path();
|
||||||
|
|
||||||
let entrypoint = std::fs::read_to_string(working_dir.join("entrypoint"))
|
let entrypoint = if let Ok(s) = std::fs::read_to_string(working_dir.join("entrypoint")) {
|
||||||
.map_err(|_| anyhow::anyhow!("file has no entrypoint to run"))?;
|
Entrypoint::Single(s)
|
||||||
|
} else if let Ok(s) = std::fs::read_to_string(working_dir.join("entrypoint.json")) {
|
||||||
|
let json = serde_json::from_str(&s)
|
||||||
|
.map_err(|e| anyhow::anyhow!("could not deserialize entrypoint.json: {e}"))?;
|
||||||
|
Entrypoint::Multi(json)
|
||||||
|
} else {
|
||||||
|
return Err(anyhow::anyhow!(
|
||||||
|
"no /entrypoint or /entrypoint.json found in {}",
|
||||||
|
working_dir.display()
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
if !working_dir.join("atoms").exists() {
|
if !working_dir.join("atoms").exists() {
|
||||||
return Err(anyhow::anyhow!("file has no atoms to compile"));
|
return Err(anyhow::anyhow!("file has no atoms to compile"));
|
||||||
@@ -975,19 +1029,12 @@ impl CreateExe {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ObjectFormat::Symbols => {
|
ObjectFormat::Symbols => {
|
||||||
let object_file_path = working_dir.join("atoms").join(&format!("{entrypoint}.o"));
|
|
||||||
let static_defs_file_path = working_dir
|
|
||||||
.join("atoms")
|
|
||||||
.join(&entrypoint)
|
|
||||||
.join("static_defs.h");
|
|
||||||
let volumes_obj_path = Self::write_volume_obj(volume_bytes, target, tempdir_path)?;
|
let volumes_obj_path = Self::write_volume_obj(volume_bytes, target, tempdir_path)?;
|
||||||
|
|
||||||
if let Some(setup) = cross_compilation.as_ref() {
|
if let Some(setup) = cross_compilation.as_ref() {
|
||||||
self.compile_zig(
|
self.compile_zig(
|
||||||
output_path,
|
output_path,
|
||||||
self.debug_dir.clone(),
|
self.debug_dir.clone(),
|
||||||
&[object_file_path],
|
&entrypoint,
|
||||||
&[static_defs_file_path],
|
|
||||||
setup,
|
setup,
|
||||||
&atom_names,
|
&atom_names,
|
||||||
Some(&entrypoint),
|
Some(&entrypoint),
|
||||||
@@ -996,8 +1043,6 @@ impl CreateExe {
|
|||||||
} else {
|
} else {
|
||||||
self.link(
|
self.link(
|
||||||
output_path,
|
output_path,
|
||||||
object_file_path,
|
|
||||||
static_defs_file_path,
|
|
||||||
&atom_names,
|
&atom_names,
|
||||||
Some(&entrypoint),
|
Some(&entrypoint),
|
||||||
Some(volumes_obj_path),
|
Some(volumes_obj_path),
|
||||||
@@ -1023,7 +1068,19 @@ impl CreateExe {
|
|||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_pirita_wasmer_main_c_static(atom_names: &[String], atom_to_run: &str) -> String {
|
fn generate_pirita_wasmer_main_c_static(
|
||||||
|
atom_names: &[String],
|
||||||
|
entrypoint: &Entrypoint,
|
||||||
|
) -> String {
|
||||||
|
let atom_to_run = match entrypoint {
|
||||||
|
Entrypoint::Single(s) => s,
|
||||||
|
Entrypoint::Multi(m) => {
|
||||||
|
return Err(anyhow::anyhow!("generate_pirita_wasmer_main_c_static: not yet able to generate multi-command exe"));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut c_code_to_instantiate = String::new();
|
||||||
|
let mut deallocate_module = String::new();
|
||||||
let mut c_code_to_instantiate = String::new();
|
let mut c_code_to_instantiate = String::new();
|
||||||
let mut deallocate_module = String::new();
|
let mut deallocate_module = String::new();
|
||||||
|
|
||||||
@@ -1063,7 +1120,19 @@ impl CreateExe {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "webc_runner")]
|
#[cfg(feature = "webc_runner")]
|
||||||
fn generate_pirita_wasmer_main_c(atom_names: &[String], atom_to_run: &str) -> String {
|
fn generate_pirita_wasmer_main_c(
|
||||||
|
atom_names: &[String],
|
||||||
|
entrypoint: &Entrypoint,
|
||||||
|
) -> Result<String, anyhow::Error> {
|
||||||
|
let atom_to_run = match entrypoint {
|
||||||
|
Entrypoint::Single(s) => s,
|
||||||
|
Entrypoint::Multi(m) => {
|
||||||
|
return Err(anyhow::anyhow!(
|
||||||
|
"generate_pirita_wasmer_main_c: not yet able to generate multi-command exe"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let mut c_code_to_add = String::new();
|
let mut c_code_to_add = String::new();
|
||||||
let mut c_code_to_instantiate = String::new();
|
let mut c_code_to_instantiate = String::new();
|
||||||
let mut deallocate_module = String::new();
|
let mut deallocate_module = String::new();
|
||||||
@@ -1111,15 +1180,20 @@ impl CreateExe {
|
|||||||
file: &WebCMmap,
|
file: &WebCMmap,
|
||||||
target: Target,
|
target: Target,
|
||||||
cross_compilation: Option<CrossCompileSetup>,
|
cross_compilation: Option<CrossCompileSetup>,
|
||||||
working_dir: &Path,
|
|
||||||
output_path: PathBuf,
|
output_path: PathBuf,
|
||||||
debug_dir: Option<PathBuf>,
|
debug_dir: Option<PathBuf>,
|
||||||
object_format: ObjectFormat,
|
object_format: ObjectFormat,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
|
let working_dir = match debug_dir.as_ref() {
|
||||||
|
None => temp_dir.path().to_path_buf(),
|
||||||
|
Some(s) => s.clone(),
|
||||||
|
};
|
||||||
|
let _ = std::fs::create_dir_all(&working_dir);
|
||||||
|
let (store, _) = self.compiler.get_store_for_target(target.clone())?;
|
||||||
let _ = std::fs::create_dir_all(&working_dir);
|
let _ = std::fs::create_dir_all(&working_dir);
|
||||||
let (store, _) = self.compiler.get_store_for_target(target.clone())?;
|
let (store, _) = self.compiler.get_store_for_target(target.clone())?;
|
||||||
|
|
||||||
Self::create_objs_pirita(&store, file, &target, working_dir, object_format)?;
|
let volumes_obj = file.get_volumes_as_fileblock();
|
||||||
|
|
||||||
let volumes_obj = file.get_volumes_as_fileblock();
|
let volumes_obj = file.get_volumes_as_fileblock();
|
||||||
self.link_exe_from_dir(
|
self.link_exe_from_dir(
|
||||||
@@ -1127,7 +1201,7 @@ impl CreateExe {
|
|||||||
&store,
|
&store,
|
||||||
&target,
|
&target,
|
||||||
cross_compilation,
|
cross_compilation,
|
||||||
working_dir,
|
debug_dir,
|
||||||
output_path,
|
output_path,
|
||||||
debug_dir,
|
debug_dir,
|
||||||
object_format,
|
object_format,
|
||||||
@@ -1140,10 +1214,8 @@ impl CreateExe {
|
|||||||
fn link(
|
fn link(
|
||||||
&self,
|
&self,
|
||||||
output_path: PathBuf,
|
output_path: PathBuf,
|
||||||
object_path: PathBuf,
|
|
||||||
mut header_code_path: PathBuf,
|
|
||||||
pirita_atoms: &[String],
|
pirita_atoms: &[String],
|
||||||
pirita_main_atom: Option<&str>,
|
pirita_entrypoint: Option<&Entrypoint>,
|
||||||
pirita_volume_path: Option<PathBuf>,
|
pirita_volume_path: Option<PathBuf>,
|
||||||
) -> anyhow::Result<()> {
|
) -> anyhow::Result<()> {
|
||||||
let tempdir = tempdir::TempDir::new("wasmer-static-compile")?;
|
let tempdir = tempdir::TempDir::new("wasmer-static-compile")?;
|
||||||
|
|||||||
Reference in New Issue
Block a user