Skip to content

Commit

Permalink
feat: add mopro build command (#237)
Browse files Browse the repository at this point in the history
* feat: init mopro-cli package

* feat(cli): let users select adapters

* feat(cli): refactor init_project function to use optional arguments

* feat: add `mopro build` command

* chore: udpate text style
  • Loading branch information
vivianjeng authored Sep 13, 2024
1 parent c659894 commit b625093
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 2 deletions.
6 changes: 6 additions & 0 deletions cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,9 @@ cargo install --path .
```sh
mopro init
```

## Build bindings

```sh
mopro build
```
118 changes: 118 additions & 0 deletions cli/src/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
use crate::style::{self, blue_bold, print_green_bold};
use dialoguer::{theme::ColorfulTheme, MultiSelect, Select};
use std::{env, error::Error};

const MODES: [&str; 2] = ["debug", "release"];
const PLATFORMS: [&str; 2] = ["ios", "android"];

pub fn build_project(
arg_mode: &Option<String>,
arg_platforms: &Option<Vec<String>>,
) -> Result<(), Box<dyn Error>> {
let mode: String = match arg_mode.as_deref() {
None => select_mode()?,
Some(m) => {
if MODES.contains(&m) {
m.to_string()
} else {
style::print_yellow("Invalid mode selected. Please choose a valid mode (e.g., 'release' or 'debug').".to_string());
select_mode()?
}
}
};

let platforms: Vec<String> = match arg_platforms {
None => select_platforms()?,
Some(p) => {
let mut valid_platforms: Vec<String> = p
.iter()
.filter(|&platform| PLATFORMS.contains(&platform.as_str()))
.map(|platform| platform.to_owned())
.collect();

if valid_platforms.is_empty() {
style::print_yellow(
"No platforms selected. Please select at least one platform.".to_string(),
);
valid_platforms = select_platforms()?;
} else if valid_platforms.len() != p.len() {
style::print_yellow(
format!(
"Invalid platform(s) selected. Only {:?} platform(s) is created.",
&valid_platforms
)
.to_string(),
);
}

valid_platforms
}
};

if platforms.is_empty() {
style::print_yellow("No platform selected. Use space to select platform(s).".to_string());
build_project(&Some(mode), &None)?;
} else {
for platform in platforms.clone() {
let status = std::process::Command::new("cargo")
.arg("run")
.arg("--bin")
.arg(platform.clone())
.env("CONFIGURATION", mode.clone())
.status()?;

if !status.success() {
// Return a custom error if the command fails
return Err(format!("Output with status code {}", status.code().unwrap()).into());
}
}

print_binding_message(platforms)?;
}

Ok(())
}

fn select_mode() -> Result<String, Box<dyn Error>> {
let idx = Select::with_theme(&ColorfulTheme::default())
.with_prompt("Build mode")
.items(&MODES)
.interact()?;

Ok(MODES[idx].to_owned())
}

fn select_platforms() -> Result<Vec<String>, Box<dyn Error>> {
let selected_platforms = MultiSelect::with_theme(&ColorfulTheme::default())
.with_prompt("Select platform(s) to build for (multiple selection with space)")
.items(&PLATFORMS)
.interact()?;

Ok(selected_platforms
.iter()
.map(|&idx| PLATFORMS[idx].to_owned())
.collect())
}

fn print_binding_message(platforms: Vec<String>) -> Result<(), Box<dyn Error>> {
let current_dir = env::current_dir()?;
print_green_bold("✨ Bindings Built Successfully! ✨".to_string());
println!("The Mopro bindings have been successfully generated and are available in the following directories:\n");
for platform in platforms {
let text = format!(
"- {}/Mopro{}Bindings",
current_dir.display(),
platform
.to_lowercase()
.replace("ios", "iOS")
.replace("android", "Android")
);
println!("{}", blue_bold(text.to_string()));
}
println!();
println!(
"📚 To learn more about mopro, visit: {}",
style::blue_bold("https://zkmopro.org".to_string())
);
Ok(())
}
3 changes: 1 addition & 2 deletions cli/src/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,7 @@ pub fn init_project(
print_bold(format!(" cd {}", &project_name));
println!();
print_green_bold("2. Run the following commands to build and run the project:".to_string());
print_bold(" cargo run --bin ios".to_string());
print_bold(" cargo run --bin android".to_string());
print_bold(" mopro build".to_string());
println!();
println!(
"📚 To learn more about mopro, visit: {}",
Expand Down
12 changes: 12 additions & 0 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use clap::{Parser, Subcommand};

mod build;
mod init;
mod style;

Expand All @@ -22,6 +23,13 @@ enum Commands {
#[arg(long)]
project_name: Option<String>,
},
/// Builds the project for specified platforms
Build {
#[arg(long, help = "Specify the build mode (e.g., 'release' or 'debug').")]
mode: Option<String>,
#[arg(long, num_args = 1.., help = "Specify the platforms to build for (e.g., 'ios', 'android').")]
platforms: Option<Vec<String>>,
},
}

fn main() {
Expand All @@ -35,5 +43,9 @@ fn main() {
Ok(_) => {}
Err(e) => style::print_read_bold(format!("Failed to initialize project {:?}", e)),
},
Commands::Build { mode, platforms } => match build::build_project(mode, platforms) {
Ok(_) => {}
Err(e) => style::print_read_bold(format!("Failed to build project {:?}", e)),
},
}
}

0 comments on commit b625093

Please sign in to comment.