Skip to content

Commit 5775c18

Browse files
committed
Print command creation and execution location when it fails
This should make it quicker to debug command failures.
1 parent cdadff7 commit 5775c18

File tree

3 files changed

+27
-12
lines changed

3 files changed

+27
-12
lines changed

src/bootstrap/src/lib.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -937,13 +937,19 @@ impl Build {
937937

938938
/// Execute a command and return its output.
939939
/// This method should be used for all command executions in bootstrap.
940+
#[track_caller]
940941
fn run(&self, command: &mut BootstrapCommand) -> CommandOutput {
941942
command.mark_as_executed();
942943
if self.config.dry_run() && !command.run_always {
943944
return CommandOutput::default();
944945
}
945946

946-
self.verbose(|| println!("running: {command:?}"));
947+
let created_at = command.get_created_location();
948+
let executed_at = std::panic::Location::caller();
949+
950+
self.verbose(|| {
951+
println!("running: {command:?} (created at {created_at}, executed at {executed_at})")
952+
});
947953

948954
let stdout = command.stdout.stdio();
949955
command.as_command_mut().stdout(stdout);
@@ -962,8 +968,11 @@ impl Build {
962968
Ok(output) => {
963969
writeln!(
964970
message,
965-
"\n\nCommand {command:?} did not execute successfully.\
966-
\nExpected success, got: {}",
971+
r#"
972+
Command {command:?} did not execute successfully.
973+
Expected success, got {}
974+
Created at: {created_at}
975+
Executed at: {executed_at}"#,
967976
output.status,
968977
)
969978
.unwrap();

src/bootstrap/src/utils/exec.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,24 +160,31 @@ impl BootstrapCommand {
160160
&mut self.command
161161
}
162162

163-
/// Mark the command as being executd, disarming the drop bomb.
163+
/// Mark the command as being executed, disarming the drop bomb.
164164
/// If this method is not called before the command is dropped, its drop will panic.
165165
pub fn mark_as_executed(&mut self) {
166166
self.drop_bomb.defuse();
167167
}
168+
169+
/// Returns the source code location where this command was created.
170+
pub fn get_created_location(&self) -> std::panic::Location<'static> {
171+
self.drop_bomb.get_created_location()
172+
}
168173
}
169174

170175
impl From<Command> for BootstrapCommand {
171176
#[track_caller]
172177
fn from(command: Command) -> Self {
173178
let program = command.get_program().to_owned();
179+
let created_at = std::panic::Location::caller();
180+
174181
Self {
175182
command,
176183
failure_behavior: BehaviorOnFailure::Exit,
177184
stdout: OutputMode::Print,
178185
stderr: OutputMode::Print,
179186
run_always: false,
180-
drop_bomb: DropBomb::arm(program),
187+
drop_bomb: DropBomb::arm(program, *created_at),
181188
}
182189
}
183190
}

src/tools/build_helper/src/drop_bomb/mod.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,12 @@ impl DropBomb {
2222
/// Arm a [`DropBomb`]. If the value is dropped without being [`defused`][Self::defused], then
2323
/// it will panic. It is expected that the command wrapper uses `#[track_caller]` to help
2424
/// propagate the caller location.
25-
#[track_caller]
26-
pub fn arm<S: AsRef<OsStr>>(command: S) -> DropBomb {
27-
DropBomb {
28-
command: command.as_ref().into(),
29-
defused: false,
30-
armed_location: *panic::Location::caller(),
31-
}
25+
pub fn arm<S: AsRef<OsStr>>(command: S, armed_location: panic::Location<'static>) -> DropBomb {
26+
DropBomb { command: command.as_ref().into(), defused: false, armed_location }
27+
}
28+
29+
pub fn get_created_location(&self) -> panic::Location<'static> {
30+
self.armed_location
3231
}
3332

3433
/// Defuse the [`DropBomb`]. This will prevent the drop bomb from panicking when dropped.

0 commit comments

Comments
 (0)