From 020de16058bc1ddb14f0b1c0fc3cbe851a92b318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Doru=20Bl=C3=A2nzeanu?= Date: Tue, 3 Feb 2026 17:14:22 +0200 Subject: [PATCH 1/2] Add option to build and run pulley pre-compiled modules or components MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Doru Blânzeanu --- src/hyperlight_wasm/Cargo.toml | 1 + src/hyperlight_wasm/build.rs | 4 +++ src/hyperlight_wasm_aot/Cargo.toml | 2 +- src/hyperlight_wasm_aot/src/main.rs | 40 +++++++++++++++++++++++------ src/wasm_runtime/Cargo.toml | 1 + src/wasm_runtime/build.rs | 1 + src/wasm_runtime/src/component.rs | 10 ++++++++ src/wasm_runtime/src/module.rs | 7 +++++ 8 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/hyperlight_wasm/Cargo.toml b/src/hyperlight_wasm/Cargo.toml index 0dc8365..0be8c15 100644 --- a/src/hyperlight_wasm/Cargo.toml +++ b/src/hyperlight_wasm/Cargo.toml @@ -114,6 +114,7 @@ crashdump = ["hyperlight-host/crashdump"] gdb = ["hyperlight-host/gdb"] kvm = ["hyperlight-host/kvm"] mshv3 = ["hyperlight-host/mshv3"] +pulley = [] trace_guest = ["hyperlight-host/trace_guest"] [[bench]] diff --git a/src/hyperlight_wasm/build.rs b/src/hyperlight_wasm/build.rs index 281cb8b..ed74b62 100644 --- a/src/hyperlight_wasm/build.rs +++ b/src/hyperlight_wasm/build.rs @@ -128,6 +128,10 @@ fn build_wasm_runtime() -> PathBuf { if std::env::var("CARGO_FEATURE_GDB").is_ok() { cmd = cmd.arg("--features").arg("gdb"); } + // Add --features pulley if the pulley feature is enabled + if std::env::var("CARGO_FEATURE_PULLEY").is_ok() { + cmd = cmd.arg("--features").arg("pulley"); + } // Enable the "trace_guest" feature if the corresponding Cargo feature is enabled if std::env::var("CARGO_FEATURE_TRACE_GUEST").is_ok() { cmd = cmd.arg("--features").arg("trace_guest"); diff --git a/src/hyperlight_wasm_aot/Cargo.toml b/src/hyperlight_wasm_aot/Cargo.toml index e309432..ae2859a 100644 --- a/src/hyperlight_wasm_aot/Cargo.toml +++ b/src/hyperlight_wasm_aot/Cargo.toml @@ -12,7 +12,7 @@ Application to precompile WebAssembly binaries to for hyperlight-wasm. """ [dependencies] -wasmtime = { version = "36.0.5", default-features = false, features = ["cranelift", "runtime", "component-model" ] } +wasmtime = { version = "36.0.5", default-features = false, features = ["cranelift", "pulley", "runtime", "component-model" ] } clap = { version = "4.5", features = ["derive"] } cargo_metadata = "0.23" cargo-util-schemas = "0.10.1" diff --git a/src/hyperlight_wasm_aot/src/main.rs b/src/hyperlight_wasm_aot/src/main.rs index 7ad9fcb..b1377ff 100644 --- a/src/hyperlight_wasm_aot/src/main.rs +++ b/src/hyperlight_wasm_aot/src/main.rs @@ -51,6 +51,10 @@ enum Commands { /// Disable address map and native unwind info for smaller binaries #[arg(long)] minimal: bool, + + /// Pre-compile for the pulley64 target + #[arg(long)] + pulley: bool, }, /// Check which Wasmtime version was used to precompile a module @@ -61,6 +65,10 @@ enum Commands { /// Specifies if the module has been compiled with debug support #[arg(long)] debug: bool, + + /// Specifies if the module has been compiled for pulley64 target + #[arg(long)] + pulley: bool, }, } @@ -74,6 +82,7 @@ fn main() { component, debug, minimal, + pulley, } => { let outfile = match output { Some(s) => s, @@ -83,15 +92,20 @@ fn main() { path.to_str().unwrap().to_string() } }; + let target = if pulley { + "pulley64".to_string() + } else { + "x86_64-unknown-none".to_string() + }; if debug { println!( - "Aot Compiling {} to {} with debug info and optimizations off", - input, outfile + "Aot Compiling {} to [{}]: {} with debug info and optimizations off", + input, target, outfile ); } else { - println!("Aot Compiling {} to {}", input, outfile); + println!("Aot Compiling {} to [{}]: {}", input, target, outfile); } - let config = get_config(debug, minimal); + let config = get_config(debug, minimal, pulley); let engine = Engine::new(&config).unwrap(); let bytes = std::fs::read(&input).unwrap(); let serialized = if component { @@ -101,7 +115,11 @@ fn main() { }; std::fs::write(outfile, serialized).unwrap(); } - Commands::CheckWasmtimeVersion { file, debug } => { + Commands::CheckWasmtimeVersion { + file, + debug, + pulley, + } => { // get the wasmtime version used by hyperlight-wasm-aot let metadata = MetadataCommand::new().exec().unwrap(); let package_name = PackageName::new("wasmtime".to_string()).unwrap(); @@ -121,7 +139,7 @@ fn main() { } // 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, false); + let config = get_config(debug, false, pulley); let engine = Engine::new(&config).unwrap(); match Engine::detect_precompiled(&bytes) { Some(pre_compiled) => { @@ -168,9 +186,15 @@ fn main() { } /// Returns a new `Config` for the Wasmtime engine with additional settings for AOT compilation. -fn get_config(debug: bool, minimal: bool) -> Config { +fn get_config(debug: bool, minimal: bool, pulley: bool) -> Config { let mut config = Config::new(); - config.target("x86_64-unknown-none").unwrap(); + + // Compile for the pulley64 target if specified + if pulley { + config.target("pulley64").unwrap(); + } else { + config.target("x86_64-unknown-none").unwrap(); + } // Enable the default features for the Wasmtime engine. if debug { diff --git a/src/wasm_runtime/Cargo.toml b/src/wasm_runtime/Cargo.toml index 5702ba4..7d60e3d 100644 --- a/src/wasm_runtime/Cargo.toml +++ b/src/wasm_runtime/Cargo.toml @@ -31,4 +31,5 @@ reqwest = {version = "0.12", default-features = false, features = ["blocking"," [features] default = [] gdb = ["wasmtime/debug-builtins"] +pulley = ["wasmtime/pulley"] trace_guest = ["hyperlight-common/trace_guest", "hyperlight-guest/trace_guest", "hyperlight-guest-bin/trace_guest"] diff --git a/src/wasm_runtime/build.rs b/src/wasm_runtime/build.rs index 2aa4b60..4b19da6 100644 --- a/src/wasm_runtime/build.rs +++ b/src/wasm_runtime/build.rs @@ -67,5 +67,6 @@ fn main() { cfg_aliases::cfg_aliases! { gdb: { all(feature = "gdb", debug_assertions) }, + pulley: { feature = "pulley" }, } } diff --git a/src/wasm_runtime/src/component.rs b/src/wasm_runtime/src/component.rs index ea43d03..de07296 100644 --- a/src/wasm_runtime/src/component.rs +++ b/src/wasm_runtime/src/component.rs @@ -111,6 +111,16 @@ pub extern "C" fn hyperlight_main() { config.with_custom_code_memory(Some(alloc::sync::Arc::new(platform::WasmtimeCodeMemory {}))); #[cfg(gdb)] config.debug_info(true); + #[cfg(pulley)] + config + .target("pulley64") + .map_err(|_| { + HyperlightGuestError::new( + ErrorCode::GuestError, + "Failed to set wasmtime target: pulley64".to_string(), + ) + }) + .unwrap(); let engine = Engine::new(&config).unwrap(); let linker = Linker::new(&engine); *CUR_ENGINE.lock() = Some(engine); diff --git a/src/wasm_runtime/src/module.rs b/src/wasm_runtime/src/module.rs index 14e2d64..195cf0c 100644 --- a/src/wasm_runtime/src/module.rs +++ b/src/wasm_runtime/src/module.rs @@ -101,6 +101,13 @@ fn init_wasm_runtime() -> Result> { config.with_custom_code_memory(Some(alloc::sync::Arc::new(platform::WasmtimeCodeMemory {}))); #[cfg(gdb)] config.debug_info(true); + #[cfg(pulley)] + config.target("pulley64").map_err(|_| { + HyperlightGuestError::new( + ErrorCode::GuestError, + "Failed to set wasmtime target: pulley64".to_string(), + ) + })?; let engine = Engine::new(&config)?; let mut linker = Linker::new(&engine); wasip1::register_handlers(&mut linker)?; From 51d839b4ec530ac74810e0e08b018df0a1e87c9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Doru=20Bl=C3=A2nzeanu?= Date: Wed, 4 Feb 2026 15:47:33 +0200 Subject: [PATCH 2/2] Add some tests for pulley on CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Doru Blânzeanu --- Justfile | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/Justfile b/Justfile index 4ad3301..d3686e0 100644 --- a/Justfile +++ b/Justfile @@ -43,6 +43,11 @@ build-rust-wasm-examples target=default-target features="": (mkdir-redist target cd ./src/rust_wasm_samples && cargo build --target wasm32-unknown-unknown --profile={{ if target == "debug" {"dev"} else { target } }} cargo run {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--features " + features } }} -p hyperlight-wasm-aot compile {{ if features =~ "gdb" {"--debug"} else {""} }} ./src/rust_wasm_samples/target/wasm32-unknown-unknown/{{ target }}/rust_wasm_samples.wasm ./x64/{{ target }}/rust_wasm_samples.aot +build-pulley-rust-wasm-examples target=default-target features="": (mkdir-redist target) + rustup target add wasm32-unknown-unknown + cd ./src/rust_wasm_samples && cargo build --target wasm32-unknown-unknown --profile={{ if target == "debug" {"dev"} else { target } }} + cargo run {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--features " + features } }} -p hyperlight-wasm-aot compile --pulley {{ if features =~ "gdb" {"--debug"} else {""} }} ./src/rust_wasm_samples/target/wasm32-unknown-unknown/{{ target }}/rust_wasm_samples.wasm ./x64/{{ target }}/rust_wasm_samples.aot + build-rust-component-examples target=default-target features="": (compile-wit) # use cargo component so we don't get all the wasi imports https://github.com/bytecodealliance/cargo-component?tab=readme-ov-file#relationship-with-wasm32-wasip2 # we also explicitly target wasm32-unknown-unknown since cargo component might try to pull in wasi imports https://github.com/bytecodealliance/cargo-component/issues/290 @@ -50,6 +55,13 @@ build-rust-component-examples target=default-target features="": (compile-wit) cd ./src/component_sample && cargo component build --target wasm32-unknown-unknown --profile={{ if target == "debug" {"dev"} else { target } }} cargo run {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--features " + features } }} -p hyperlight-wasm-aot compile {{ if features =~ "gdb" {"--debug"} else {""} }} --component ./src/component_sample/target/wasm32-unknown-unknown/{{ target }}/component_sample.wasm ./x64/{{ target }}/component_sample.aot +build-pulley-rust-component-examples target=default-target features="": (compile-wit) + # use cargo component so we don't get all the wasi imports https://github.com/bytecodealliance/cargo-component?tab=readme-ov-file#relationship-with-wasm32-wasip2 + # we also explicitly target wasm32-unknown-unknown since cargo component might try to pull in wasi imports https://github.com/bytecodealliance/cargo-component/issues/290 + rustup target add wasm32-unknown-unknown + cd ./src/component_sample && cargo component build --target wasm32-unknown-unknown --profile={{ if target == "debug" {"dev"} else { target } }} + cargo run {{ if features =="" {''} else if features=="no-default-features" {"--no-default-features" } else {"--features " + features } }} -p hyperlight-wasm-aot compile --pulley {{ if features =~ "gdb" {"--debug"} else {""} }} --component ./src/component_sample/target/wasm32-unknown-unknown/{{ target }}/component_sample.wasm ./x64/{{ target }}/component_sample.aot + check target=default-target: cargo check --profile={{ if target == "debug" {"dev"} else { target } }} cd src/rust_wasm_samples && cargo check --profile={{ if target == "debug" {"dev"} else { target } }} @@ -97,12 +109,18 @@ examples-ci target=default-target features="": (build-rust-wasm-examples target) cargo run {{ if features =="" {''} else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example rust_wasm_examples cargo run {{ if features =="" {''} else {"--no-default-features -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example interruption cargo run {{ if features =="" {''} else {"--no-default-features -F function_call_metrics," + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example metrics - cargo run {{ if features =="" {"--no-default-features --features kvm,mshv3"} else {"--no-default-features -F function_call_metrics," + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example metrics + cargo run {{ if features =="" {"--no-default-features --features kvm,mshv3"} else {"--no-default-features -F function_call_metrics," + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example metrics + just examples-pulley {{ target }} {{ features }} examples-components target=default-target features="": (build-rust-component-examples target) {{ wit-world }} cargo run {{ if features =="" {''} else {"--no-default-features -F kvm -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example component_example {{ wit-world-c }} cargo run {{ if features =="" {''} else {"--no-default-features -F kvm -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example c-component +# Test a component and a module compiled with pulley +examples-pulley target=default-target features="": (build-pulley-rust-component-examples target) (build-pulley-rust-wasm-examples target) + {{ wit-world }} cargo run {{ if features =="" {'-F pulley'} else {"--no-default-features -F kvm,pulley -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example component_example + cargo run {{ if features =="" {'-F pulley'} else {"--no-default-features -F pulley -F " + features } }} --profile={{ if target == "debug" {"dev"} else { target } }} --example rust_wasm_examples + # warning, compares to and then OVERWRITES the given baseline bench-ci baseline target="release" features="": cd src/hyperlight_wasm && cargo bench --profile={{ if target == "debug" {"dev"} else { target } }} {{ if features =="" {''} else { "--features " + features } }} --bench benchmarks -- --verbose --save-baseline {{baseline}}