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")]
|
||||
use crate::commands::Wast;
|
||||
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 clap::{CommandFactory, ErrorKind, Parser};
|
||||
@@ -128,6 +129,9 @@ enum WasmerCLIOptions {
|
||||
#[structopt(name = "create-obj", verbatim_doc_comment)]
|
||||
CreateObj(CreateObj),
|
||||
|
||||
/// Generate the C static_defs.h header file for the input .wasm module
|
||||
GenCHeader(GenCHeader),
|
||||
|
||||
/// Get various configuration information needed
|
||||
/// to compile programs which use Wasmer
|
||||
Config(Config),
|
||||
@@ -177,6 +181,7 @@ impl WasmerCLIOptions {
|
||||
Self::List(list) => list.execute(),
|
||||
Self::Login(login) => login.execute(),
|
||||
Self::Publish(publish) => publish.execute(),
|
||||
Self::GenCHeader(gen_heder) => gen_heder.execute(),
|
||||
#[cfg(feature = "wast")]
|
||||
Self::Wast(wast) => wast.execute(),
|
||||
#[cfg(target_os = "linux")]
|
||||
@@ -235,8 +240,8 @@ fn wasmer_main_inner() -> Result<(), anyhow::Error> {
|
||||
} else {
|
||||
match command.unwrap_or(&"".to_string()).as_ref() {
|
||||
"add" | "cache" | "compile" | "config" | "create-obj" | "create-exe" | "help"
|
||||
| "inspect" | "init" | "run" | "self-update" | "validate" | "wast" | "binfmt"
|
||||
| "list" | "login" | "publish" => WasmerCLIOptions::parse(),
|
||||
| "gen-c-header" | "inspect" | "init" | "run" | "self-update" | "validate" | "wast"
|
||||
| "binfmt" | "list" | "login" | "publish" => WasmerCLIOptions::parse(),
|
||||
_ => {
|
||||
WasmerCLIOptions::try_parse_from(args.iter()).unwrap_or_else(|e| {
|
||||
match e.kind() {
|
||||
|
||||
@@ -10,6 +10,7 @@ mod config;
|
||||
mod create_exe;
|
||||
#[cfg(feature = "static-artifact-create")]
|
||||
mod create_obj;
|
||||
mod gen_c_header;
|
||||
mod init;
|
||||
mod inspect;
|
||||
mod list;
|
||||
@@ -34,8 +35,8 @@ use serde::{Deserialize, Serialize};
|
||||
#[cfg(feature = "wast")]
|
||||
pub use wast::*;
|
||||
pub use {
|
||||
add::*, cache::*, config::*, init::*, inspect::*, list::*, login::*, publish::*, run::*,
|
||||
self_update::*, validate::*, whoami::*,
|
||||
add::*, cache::*, config::*, gen_c_header::*, init::*, inspect::*, list::*, login::*,
|
||||
publish::*, run::*, self_update::*, validate::*, whoami::*,
|
||||
};
|
||||
|
||||
/// 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
|
||||
#[derive(Debug, Default, PartialEq)]
|
||||
struct PrefixMapCompilation {
|
||||
pub(crate) struct PrefixMapCompilation {
|
||||
/// Sha256 hashes for the input files
|
||||
input_hashes: BTreeMap<String, String>,
|
||||
/// 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};
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(bytes);
|
||||
@@ -992,7 +992,7 @@ fn get_module_infos(
|
||||
}
|
||||
|
||||
/// 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,
|
||||
entrypoint: &mut Entrypoint,
|
||||
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)]
|
||||
#[cfg(feature = "static-artifact-create")]
|
||||
/// Generate a compilation
|
||||
fn generate_metadata<'data>(
|
||||
pub fn generate_metadata<'data>(
|
||||
data: &'data [u8],
|
||||
compiler: &dyn Compiler,
|
||||
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