Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/hyperlight_wasm_aot/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Application to precompile WebAssembly binaries to for hyperlight-wasm.

[dependencies]
wasmtime = { version = "36.0.5", default-features = false, features = ["cranelift", "runtime", "component-model" ] }
clap = "4.5"
clap = { version = "4.5", features = ["derive"] }
cargo_metadata = "0.23"
cargo-util-schemas = "0.10.1"

Expand Down
152 changes: 72 additions & 80 deletions src/hyperlight_wasm_aot/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,95 +18,90 @@ use std::path::Path;

use cargo_metadata::{MetadataCommand, Package};
use cargo_util_schemas::manifest::PackageName;
use clap::{Arg, Command};
use clap::{Parser, Subcommand};
use wasmtime::{Config, Engine, Module, OptLevel, Precompiled};

#[derive(Parser)]
#[command(name = "hyperlight-wasm-aot")]
#[command(version = env!("CARGO_PKG_VERSION"))]
#[command(about = "Precompile WebAssembly modules and components for hyperlight-wasm")]
struct Cli {
#[command(subcommand)]
command: Commands,
}

#[derive(Subcommand)]
enum Commands {
/// Precompile a WebAssembly module or component for Wasmtime
Compile {
/// The input WebAssembly file
input: String,

/// The output file path (defaults to input with .aot extension)
output: Option<String>,

/// Compile a component rather than a module
#[arg(long)]
component: bool,

/// Precompile with debug and disable optimizations
#[arg(long)]
debug: bool,

/// Disable address map and native unwind info for smaller binaries
#[arg(long)]
minimal: bool,
},

/// Check which Wasmtime version was used to precompile a module
CheckWasmtimeVersion {
/// The precompiled file to check
file: String,

/// Specifies if the module has been compiled with debug support
#[arg(long)]
debug: bool,
},
}

fn main() {
let hyperlight_wasm_aot_version = env!("CARGO_PKG_VERSION");
let matches = Command::new("hyperlight-wasm-aot")
.version(hyperlight_wasm_aot_version)
.about("AOT compilation for hyperlight-wasm")
.subcommand(
Command::new("compile")
.about("Compile a wasm file to an AOT file")
.arg(
Arg::new("input")
.help("The input wasm file")
.required(true)
.index(1),
)
.arg(
Arg::new("output")
.help("The output AOT file")
.required(false)
.index(2),
)
.arg(
Arg::new("component")
.help("Compile a component rather than a module")
.required(false)
.long("component")
.action(clap::ArgAction::SetTrue),
)
.arg(
Arg::new("debug")
.help("Precompile with debug and disable optimizations")
.required(false)
.long("debug")
.action(clap::ArgAction::SetTrue),
),
)
.subcommand(
Command::new("check-wasmtime-version")
.about("Check the Wasmtime version use to compile a AOT file")
.arg(
Arg::new("file")
.help("The aot compiled file to check")
.required(true)
.index(1),
)
.arg(
Arg::new("debug")
.help("Specifies if the module has been compiled with debug support")
.required(false)
.long("debug")
.action(clap::ArgAction::SetTrue),
),
)
.get_matches();

match matches.subcommand_name() {
Some("compile") => {
let args = matches.subcommand_matches("compile").unwrap();
let infile = args.get_one::<String>("input").unwrap();
let outfile = match args.get_one::<String>("output") {
Some(s) => s.clone(),
let cli = Cli::parse();

match cli.command {
Commands::Compile {
input,
output,
component,
debug,
minimal,
} => {
let outfile = match output {
Some(s) => s,
None => {
let mut path = Path::new(infile).to_path_buf();
let mut path = Path::new(&input).to_path_buf();
path.set_extension("aot");
path.to_str().unwrap().to_string().clone()
path.to_str().unwrap().to_string()
}
};
let debug = args.get_flag("debug");
if debug {
println!(
"Aot Compiling {} to {} with debug info and optimizations off",
infile, outfile
input, outfile
);
} else {
println!("Aot Compiling {} to {}", infile, outfile);
println!("Aot Compiling {} to {}", input, outfile);
}
let config = get_config(debug);
let config = get_config(debug, minimal);
let engine = Engine::new(&config).unwrap();
let bytes = std::fs::read(infile).unwrap();
let serialized = if args.get_flag("component") {
let bytes = std::fs::read(&input).unwrap();
let serialized = if component {
engine.precompile_component(&bytes).unwrap()
} else {
engine.precompile_module(&bytes).unwrap()
};
std::fs::write(outfile, serialized).unwrap();
}
Some("check-wasmtime-version") => {
Commands::CheckWasmtimeVersion { file, debug } => {
// get the wasmtime version used by hyperlight-wasm-aot
let metadata = MetadataCommand::new().exec().unwrap();
let package_name = PackageName::new("wasmtime".to_string()).unwrap();
Expand All @@ -116,11 +111,6 @@ fn main() {
Some(pkg) => pkg.version.clone(),
None => panic!("wasmtime dependency not found"),
};
let args = matches
.subcommand_matches("check-wasmtime-version")
.unwrap();
let debug = args.get_flag("debug");
let file = args.get_one::<String>("file").unwrap();
if debug {
println!(
"Checking Wasmtime version used to compile debug info enabled file: {}",
Expand All @@ -130,8 +120,8 @@ fn main() {
println!("Checking Wasmtime version used to compile file: {}", file);
}
// load the file into wasmtime, check that it is aot compiled and extract the version of wasmtime used to compile it from its metadata
let bytes = std::fs::read(file).unwrap();
let config = get_config(debug);
let bytes = std::fs::read(&file).unwrap();
let config = get_config(debug, false);
let engine = Engine::new(&config).unwrap();
match Engine::detect_precompiled(&bytes) {
Some(pre_compiled) => {
Expand Down Expand Up @@ -174,14 +164,11 @@ fn main() {
}
}
}
_ => {
println!("No subcommand specified");
}
}
}

/// Returns a new `Config` for the Wasmtime engine with additional settings for AOT compilation.
fn get_config(debug: bool) -> Config {
fn get_config(debug: bool, minimal: bool) -> Config {
let mut config = Config::new();
config.target("x86_64-unknown-none").unwrap();

Expand All @@ -191,5 +178,10 @@ fn get_config(debug: bool) -> Config {
config.cranelift_opt_level(OptLevel::None);
}

if minimal {
config.generate_address_map(false);
config.native_unwind_info(false);
}

config
}
Loading