mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-07 13:18:20 +00:00
Add gen-c-header option
This commit is contained in:
@@ -11,7 +11,8 @@ use crate::commands::CreateObj;
|
|||||||
#[cfg(feature = "wast")]
|
#[cfg(feature = "wast")]
|
||||||
use crate::commands::Wast;
|
use crate::commands::Wast;
|
||||||
use crate::commands::{
|
use crate::commands::{
|
||||||
Add, Cache, Config, Init, Inspect, List, Login, Publish, Run, SelfUpdate, Validate, Whoami,
|
Add, Cache, Config, GenCHeader, Init, Inspect, List, Login, Publish, Run, SelfUpdate, Validate,
|
||||||
|
Whoami,
|
||||||
};
|
};
|
||||||
use crate::error::PrettyError;
|
use crate::error::PrettyError;
|
||||||
use clap::{CommandFactory, ErrorKind, Parser};
|
use clap::{CommandFactory, ErrorKind, Parser};
|
||||||
@@ -128,6 +129,9 @@ enum WasmerCLIOptions {
|
|||||||
#[structopt(name = "create-obj", verbatim_doc_comment)]
|
#[structopt(name = "create-obj", verbatim_doc_comment)]
|
||||||
CreateObj(CreateObj),
|
CreateObj(CreateObj),
|
||||||
|
|
||||||
|
/// Generate the C static_defs.h header file for the input .wasm module
|
||||||
|
GenCHeader(GenCHeader),
|
||||||
|
|
||||||
/// Get various configuration information needed
|
/// Get various configuration information needed
|
||||||
/// to compile programs which use Wasmer
|
/// to compile programs which use Wasmer
|
||||||
Config(Config),
|
Config(Config),
|
||||||
@@ -177,6 +181,7 @@ impl WasmerCLIOptions {
|
|||||||
Self::List(list) => list.execute(),
|
Self::List(list) => list.execute(),
|
||||||
Self::Login(login) => login.execute(),
|
Self::Login(login) => login.execute(),
|
||||||
Self::Publish(publish) => publish.execute(),
|
Self::Publish(publish) => publish.execute(),
|
||||||
|
Self::GenCHeader(gen_heder) => gen_heder.execute(),
|
||||||
#[cfg(feature = "wast")]
|
#[cfg(feature = "wast")]
|
||||||
Self::Wast(wast) => wast.execute(),
|
Self::Wast(wast) => wast.execute(),
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
@@ -235,8 +240,8 @@ fn wasmer_main_inner() -> Result<(), anyhow::Error> {
|
|||||||
} else {
|
} else {
|
||||||
match command.unwrap_or(&"".to_string()).as_ref() {
|
match command.unwrap_or(&"".to_string()).as_ref() {
|
||||||
"add" | "cache" | "compile" | "config" | "create-obj" | "create-exe" | "help"
|
"add" | "cache" | "compile" | "config" | "create-obj" | "create-exe" | "help"
|
||||||
| "inspect" | "init" | "run" | "self-update" | "validate" | "wast" | "binfmt"
|
| "gen-c-header" | "inspect" | "init" | "run" | "self-update" | "validate" | "wast"
|
||||||
| "list" | "login" | "publish" => WasmerCLIOptions::parse(),
|
| "binfmt" | "list" | "login" | "publish" => WasmerCLIOptions::parse(),
|
||||||
_ => {
|
_ => {
|
||||||
WasmerCLIOptions::try_parse_from(args.iter()).unwrap_or_else(|e| {
|
WasmerCLIOptions::try_parse_from(args.iter()).unwrap_or_else(|e| {
|
||||||
match e.kind() {
|
match e.kind() {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ mod config;
|
|||||||
mod create_exe;
|
mod create_exe;
|
||||||
#[cfg(feature = "static-artifact-create")]
|
#[cfg(feature = "static-artifact-create")]
|
||||||
mod create_obj;
|
mod create_obj;
|
||||||
|
mod gen_c_header;
|
||||||
mod init;
|
mod init;
|
||||||
mod inspect;
|
mod inspect;
|
||||||
mod list;
|
mod list;
|
||||||
@@ -34,8 +35,8 @@ use serde::{Deserialize, Serialize};
|
|||||||
#[cfg(feature = "wast")]
|
#[cfg(feature = "wast")]
|
||||||
pub use wast::*;
|
pub use wast::*;
|
||||||
pub use {
|
pub use {
|
||||||
add::*, cache::*, config::*, init::*, inspect::*, list::*, login::*, publish::*, run::*,
|
add::*, cache::*, config::*, gen_c_header::*, init::*, inspect::*, list::*, login::*,
|
||||||
self_update::*, validate::*, whoami::*,
|
publish::*, run::*, self_update::*, validate::*, whoami::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The kind of object format to emit.
|
/// The kind of object format to emit.
|
||||||
|
|||||||
@@ -504,7 +504,7 @@ pub(super) fn compile_pirita_into_directory(
|
|||||||
|
|
||||||
/// Prefix map used during compilation of object files
|
/// Prefix map used during compilation of object files
|
||||||
#[derive(Debug, Default, PartialEq)]
|
#[derive(Debug, Default, PartialEq)]
|
||||||
struct PrefixMapCompilation {
|
pub(crate) struct PrefixMapCompilation {
|
||||||
/// Sha256 hashes for the input files
|
/// Sha256 hashes for the input files
|
||||||
input_hashes: BTreeMap<String, String>,
|
input_hashes: BTreeMap<String, String>,
|
||||||
/// Manual prefixes for input files (file:prefix)
|
/// Manual prefixes for input files (file:prefix)
|
||||||
@@ -638,7 +638,7 @@ impl PrefixMapCompilation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash_for_bytes(bytes: &[u8]) -> String {
|
pub(crate) fn hash_for_bytes(bytes: &[u8]) -> String {
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
hasher.update(bytes);
|
hasher.update(bytes);
|
||||||
@@ -992,7 +992,7 @@ fn get_module_infos(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Create the static_defs.h header files in the /include directory
|
/// Create the static_defs.h header files in the /include directory
|
||||||
fn create_header_files_in_dir(
|
pub(crate) fn create_header_files_in_dir(
|
||||||
directory: &Path,
|
directory: &Path,
|
||||||
entrypoint: &mut Entrypoint,
|
entrypoint: &mut Entrypoint,
|
||||||
atoms: &[(String, Vec<u8>)],
|
atoms: &[(String, Vec<u8>)],
|
||||||
|
|||||||
69
lib/cli/src/commands/gen_c_header.rs
Normal file
69
lib/cli/src/commands/gen_c_header.rs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
use crate::store::CompilerOptions;
|
||||||
|
use anyhow::Context;
|
||||||
|
use clap::Parser;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use wasmer::Target;
|
||||||
|
use wasmer_compiler::Artifact;
|
||||||
|
use wasmer_types::compilation::symbols::ModuleMetadataSymbolRegistry;
|
||||||
|
|
||||||
|
use super::normalize_path;
|
||||||
|
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
/// The options for the `wasmer gen-c-header` subcommand
|
||||||
|
pub struct GenCHeader {
|
||||||
|
/// Input file
|
||||||
|
#[clap(name = "FILE", parse(from_os_str))]
|
||||||
|
path: PathBuf,
|
||||||
|
|
||||||
|
/// Prefix hash (default: SHA256 of input .wasm file)
|
||||||
|
#[clap(long)]
|
||||||
|
prefix: Option<String>,
|
||||||
|
|
||||||
|
/// Output file
|
||||||
|
#[clap(name = "OUTPUT PATH", short = 'o', parse(from_os_str))]
|
||||||
|
output: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GenCHeader {
|
||||||
|
/// Runs logic for the `gen-c-header` subcommand
|
||||||
|
pub fn execute(&self) -> Result<(), anyhow::Error> {
|
||||||
|
let path = crate::commands::normalize_path(&format!("{}", self.path.display()));
|
||||||
|
let file = std::fs::read(&path)
|
||||||
|
.map_err(|e| anyhow::anyhow!("{e}"))
|
||||||
|
.with_context(|| anyhow::anyhow!("{path}"))?;
|
||||||
|
let prefix = match self.prefix.as_deref() {
|
||||||
|
Some(s) => s.to_string(),
|
||||||
|
None => crate::commands::PrefixMapCompilation::hash_for_bytes(&file),
|
||||||
|
};
|
||||||
|
let (store, _) = CompilerOptions::default().get_store_for_target(Target::default())?;
|
||||||
|
let module_name = format!("WASMER_{}_METADATA", prefix.to_uppercase());
|
||||||
|
let engine = store.engine();
|
||||||
|
let engine_inner = engine.inner();
|
||||||
|
let compiler = engine_inner.compiler()?;
|
||||||
|
let features = engine_inner.features();
|
||||||
|
let tunables = store.tunables();
|
||||||
|
let (compile_info, _, _, _) =
|
||||||
|
Artifact::generate_metadata(&file, compiler, tunables, features)?;
|
||||||
|
let module_info = compile_info.module;
|
||||||
|
|
||||||
|
let metadata_length = 0;
|
||||||
|
|
||||||
|
let header_file_src = crate::c_gen::staticlib_header::generate_header_file(
|
||||||
|
&prefix,
|
||||||
|
&module_name,
|
||||||
|
&module_info,
|
||||||
|
&ModuleMetadataSymbolRegistry {
|
||||||
|
prefix: prefix.clone(),
|
||||||
|
},
|
||||||
|
metadata_length as usize,
|
||||||
|
);
|
||||||
|
|
||||||
|
let output = normalize_path(&self.output.display().to_string());
|
||||||
|
|
||||||
|
std::fs::write(&output, &header_file_src)
|
||||||
|
.map_err(|e| anyhow::anyhow!("{e}"))
|
||||||
|
.with_context(|| anyhow::anyhow!("{output}"))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -412,7 +412,7 @@ impl Artifact {
|
|||||||
#[allow(clippy::type_complexity)]
|
#[allow(clippy::type_complexity)]
|
||||||
#[cfg(feature = "static-artifact-create")]
|
#[cfg(feature = "static-artifact-create")]
|
||||||
/// Generate a compilation
|
/// Generate a compilation
|
||||||
fn generate_metadata<'data>(
|
pub fn generate_metadata<'data>(
|
||||||
data: &'data [u8],
|
data: &'data [u8],
|
||||||
compiler: &dyn Compiler,
|
compiler: &dyn Compiler,
|
||||||
tunables: &dyn Tunables,
|
tunables: &dyn Tunables,
|
||||||
|
|||||||
54
tests/integration/cli/tests/gen_c_header.rs
Normal file
54
tests/integration/cli/tests/gen_c_header.rs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
use std::path::PathBuf;
|
||||||
|
use std::process::Command;
|
||||||
|
use wasmer_integration_tests_cli::get_wasmer_path;
|
||||||
|
use wasmer_integration_tests_cli::C_ASSET_PATH;
|
||||||
|
|
||||||
|
fn create_exe_wabt_path() -> String {
|
||||||
|
format!("{}/{}", C_ASSET_PATH, "wabt-1.0.37.wasmer")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_exe_python_wasmer() -> String {
|
||||||
|
format!("{}/{}", C_ASSET_PATH, "python-0.1.0.wasmer")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_exe_test_wasm_path() -> String {
|
||||||
|
format!("{}/{}", C_ASSET_PATH, "qjs.wasm")
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn gen_c_header_works() -> anyhow::Result<()> {
|
||||||
|
let temp_dir = tempfile::tempdir()?;
|
||||||
|
let operating_dir: PathBuf = temp_dir.path().to_owned();
|
||||||
|
|
||||||
|
let wasm_path = operating_dir.join(create_exe_test_wasm_path());
|
||||||
|
let out_path = temp_dir.path().join("header.h");
|
||||||
|
|
||||||
|
let _ = Command::new(get_wasmer_path())
|
||||||
|
.arg("gen-c-header")
|
||||||
|
.arg(&wasm_path)
|
||||||
|
.arg("-o")
|
||||||
|
.arg(&out_path)
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let file = std::fs::read_to_string(&out_path).expect("no header.h file");
|
||||||
|
assert!(file.contains("wasmer_function_6f62a6bc5c8f8e3e12a54e2ecbc5674ccfe1c75f91d8e4dd6ebb3fec422a4d6c_0"), "no wasmer_function_6f62a6bc5c8f8e3e12a54e2ecbc5674ccfe1c75f91d8e4dd6ebb3fec422a4d6c_0 in file");
|
||||||
|
|
||||||
|
let cmd = Command::new(get_wasmer_path())
|
||||||
|
.arg("gen-c-header")
|
||||||
|
.arg(&wasm_path)
|
||||||
|
.arg("-o")
|
||||||
|
.arg(&out_path)
|
||||||
|
.arg("--prefix")
|
||||||
|
.arg("abc123")
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let file = std::fs::read_to_string(&out_path).expect("no header.h file");
|
||||||
|
assert!(
|
||||||
|
file.contains("wasmer_function_abc123_0"),
|
||||||
|
"no wasmer_function_abc123_0 in file"
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user