From 542344f5bb32a8593b4d775d351d3f4fc8e55fda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 4 Jul 2024 20:24:37 +0200 Subject: [PATCH] Print command creation and execution location when it fails This should make it quicker to debug command failures. --- src/bootstrap/src/lib.rs | 15 ++++++++++++--- src/bootstrap/src/utils/exec.rs | 8 +++++++- src/tools/build_helper/src/drop_bomb/mod.rs | 4 ++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 4a69068b51e7..10ec7d135f0c 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -937,13 +937,19 @@ impl Build { /// Execute a command and return its output. /// This method should be used for all command executions in bootstrap. + #[track_caller] fn run(&self, command: &mut BootstrapCommand) -> CommandOutput { command.mark_as_executed(); if self.config.dry_run() && !command.run_always { return CommandOutput::default(); } - self.verbose(|| println!("running: {command:?}")); + let created_at = command.get_created_location(); + let executed_at = std::panic::Location::caller(); + + self.verbose(|| { + println!("running: {command:?} (created at {created_at}, executed at {executed_at})") + }); let stdout = command.stdout.stdio(); command.as_command_mut().stdout(stdout); @@ -962,8 +968,11 @@ impl Build { Ok(output) => { writeln!( message, - "\n\nCommand {command:?} did not execute successfully.\ - \nExpected success, got: {}", + r#" +Command {command:?} did not execute successfully. +Expected success, got {} +Created at: {created_at} +Executed at: {executed_at}"#, output.status, ) .unwrap(); diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs index a9291d45f216..38fc0cf70b5c 100644 --- a/src/bootstrap/src/utils/exec.rs +++ b/src/bootstrap/src/utils/exec.rs @@ -160,17 +160,23 @@ impl BootstrapCommand { &mut self.command } - /// Mark the command as being executd, disarming the drop bomb. + /// Mark the command as being executed, disarming the drop bomb. /// If this method is not called before the command is dropped, its drop will panic. pub fn mark_as_executed(&mut self) { self.drop_bomb.defuse(); } + + /// Returns the source code location where this command was created. + pub fn get_created_location(&self) -> std::panic::Location<'static> { + self.drop_bomb.get_created_location() + } } impl From for BootstrapCommand { #[track_caller] fn from(command: Command) -> Self { let program = command.get_program().to_owned(); + Self { command, failure_behavior: BehaviorOnFailure::Exit, diff --git a/src/tools/build_helper/src/drop_bomb/mod.rs b/src/tools/build_helper/src/drop_bomb/mod.rs index 854113a5181a..2dd4a6bee26b 100644 --- a/src/tools/build_helper/src/drop_bomb/mod.rs +++ b/src/tools/build_helper/src/drop_bomb/mod.rs @@ -31,6 +31,10 @@ impl DropBomb { } } + pub fn get_created_location(&self) -> panic::Location<'static> { + self.armed_location + } + /// Defuse the [`DropBomb`]. This will prevent the drop bomb from panicking when dropped. pub fn defuse(&mut self) { self.defused = true;