Browse Source

Add verbose flag to print cargo commands

Also fix minor issue with building test crate for doctests.
pull/42/head
Ian Chamberlain 1 year ago
parent
commit
d374e7016d
No known key found for this signature in database
GPG Key ID: AE5484D09405AA60
  1. 1
      Cargo.toml
  2. 35
      src/command.rs
  3. 69
      src/lib.rs
  4. 4
      src/main.rs

1
Cargo.toml

@ -18,3 +18,4 @@ serde = { version = "1.0.139", features = ["derive"] } @@ -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"

35
src/command.rs

@ -18,6 +18,11 @@ pub enum Cargo { @@ -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
@ -153,6 +158,10 @@ impl CargoCmd { @@ -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());
@ -278,7 +287,7 @@ impl CargoCmd { @@ -278,7 +287,7 @@ 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");
@ -290,9 +299,9 @@ impl CargoCmd { @@ -290,9 +299,9 @@ impl CargoCmd {
// 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(),
_ => (),
}
@ -327,12 +336,12 @@ impl Build { @@ -327,12 +336,12 @@ impl Build {
/// Callback for `cargo 3ds build`.
///
/// This callback handles building the application as a `.3dsx` file.
fn callback(&self, config: &CTRConfig) {
fn callback(&self, config: &CTRConfig, verbose: bool) {
eprintln!("Building smdh: {}", config.path_smdh().display());
build_smdh(config);
build_smdh(config, verbose);
eprintln!("Building 3dsx: {}", config.path_3dsx().display());
build_3dsx(config);
build_3dsx(config, verbose);
}
}
@ -381,12 +390,12 @@ impl Run { @@ -381,12 +390,12 @@ impl Run {
/// Callback for `cargo 3ds run`.
///
/// This callback handles launching the application via `3dslink`.
fn callback(&self, config: &CTRConfig) {
fn callback(&self, config: &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);
link(config, self, verbose);
}
}
@ -394,13 +403,13 @@ impl Test { @@ -394,13 +403,13 @@ impl Test {
/// Callback for `cargo 3ds test`.
///
/// This callback handles launching the application via `3dslink`.
fn callback(&self, config: &CTRConfig) {
fn callback(&self, config: &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)
}
}
}

69
src/lib.rs

@ -3,7 +3,7 @@ pub mod command; @@ -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;
@ -20,8 +20,12 @@ use std::{env, io, process}; @@ -20,8 +20,12 @@ 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();
@ -29,7 +33,7 @@ pub fn run_cargo(cmd: &CargoCmd, message_format: Option<String>) -> (ExitStatus, @@ -29,7 +33,7 @@ pub fn run_cargo(cmd: &CargoCmd, message_format: Option<String>) -> (ExitStatus,
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.
@ -112,6 +116,23 @@ pub fn make_cargo_command(cmd: &CargoCmd, message_format: &Option<String>) -> Co @@ -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(|| {
@ -235,8 +256,9 @@ pub fn get_metadata(messages: &[Message]) -> CTRConfig { @@ -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)
@ -245,7 +267,13 @@ pub fn build_smdh(config: &CTRConfig) { @@ -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");
@ -258,9 +286,9 @@ pub fn build_smdh(config: &CTRConfig) { @@ -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()));
@ -269,7 +297,7 @@ pub fn build_3dsx(config: &CTRConfig) { @@ -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: {}",
@ -278,7 +306,11 @@ pub fn build_3dsx(config: &CTRConfig) { @@ -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())
@ -294,17 +326,20 @@ pub fn build_3dsx(config: &CTRConfig) { @@ -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));

4
src/main.rs

@ -18,11 +18,11 @@ fn main() { @@ -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);
}

Loading…
Cancel
Save