Skip to content

Commit cd1d41e

Browse files
Rollup merge of #158562 - Kobzol:bootstrap-tracing-step-caller, r=jieyouxu
Improve tracing of steps in bootstrap Found this useful while debugging #158299. r? @jieyouxu
2 parents 912d8f2 + ee4ea97 commit cd1d41e

3 files changed

Lines changed: 54 additions & 19 deletions

File tree

src/bootstrap/src/core/builder/mod.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1150,6 +1150,7 @@ impl<'a> Builder<'a> {
11501150
/// compiler will run on, *not* the target it will build code for). Explicitly does not take
11511151
/// `Compiler` since all `Compiler` instances are meant to be obtained through this function,
11521152
/// since it ensures that they are valid (i.e., built and assembled).
1153+
#[track_caller]
11531154
#[cfg_attr(
11541155
feature = "tracing",
11551156
instrument(
@@ -1183,6 +1184,7 @@ impl<'a> Builder<'a> {
11831184
///
11841185
/// However, without this optimization, we would also build stage 2 rustc for **target1**,
11851186
/// which is completely wasteful.
1187+
#[track_caller]
11861188
pub fn compiler_for_std(&self, stage: u32) -> Compiler {
11871189
if compile::Std::should_be_uplifted_from_stage_1(self, stage) {
11881190
self.compiler(1, self.host_target)
@@ -1202,6 +1204,7 @@ impl<'a> Builder<'a> {
12021204
/// sysroot.
12031205
///
12041206
/// See `force_use_stage1` and `force_use_stage2` for documentation on what each argument is.
1207+
#[track_caller]
12051208
#[cfg_attr(
12061209
feature = "tracing",
12071210
instrument(
@@ -1249,6 +1252,7 @@ impl<'a> Builder<'a> {
12491252
/// Prefer using this method rather than manually invoking `Std::new`.
12501253
///
12511254
/// Returns an optional build stamp, if libstd was indeed built.
1255+
#[track_caller]
12521256
#[cfg_attr(
12531257
feature = "tracing",
12541258
instrument(
@@ -1297,17 +1301,20 @@ Alternatively, you can set `build.local-rebuild=true` and use a stage0 compiler
12971301
}
12981302
}
12991303

1304+
#[track_caller]
13001305
pub fn sysroot(&self, compiler: Compiler) -> PathBuf {
13011306
self.ensure(compile::Sysroot::new(compiler))
13021307
}
13031308

13041309
/// Returns the bindir for a compiler's sysroot.
1310+
#[track_caller]
13051311
pub fn sysroot_target_bindir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf {
13061312
self.ensure(Libdir { compiler, target }).join(target).join("bin")
13071313
}
13081314

13091315
/// Returns the libdir where the standard library and other artifacts are
13101316
/// found for a compiler's sysroot.
1317+
#[track_caller]
13111318
pub fn sysroot_target_libdir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf {
13121319
self.ensure(Libdir { compiler, target }).join(target).join("lib")
13131320
}
@@ -1416,6 +1423,7 @@ Alternatively, you can set `build.local-rebuild=true` and use a stage0 compiler
14161423
/// Returns a path to `Rustdoc` that "belongs" to the `target_compiler`.
14171424
/// It can be either a stage0 rustdoc or a locally built rustdoc that *links* to
14181425
/// `target_compiler`.
1426+
#[track_caller]
14191427
pub fn rustdoc_for_compiler(&self, target_compiler: Compiler) -> PathBuf {
14201428
self.ensure(tool::Rustdoc { target_compiler })
14211429
}
@@ -1532,6 +1540,7 @@ Alternatively, you can set `build.local-rebuild=true` and use a stage0 compiler
15321540
/// Ensure that a given step is built, returning its output. This will
15331541
/// cache the step, so it is safe (and good!) to call this as often as
15341542
/// needed to ensure that all dependencies are built.
1543+
#[track_caller]
15351544
pub fn ensure<S: Step>(&'a self, step: S) -> S::Output {
15361545
{
15371546
let mut stack = self.stack.borrow_mut();
@@ -1589,7 +1598,8 @@ Alternatively, you can set `build.local-rebuild=true` and use a stage0 compiler
15891598
// in the step_name field.
15901599
"step",
15911600
step_name = pretty_step_name::<S>(),
1592-
args = step_debug_args(&step)
1601+
args = step_debug_args(&step),
1602+
location = crate::utils::tracing::format_location(*std::panic::Location::caller())
15931603
);
15941604
span.entered()
15951605
};

src/bootstrap/src/utils/step_graph.rs

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
use std::collections::{HashMap, HashSet};
1+
use std::collections::HashMap;
22
use std::fmt::Debug;
33
use std::io::BufWriter;
4+
use std::panic::Location;
45
use std::path::Path;
56

67
use crate::core::builder::{AnyDebug, Step, pretty_step_name};
78
use crate::t;
9+
use crate::utils::tracing::format_location;
810

911
/// Records the executed steps and their dependencies in a directed graph,
1012
/// which can then be rendered into a DOT file for visualization.
@@ -20,6 +22,7 @@ pub struct StepGraph {
2022
}
2123

2224
impl StepGraph {
25+
#[track_caller]
2326
pub fn register_step_execution<S: Step>(
2427
&mut self,
2528
step: &S,
@@ -57,6 +60,7 @@ impl StepGraph {
5760
}
5861
}
5962

63+
#[track_caller]
6064
pub fn register_cached_step<S: Step>(
6165
&mut self,
6266
step: &S,
@@ -97,12 +101,18 @@ struct Node {
97101
struct NodeHandle(usize);
98102

99103
/// Represents a dependency between two bootstrap steps.
100-
#[derive(PartialEq, Eq, Hash, PartialOrd, Ord)]
101-
struct Edge {
102-
src: NodeHandle,
103-
dst: NodeHandle,
104+
#[derive(Default)]
105+
struct EdgeData {
104106
// Was the corresponding execution of a step cached, or was the step actually executed?
105107
cached: bool,
108+
// Locations from where the step was called
109+
locations: Vec<Location<'static>>,
110+
}
111+
112+
#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone)]
113+
struct EdgeKey {
114+
src: NodeHandle,
115+
dst: NodeHandle,
106116
}
107117

108118
// We could use a library for this, but they either:
@@ -114,8 +124,8 @@ struct Edge {
114124
#[derive(Default)]
115125
struct DotGraph {
116126
nodes: Vec<Node>,
127+
edges: HashMap<EdgeKey, EdgeData>,
117128
/// The `NodeHandle` represents an index within `self.nodes`
118-
edges: HashSet<Edge>,
119129
key_to_index: HashMap<String, NodeHandle>,
120130
}
121131

@@ -127,16 +137,19 @@ impl DotGraph {
127137
handle
128138
}
129139

140+
#[track_caller]
130141
fn add_edge(&mut self, src: NodeHandle, dst: NodeHandle) {
131-
self.edges.insert(Edge { src, dst, cached: false });
142+
let key = EdgeKey { src, dst };
143+
let edge = self.edges.entry(key).or_default();
144+
edge.locations.push(*Location::caller());
132145
}
133146

147+
#[track_caller]
134148
fn add_cached_edge(&mut self, src: NodeHandle, dst: NodeHandle) {
135-
// There's no point in rendering both cached and uncached edge
136-
let uncached = Edge { src, dst, cached: false };
137-
if !self.edges.contains(&uncached) {
138-
self.edges.insert(Edge { src, dst, cached: true });
139-
}
149+
let key = EdgeKey { src, dst };
150+
let edge = self.edges.entry(key).or_default();
151+
edge.cached = true;
152+
edge.locations.push(*Location::caller());
140153
}
141154

142155
fn get_handle_by_key(&self, key: &str) -> Option<NodeHandle> {
@@ -157,11 +170,23 @@ impl DotGraph {
157170
)?;
158171
}
159172

160-
let mut edges: Vec<&Edge> = self.edges.iter().collect();
161-
edges.sort();
162-
for edge in edges {
163-
let style = if edge.cached { "dashed" } else { "solid" };
164-
writeln!(file, r#"{} -> {} [style="{style}"]"#, edge.src.0, edge.dst.0)?;
173+
let mut edges: Vec<(&EdgeKey, &EdgeData)> = self.edges.iter().collect();
174+
edges.sort_by_key(|(key, _)| **key);
175+
for (key, data) in edges {
176+
let style = if data.cached { "dashed" } else { "solid" };
177+
let mut locations = data
178+
.locations
179+
.iter()
180+
.map(|location| format_location(*location))
181+
.collect::<Vec<_>>();
182+
locations.sort();
183+
locations.dedup();
184+
let locations = locations.join(", ");
185+
writeln!(
186+
file,
187+
r#"{} -> {} [style="{style}", tooltip="{locations}"]"#,
188+
key.src.0, key.dst.0,
189+
)?;
165190
}
166191

167192
writeln!(file, "}}")

src/bootstrap/src/utils/tracing.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ mod inner {
351351
let field = &values.fields[0];
352352
write!(writer, " {{{}}}", field.1)?;
353353
}
354-
write_location(writer, span.metadata())?;
354+
write_with_location(writer)?;
355355
}
356356
// Executed command
357357
COMMAND_SPAN_TARGET => {

0 commit comments

Comments
 (0)