Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add verbose flag to print cargo commands #42

Merged
merged 2 commits into from
Aug 16, 2023
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
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);
}