Skip to content

Commit 9d49d16

Browse files
committed
feat(cli): register Wasm modules as custom tools
Signed-off-by: akrm al-hakimi <alhakimiakrmj@gmail.com>
1 parent 21aa0b2 commit 9d49d16

1 file changed

Lines changed: 114 additions & 0 deletions

File tree

host/src/main.rs

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ use hyperlight_unikraft::{
1313
};
1414
use std::path::PathBuf;
1515

16+
#[cfg(feature = "wasm-host-fns")]
17+
mod wasm_host_fns;
18+
1619
#[derive(Parser, Debug)]
1720
#[command(
1821
name = "hyperlight-unikraft",
@@ -43,6 +46,64 @@ struct Args {
4346
#[arg(long)]
4447
enable_tools: bool,
4548

49+
#[cfg(feature = "wasm-host-fns")]
50+
#[arg(
51+
long = "tool",
52+
value_name = "NAME=WASM",
53+
help = "Register a WASIp1 module as a host tool"
54+
)]
55+
tool: Vec<String>,
56+
57+
#[cfg(feature = "wasm-host-fns")]
58+
#[arg(
59+
long = "tool-wasi-dir",
60+
value_name = "HOST[:GUEST]",
61+
help = "Preopen a read-write host directory for Wasm tools"
62+
)]
63+
tool_wasi_dir: Vec<String>,
64+
65+
#[cfg(feature = "wasm-host-fns")]
66+
#[arg(
67+
long = "tool-wasi-dir-ro",
68+
value_name = "HOST[:GUEST]",
69+
help = "Preopen a read-only host directory for Wasm tools"
70+
)]
71+
tool_wasi_dir_ro: Vec<String>,
72+
73+
#[cfg(feature = "wasm-host-fns")]
74+
#[arg(
75+
long = "tool-wasi-env",
76+
value_name = "KEY=VALUE",
77+
help = "Set an environment variable for Wasm tools"
78+
)]
79+
tool_wasi_env: Vec<String>,
80+
81+
#[cfg(feature = "wasm-host-fns")]
82+
#[arg(
83+
long = "tool-wasi-env-inherit",
84+
value_name = "KEY",
85+
help = "Inherit one host environment variable into Wasm tools"
86+
)]
87+
tool_wasi_env_inherit: Vec<String>,
88+
89+
#[cfg(feature = "wasm-host-fns")]
90+
#[arg(
91+
long = "tool-wasi-fuel",
92+
default_value_t = 100_000_000,
93+
value_name = "FUEL",
94+
help = "Fuel units available to each Wasm tool call"
95+
)]
96+
tool_wasi_fuel: u64,
97+
98+
#[cfg(feature = "wasm-host-fns")]
99+
#[arg(
100+
long = "tool-wasi-output-limit",
101+
default_value = "1Mi",
102+
value_name = "SIZE",
103+
help = "Maximum stdout or stderr captured from one Wasm tool call"
104+
)]
105+
tool_wasi_output_limit: String,
106+
46107
/// Preopen a host directory for the guest's sandboxed filesystem.
47108
///
48109
/// Syntax: `HOST_DIR[:GUEST_PATH]`. When `GUEST_PATH` is omitted the
@@ -206,6 +267,53 @@ fn main() -> Result<()> {
206267
None
207268
};
208269

270+
#[cfg(feature = "wasm-host-fns")]
271+
let wasm_tools = {
272+
if args.tool.is_empty()
273+
&& wasm_host_fns::WasmToolOptions::has_capabilities(
274+
&args.tool_wasi_dir,
275+
&args.tool_wasi_dir_ro,
276+
&args.tool_wasi_env,
277+
&args.tool_wasi_env_inherit,
278+
)
279+
{
280+
return Err(anyhow::anyhow!(
281+
"--tool-wasi-* flags require at least one --tool"
282+
));
283+
}
284+
if args.tool.is_empty() {
285+
Vec::new()
286+
} else {
287+
let output_limit = parse_memory(&args.tool_wasi_output_limit)?;
288+
let output_limit = usize::try_from(output_limit).map_err(|_| {
289+
anyhow::anyhow!(
290+
"--tool-wasi-output-limit too large: {}",
291+
args.tool_wasi_output_limit
292+
)
293+
})?;
294+
let options = wasm_host_fns::WasmToolOptions::from_cli(
295+
&args.tool_wasi_dir,
296+
&args.tool_wasi_dir_ro,
297+
&args.tool_wasi_env,
298+
&args.tool_wasi_env_inherit,
299+
args.tool_wasi_fuel,
300+
output_limit,
301+
)?;
302+
let tools = wasm_host_fns::WasmTool::load_all(&args.tool, &options)?;
303+
if args.enable_tools && tools.iter().any(|tool| tool.name() == "echo") {
304+
return Err(anyhow::anyhow!(
305+
"--tool echo=... conflicts with --enable-tools built-in echo"
306+
));
307+
}
308+
if !args.quiet {
309+
for tool in &tools {
310+
eprintln!("Tool: {} -> {}", tool.name(), tool.path().display());
311+
}
312+
}
313+
tools
314+
}
315+
};
316+
209317
let mut builder = Sandbox::builder(&args.kernel)
210318
.args(app_args)
211319
.heap_size(heap_size)
@@ -225,6 +333,12 @@ fn main() -> Result<()> {
225333
if args.enable_tools {
226334
builder = builder.tool("echo", Ok);
227335
}
336+
#[cfg(feature = "wasm-host-fns")]
337+
for tool in wasm_tools {
338+
let name = tool.name().to_string();
339+
let tool = std::sync::Arc::new(tool);
340+
builder = builder.tool(&name, move |args| tool.invoke(args));
341+
}
228342
let mut sandbox = builder.build()?;
229343
let evolve_time = t0.elapsed();
230344

0 commit comments

Comments
 (0)