@@ -13,6 +13,9 @@ use hyperlight_unikraft::{
1313} ;
1414use 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