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
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
run: cargo test --release

- name: Setup registry
run: cargo run --release -- --setup-registry
run: cargo run --release -- setup-registry

- name: Run CLI with JavaScript
run: cargo run --release -- guest-examples/hello.js
Expand Down Expand Up @@ -102,7 +102,7 @@ jobs:
run: npm run build

- name: Setup registry
run: cargo run --release -- --setup-registry
run: cargo run --release -- setup-registry

- name: Run Node.js example
run: node examples/napi.js
Expand Down Expand Up @@ -149,7 +149,7 @@ jobs:
run: .venv/bin/maturin develop --features python

- name: Setup registry
run: cargo run --release -- --setup-registry
run: cargo run --release -- setup-registry

- name: Run Python example
run: .venv/bin/python examples/python_sdk_example.py
131 changes: 129 additions & 2 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ nanvix = { git = "https://github.com/nanvix/nanvix", rev = "7752e9f2deb4a5606f98
] }
tokio = { version = "1.0", features = ["rt-multi-thread", "macros"] }
anyhow = "1.0"
clap = { version = "4", features = ["derive"] }
libc = "0.2.178"

# NAPI bindings (optional)
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ For compiled languages, you'll need to compile first, then run.
#### Setup (one-time)

```bash
cargo run -- --setup-registry
cargo run -- setup-registry
```

This downloads the toolchain and runtime files to `~/.cache/nanvix-registry/`.
Expand Down Expand Up @@ -251,8 +251,8 @@ cargo run --example syscall_interception
**Clear cache and re-download:**

```bash
cargo run -- --clear-registry
cargo run -- --setup-registry
cargo run -- clear-registry
cargo run -- setup-registry
```

**Clean socket files if networking issues occur:**
Expand Down
87 changes: 49 additions & 38 deletions src/bin/hyperlight-nanvix.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,37 @@
use anyhow::Result;
use clap::{Parser, Subcommand};
use hyperlight_nanvix::{cache, RuntimeConfig, Sandbox};
use nanvix::log;
use nanvix::registry::Registry;
use std::env;
use std::path::Path;
use std::path::PathBuf;

/// A Hyperlight VMM wrapper with out-of-the-box support for running Nanvix microkernel guests
#[derive(Parser)]
#[command(name = "hyperlight-nanvix")]
#[command(about = "Run scripts in a Nanvix microkernel guest")]
#[command(
after_help = "Supported file types: .js, .mjs (JavaScript), .py (Python), .elf, .o (Binary)"
)]
struct Cli {
/// Show detailed nanvix logging
#[arg(long)]
verbose: bool,

#[command(subcommand)]
command: Option<Commands>,

/// Path to the script to run
#[arg(value_name = "SCRIPT")]
script_path: Option<PathBuf>,
}

#[derive(Subcommand)]
enum Commands {
/// Download nanvix registry and show compilation instructions
SetupRegistry,
/// Clear the nanvix registry cache
ClearRegistry,
}

/// Default log-level (overridden by RUST_LOG environment variable if set).
const DEFAULT_LOG_LEVEL: &str = "info";
Expand Down Expand Up @@ -78,48 +106,31 @@ async fn clear_registry_command() -> Result<()> {
}
}

println!("Run 'cargo run -- --setup-registry' to re-download if needed.");
println!("Run 'cargo run -- setup-registry' to re-download if needed.");
Ok(())
}

#[tokio::main]
async fn main() -> Result<()> {
// Parse command line arguments first
let args: Vec<String> = env::args().collect();

// Check for flags
let verbose = args.contains(&"--verbose".to_string());
let setup_registry = args.contains(&"--setup-registry".to_string());
let clear_registry = args.contains(&"--clear-registry".to_string());

// Handle setup-registry command
if setup_registry {
return setup_registry_command().await;
let cli = Cli::parse();

// Handle subcommands
if let Some(command) = cli.command {
return match command {
Commands::SetupRegistry => setup_registry_command().await,
Commands::ClearRegistry => clear_registry_command().await,
};
}

// Handle clear-registry command
if clear_registry {
return clear_registry_command().await;
}

// Find the script argument (first non-flag argument)
let script_arg = args
.iter()
.position(|arg| !arg.starts_with("--") && !arg.ends_with("hyperlight-nanvix"));

let script_path = if let Some(idx) = script_arg {
Path::new(&args[idx])
} else {
eprintln!("Usage: {} [--verbose] <script_path>", args[0]);
eprintln!(" {} --setup-registry", args[0]);
eprintln!(" {} --clear-registry", args[0]);
eprintln!("Supported file types: .js, .mjs (JavaScript), .py (Python), .elf, .o (Binary)");
eprintln!("Options:");
eprintln!(" --verbose Show detailed nanvix logging");
eprintln!(" --setup-registry Download nanvix registry and show compilation instructions");
eprintln!(" --clear-registry Clear the nanvix registry cache");
// Require script path for default operation
let script_path = cli.script_path.unwrap_or_else(|| {
eprintln!("error: the following required arguments were not provided:\n <SCRIPT>\n");
eprintln!("Usage: hyperlight-nanvix [OPTIONS] <SCRIPT>");
eprintln!(" hyperlight-nanvix setup-registry");
eprintln!(" hyperlight-nanvix clear-registry");
eprintln!("\nFor more information, try '--help'.");
std::process::exit(1);
};
});

// Check if file exists
if !script_path.exists() {
Expand All @@ -128,7 +139,7 @@ async fn main() -> Result<()> {
}

// Initialize nanvix logging only when --verbose is specified
if verbose {
if cli.verbose {
log::init(
false,
DEFAULT_LOG_LEVEL,
Expand All @@ -146,7 +157,7 @@ async fn main() -> Result<()> {
let mut sandbox = Sandbox::new(config)?;

// Run the workload
match sandbox.run(script_path).await {
match sandbox.run(&script_path).await {
Ok(()) => {}
Err(e) => {
eprintln!("Error running workload: {}", e);
Expand Down