Skip to content

Commit

Permalink
Merge pull request #42 from rust3ds/feature/verbose-flag
Browse files Browse the repository at this point in the history
  • Loading branch information
ian-h-chamberlain authored Aug 16, 2023
2 parents 268c45a + 48aa793 commit cda49e0
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 37 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ serde = { version = "1.0.139", features = ["derive"] }
tee = "0.1.0"
toml = "0.5.6"
clap = { version = "4.0.15", features = ["derive", "wrap_help"] }
shlex = "1.1.0"
49 changes: 31 additions & 18 deletions src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ pub enum Cargo {
pub struct Input {
#[command(subcommand)]
pub cmd: CargoCmd,

/// Print the exact commands `cargo-3ds` is running. Note that this does not
/// set the verbose flag for cargo itself.
#[arg(long, short = 'v')]
pub verbose: bool,
}

/// Run a cargo command. COMMAND will be forwarded to the real
Expand Down Expand Up @@ -153,6 +158,10 @@ impl CargoCmd {
"--doc".to_string(),
"-Z".to_string(),
"doctest-xcompile".to_string(),
// doctests don't automatically build the `test` crate,
// so we manually specify it on the command line
"-Z".to_string(),
"build-std=std,test".to_string(),
]);
} else {
cargo_args.push("--no-run".to_string());
Expand Down Expand Up @@ -278,21 +287,21 @@ impl CargoCmd {
///
/// - `cargo 3ds build` and other "build" commands will use their callbacks to build the final `.3dsx` file and link it.
/// - `cargo 3ds new` and other generic commands will use their callbacks to make 3ds-specific changes to the environment.
pub fn run_callback(&self, messages: &[Message]) {
pub fn run_callback(&self, messages: &[Message], verbose: bool) {
// Process the metadata only for commands that have it/use it
let config = if self.should_build_3dsx() {
eprintln!("Getting metadata");

get_metadata(messages)
Some(get_metadata(messages))
} else {
CTRConfig::default()
None
};

// Run callback only for commands that use it
match self {
Self::Build(cmd) => cmd.callback(&config),
Self::Run(cmd) => cmd.callback(&config),
Self::Test(cmd) => cmd.callback(&config),
Self::Build(cmd) => cmd.callback(&config, verbose),
Self::Run(cmd) => cmd.callback(&config, verbose),
Self::Test(cmd) => cmd.callback(&config, verbose),
Self::New(cmd) => cmd.callback(),
_ => (),
}
Expand Down Expand Up @@ -327,12 +336,14 @@ impl Build {
/// Callback for `cargo 3ds build`.
///
/// This callback handles building the application as a `.3dsx` file.
fn callback(&self, config: &CTRConfig) {
eprintln!("Building smdh:{}", config.path_smdh().display());
build_smdh(config);
fn callback(&self, config: &Option<CTRConfig>, verbose: bool) {
if let Some(config) = config {
eprintln!("Building smdh: {}", config.path_smdh().display());
build_smdh(config, verbose);

eprintln!("Building 3dsx: {}", config.path_3dsx().display());
build_3dsx(config);
eprintln!("Building 3dsx: {}", config.path_3dsx().display());
build_3dsx(config, verbose);
}
}
}

Expand Down Expand Up @@ -381,26 +392,28 @@ impl Run {
/// Callback for `cargo 3ds run`.
///
/// This callback handles launching the application via `3dslink`.
fn callback(&self, config: &CTRConfig) {
fn callback(&self, config: &Option<CTRConfig>, verbose: bool) {
// Run the normal "build" callback
self.build_args.callback(config);
self.build_args.callback(config, verbose);

eprintln!("Running 3dslink");
link(config, self);
if let Some(cfg) = config {
eprintln!("Running 3dslink");
link(cfg, self, verbose);
}
}
}

impl Test {
/// Callback for `cargo 3ds test`.
///
/// This callback handles launching the application via `3dslink`.
fn callback(&self, config: &CTRConfig) {
fn callback(&self, config: &Option<CTRConfig>, verbose: bool) {
if self.no_run {
// If the tests don't have to run, use the "build" callback
self.run_args.build_args.callback(config)
self.run_args.build_args.callback(config, verbose);
} else {
// If the tests have to run, use the "run" callback
self.run_args.callback(config)
self.run_args.callback(config, verbose);
}
}
}
Expand Down
69 changes: 52 additions & 17 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pub mod command;
use crate::command::{CargoCmd, Run};

use cargo_metadata::{Message, MetadataCommand};
use command::Test;
use command::{Input, Test};
use rustc_version::Channel;
use semver::Version;
use serde::Deserialize;
Expand All @@ -20,16 +20,20 @@ use std::{env, io, process};
///
/// For commands that produce an executable output, this function will build the
/// `.elf` binary that can be used to create other 3ds files.
pub fn run_cargo(cmd: &CargoCmd, message_format: Option<String>) -> (ExitStatus, Vec<Message>) {
let mut command = make_cargo_command(cmd, &message_format);
pub fn run_cargo(input: &Input, message_format: Option<String>) -> (ExitStatus, Vec<Message>) {
let mut command = make_cargo_command(&input.cmd, &message_format);

if input.verbose {
print_command(&command);
}

let mut process = command.spawn().unwrap();
let command_stdout = process.stdout.take().unwrap();

let mut tee_reader;
let mut stdout_reader;

let buf_reader: &mut dyn BufRead = match (message_format, cmd) {
let buf_reader: &mut dyn BufRead = match (message_format, &input.cmd) {
// The user presumably cares about the message format if set, so we should
// copy stuff to stdout like they expect. We can still extract the executable
// information out of it that we need for 3dsxtool etc.
Expand Down Expand Up @@ -112,6 +116,23 @@ pub fn make_cargo_command(cmd: &CargoCmd, message_format: &Option<String>) -> Co
command
}

fn print_command(command: &Command) {
let mut cmd_str = vec![command.get_program().to_string_lossy().to_string()];
cmd_str.extend(command.get_args().map(|s| s.to_string_lossy().to_string()));

eprintln!("Running command:");
for (k, v) in command.get_envs() {
let v = v.map(|v| v.to_string_lossy().to_string());
eprintln!(
" {}={} \\",
k.to_string_lossy(),
v.map_or_else(String::new, |s| shlex::quote(&s).to_string())
);
}
eprintln!(" {}", shlex::join(cmd_str.iter().map(String::as_str)));
eprintln!();
}

/// Finds the sysroot path of the current toolchain
pub fn find_sysroot() -> PathBuf {
let sysroot = env::var("SYSROOT").ok().unwrap_or_else(|| {
Expand Down Expand Up @@ -235,8 +256,9 @@ pub fn get_metadata(messages: &[Message]) -> CTRConfig {

/// Builds the smdh using `smdhtool`.
/// This will fail if `smdhtool` is not within the running directory or in a directory found in $PATH
pub fn build_smdh(config: &CTRConfig) {
let mut process = Command::new("smdhtool")
pub fn build_smdh(config: &CTRConfig, verbose: bool) {
let mut command = Command::new("smdhtool");
command
.arg("--create")
.arg(&config.name)
.arg(&config.description)
Expand All @@ -245,7 +267,13 @@ pub fn build_smdh(config: &CTRConfig) {
.arg(config.path_smdh())
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.stderr(Stdio::inherit());

if verbose {
print_command(&command);
}

let mut process = command
.spawn()
.expect("smdhtool command failed, most likely due to 'smdhtool' not being in $PATH");

Expand All @@ -258,9 +286,9 @@ pub fn build_smdh(config: &CTRConfig) {

/// Builds the 3dsx using `3dsxtool`.
/// This will fail if `3dsxtool` is not within the running directory or in a directory found in $PATH
pub fn build_3dsx(config: &CTRConfig) {
pub fn build_3dsx(config: &CTRConfig, verbose: bool) {
let mut command = Command::new("3dsxtool");
let mut process = command
command
.arg(&config.target_path)
.arg(config.path_3dsx())
.arg(format!("--smdh={}", config.path_smdh().to_string_lossy()));
Expand All @@ -269,7 +297,7 @@ pub fn build_3dsx(config: &CTRConfig) {
let (romfs_path, is_default_romfs) = get_romfs_path(config);
if romfs_path.is_dir() {
eprintln!("Adding RomFS from {}", romfs_path.display());
process = process.arg(format!("--romfs={}", romfs_path.to_string_lossy()));
command.arg(format!("--romfs={}", romfs_path.to_string_lossy()));
} else if !is_default_romfs {
eprintln!(
"Could not find configured RomFS dir: {}",
Expand All @@ -278,7 +306,11 @@ pub fn build_3dsx(config: &CTRConfig) {
process::exit(1);
}

let mut process = process
if verbose {
print_command(&command);
}

let mut process = command
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
Expand All @@ -294,17 +326,20 @@ pub fn build_3dsx(config: &CTRConfig) {

/// Link the generated 3dsx to a 3ds to execute and test using `3dslink`.
/// This will fail if `3dslink` is not within the running directory or in a directory found in $PATH
pub fn link(config: &CTRConfig, run_args: &Run) {
let mut process = Command::new("3dslink")
pub fn link(config: &CTRConfig, run_args: &Run, verbose: bool) {
let mut command = Command::new("3dslink");
command
.arg(config.path_3dsx())
.args(run_args.get_3dslink_args())
.stdin(Stdio::inherit())
.stdout(Stdio::inherit())
.stderr(Stdio::inherit())
.spawn()
.unwrap();
.stderr(Stdio::inherit());

let status = process.wait().unwrap();
if verbose {
print_command(&command);
}

let status = command.spawn().unwrap().wait().unwrap();

if !status.success() {
process::exit(status.code().unwrap_or(1));
Expand Down
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ fn main() {
}
};

let (status, messages) = run_cargo(&input.cmd, message_format);
let (status, messages) = run_cargo(&input, message_format);

if !status.success() {
process::exit(status.code().unwrap_or(1));
}

input.cmd.run_callback(&messages);
input.cmd.run_callback(&messages, input.verbose);
}

0 comments on commit cda49e0

Please sign in to comment.