11use anyhow:: Result ;
2+ use clap:: { Parser , Subcommand } ;
23use hyperlight_nanvix:: { cache, RuntimeConfig , Sandbox } ;
34use nanvix:: log;
45use nanvix:: registry:: Registry ;
5- use std:: env;
6- use std:: path:: Path ;
6+ use std:: path:: PathBuf ;
7+
8+ /// A Hyperlight VMM wrapper with out-of-the-box support for running Nanvix microkernel guests
9+ #[ derive( Parser ) ]
10+ #[ command( name = "hyperlight-nanvix" ) ]
11+ #[ command( about = "Run scripts in a Nanvix microkernel guest" ) ]
12+ #[ command( after_help = "Supported file types: .js, .mjs (JavaScript), .py (Python), .elf, .o (Binary)" ) ]
13+ struct Cli {
14+ /// Show detailed nanvix logging
15+ #[ arg( long) ]
16+ verbose : bool ,
17+
18+ #[ command( subcommand) ]
19+ command : Option < Commands > ,
20+
21+ /// Path to the script to run
22+ #[ arg( value_name = "SCRIPT" ) ]
23+ script_path : Option < PathBuf > ,
24+ }
25+
26+ #[ derive( Subcommand ) ]
27+ enum Commands {
28+ /// Download nanvix registry and show compilation instructions
29+ SetupRegistry ,
30+ /// Clear the nanvix registry cache
31+ ClearRegistry ,
32+ }
733
834/// Default log-level (overridden by RUST_LOG environment variable if set).
935const DEFAULT_LOG_LEVEL : & str = "info" ;
@@ -76,42 +102,25 @@ async fn clear_registry_command() -> Result<()> {
76102
77103#[ tokio:: main]
78104async fn main ( ) -> Result < ( ) > {
79- // Parse command line arguments first
80- let args: Vec < String > = env:: args ( ) . collect ( ) ;
105+ let cli = Cli :: parse ( ) ;
81106
82- // Check for flags
83- let verbose = args. contains ( & "--verbose" . to_string ( ) ) ;
84- let setup_registry = args. contains ( & "--setup-registry" . to_string ( ) ) ;
85- let clear_registry = args. contains ( & "--clear-registry" . to_string ( ) ) ;
86-
87- // Handle setup-registry command
88- if setup_registry {
89- return setup_registry_command ( ) . await ;
90- }
91-
92- // Handle clear-registry command
93- if clear_registry {
94- return clear_registry_command ( ) . await ;
107+ // Handle subcommands
108+ if let Some ( command) = cli. command {
109+ return match command {
110+ Commands :: SetupRegistry => setup_registry_command ( ) . await ,
111+ Commands :: ClearRegistry => clear_registry_command ( ) . await ,
112+ } ;
95113 }
96114
97- // Find the script argument (first non-flag argument)
98- let script_arg = args
99- . iter ( )
100- . position ( |arg| !arg. starts_with ( "--" ) && !arg. ends_with ( "hyperlight-nanvix" ) ) ;
101-
102- let script_path = if let Some ( idx) = script_arg {
103- Path :: new ( & args[ idx] )
104- } else {
105- eprintln ! ( "Usage: {} [--verbose] <script_path>" , args[ 0 ] ) ;
106- eprintln ! ( " {} --setup-registry" , args[ 0 ] ) ;
107- eprintln ! ( " {} --clear-registry" , args[ 0 ] ) ;
108- eprintln ! ( "Supported file types: .js, .mjs (JavaScript), .py (Python), .elf, .o (Binary)" ) ;
109- eprintln ! ( "Options:" ) ;
110- eprintln ! ( " --verbose Show detailed nanvix logging" ) ;
111- eprintln ! ( " --setup-registry Download nanvix registry and show compilation instructions" ) ;
112- eprintln ! ( " --clear-registry Clear the nanvix registry cache" ) ;
115+ // Require script path for default operation
116+ let script_path = cli. script_path . unwrap_or_else ( || {
117+ eprintln ! ( "error: the following required arguments were not provided:\n <SCRIPT>\n " ) ;
118+ eprintln ! ( "Usage: hyperlight-nanvix [OPTIONS] <SCRIPT>" ) ;
119+ eprintln ! ( " hyperlight-nanvix setup-registry" ) ;
120+ eprintln ! ( " hyperlight-nanvix clear-registry" ) ;
121+ eprintln ! ( "\n For more information, try '--help'." ) ;
113122 std:: process:: exit ( 1 ) ;
114- } ;
123+ } ) ;
115124
116125 // Check if file exists
117126 if !script_path. exists ( ) {
@@ -120,7 +129,7 @@ async fn main() -> Result<()> {
120129 }
121130
122131 // Initialize nanvix logging only when --verbose is specified
123- if verbose {
132+ if cli . verbose {
124133 log:: init (
125134 false ,
126135 DEFAULT_LOG_LEVEL ,
@@ -138,7 +147,7 @@ async fn main() -> Result<()> {
138147 let mut sandbox = Sandbox :: new ( config) ?;
139148
140149 // Run the workload
141- match sandbox. run ( script_path) . await {
150+ match sandbox. run ( & script_path) . await {
142151 Ok ( ( ) ) => { }
143152 Err ( e) => {
144153 eprintln ! ( "Error running workload: {}" , e) ;
0 commit comments