Rollup merge of #137080 - jieyouxu:more-tracing, r=onur-ozkan

bootstrap: add more tracing to compiler/std/llvm flows

- Add more tracing to compiler/std/llvm flows.
- Two drive-by nits:
    1. Take `TargetSelection` by-value for `builder.is_builder_target()`. Noticed while adding tracing; follow-up to #136767.
    2. Coalesce enzyme build logic into one branch.
- Document `COMPILER{,_FOR}` tracing targets for #96176.
- No functional changes.

### Testing

You can play with the tracing locally with:

```
$ BOOTSTRAP_TRACING=bootstrap=debug ./x build library
$ BOOTSTRAP_TRACING=bootstrap=trace ./x build library
$ BOOTSTRAP_TRACING=bootstrap=trace,COMPILER=trace,COMPILER_FOR=trace ./x build library
```

### Previews

```
$ BOOTSTRAP_TRACING=bootstrap=debug ./x build library
```

![Screenshot 2025-02-15 230824](https://github.com/user-attachments/assets/c3b02b62-d52e-4c03-a00a-da0d95618989)

```
$ BOOTSTRAP_TRACING=bootstrap=trace,COMPILER=trace,COMPILER_FOR=trace ./x build library
```

![Screenshot 2025-02-15 233859](https://github.com/user-attachments/assets/842e4ece-4c26-4191-acbb-5f93e42de4dc)

r? ``@onur-ozkan`` (or reroll)
This commit is contained in:
Matthias Krüger 2025-02-17 06:37:37 +01:00 committed by GitHub
commit 5dd48bce7c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 340 additions and 31 deletions

View file

@ -16,6 +16,8 @@ use std::process::Stdio;
use std::{env, fs, str};
use serde_derive::Deserialize;
#[cfg(feature = "tracing")]
use tracing::{instrument, span};
use crate::core::build_steps::tool::SourceType;
use crate::core::build_steps::{dist, llvm};
@ -30,7 +32,7 @@ use crate::utils::exec::command;
use crate::utils::helpers::{
exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date,
};
use crate::{CLang, Compiler, DependencyType, GitRepo, LLVM_TOOLS, Mode};
use crate::{CLang, Compiler, DependencyType, GitRepo, LLVM_TOOLS, Mode, debug, trace};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Std {
@ -98,6 +100,7 @@ impl Step for Std {
run.crate_or_deps("sysroot").path("library")
}
#[cfg_attr(feature = "tracing", instrument(level = "trace", name = "Std::make_run", skip_all))]
fn make_run(run: RunConfig<'_>) {
let crates = std_crates_for_run_make(&run);
let builder = run.builder;
@ -109,6 +112,14 @@ impl Step for Std {
&& builder.download_rustc()
&& builder.config.last_modified_commit(&["library"], "download-rustc", true).is_none();
trace!("is managed git repo: {}", builder.rust_info().is_managed_git_subrepository());
trace!("download_rustc: {}", builder.download_rustc());
trace!(
"last modified commit: {:?}",
builder.config.last_modified_commit(&["library"], "download-rustc", true)
);
trace!(force_recompile);
run.builder.ensure(Std {
compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
target: run.target,
@ -124,13 +135,26 @@ impl Step for Std {
/// This will build the standard library for a particular stage of the build
/// using the `compiler` targeting the `target` architecture. The artifacts
/// created will also be linked into the sysroot directory.
#[cfg_attr(
feature = "tracing",
instrument(
level = "debug",
name = "Std::run",
skip_all,
fields(
target = ?self.target,
compiler = ?self.compiler,
force_recompile = self.force_recompile
),
),
)]
fn run(self, builder: &Builder<'_>) {
let target = self.target;
let compiler = self.compiler;
// When using `download-rustc`, we already have artifacts for the host available. Don't
// recompile them.
if builder.download_rustc() && target == builder.build.build
if builder.download_rustc() && builder.is_builder_target(target)
// NOTE: the beta compiler may generate different artifacts than the downloaded compiler, so
// its artifacts can't be reused.
&& compiler.stage != 0
@ -148,6 +172,9 @@ impl Step for Std {
if builder.config.keep_stage.contains(&compiler.stage)
|| builder.config.keep_stage_std.contains(&compiler.stage)
{
trace!(keep_stage = ?builder.config.keep_stage);
trace!(keep_stage_std = ?builder.config.keep_stage_std);
builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
builder.ensure(StartupObjects { compiler, target });
@ -163,7 +190,15 @@ impl Step for Std {
let mut target_deps = builder.ensure(StartupObjects { compiler, target });
let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
trace!(?compiler_to_use);
if compiler_to_use != compiler {
trace!(
?compiler_to_use,
?compiler,
"compiler != compiler_to_use, handling cross-compile scenario"
);
builder.ensure(Std::new(compiler_to_use, target));
let msg = if compiler_to_use.host == target {
format!(
@ -186,12 +221,21 @@ impl Step for Std {
return;
}
trace!(
?compiler_to_use,
?compiler,
"compiler == compiler_to_use, handling not-cross-compile scenario"
);
target_deps.extend(self.copy_extra_objects(builder, &compiler, target));
// The LLD wrappers and `rust-lld` are self-contained linking components that can be
// necessary to link the stdlib on some targets. We'll also need to copy these binaries to
// the `stage0-sysroot` to ensure the linker is found when bootstrapping on such a target.
if compiler.stage == 0 && builder.is_builder_target(&compiler.host) {
if compiler.stage == 0 && builder.is_builder_target(compiler.host) {
trace!(
"(build == host) copying linking components to `stage0-sysroot` for bootstrapping"
);
// We want to copy the host `bin` folder within the `rustlib` folder in the sysroot.
let src_sysroot_bin = builder
.rustc_snapshot_sysroot()
@ -210,6 +254,7 @@ impl Step for Std {
// with -Zalways-encode-mir. This frees us from the need to have a target linker, and the
// fact that this is a check build integrates nicely with run_cargo.
let mut cargo = if self.is_for_mir_opt_tests {
trace!("building special sysroot for mir-opt tests");
let mut cargo = builder::Cargo::new_for_mir_opt_tests(
builder,
compiler,
@ -222,6 +267,7 @@ impl Step for Std {
cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
cargo
} else {
trace!("building regular sysroot");
let mut cargo = builder::Cargo::new(
builder,
compiler,
@ -665,6 +711,19 @@ impl Step for StdLink {
/// Note that this assumes that `compiler` has already generated the libstd
/// libraries for `target`, and this method will find them in the relevant
/// output directory.
#[cfg_attr(
feature = "tracing",
instrument(
level = "trace",
name = "StdLink::run",
skip_all,
fields(
compiler = ?self.compiler,
target_compiler = ?self.target_compiler,
target = ?self.target
),
),
)]
fn run(self, builder: &Builder<'_>) {
let compiler = self.compiler;
let target_compiler = self.target_compiler;
@ -822,6 +881,15 @@ impl Step for StartupObjects {
/// They don't require any library support as they're just plain old object
/// files, so we just use the nightly snapshot compiler to always build them (as
/// no other compilers are guaranteed to be available).
#[cfg_attr(
feature = "tracing",
instrument(
level = "trace",
name = "StartupObjects::run",
skip_all,
fields(compiler = ?self.compiler, target = ?self.target),
),
)]
fn run(self, builder: &Builder<'_>) -> Vec<(PathBuf, DependencyType)> {
let for_compiler = self.compiler;
let target = self.target;
@ -936,6 +1004,15 @@ impl Step for Rustc {
/// This will build the compiler for a particular stage of the build using
/// the `compiler` targeting the `target` architecture. The artifacts
/// created will also be linked into the sysroot directory.
#[cfg_attr(
feature = "tracing",
instrument(
level = "debug",
name = "Rustc::run",
skip_all,
fields(previous_compiler = ?self.compiler, target = ?self.target),
),
)]
fn run(self, builder: &Builder<'_>) -> u32 {
let compiler = self.compiler;
let target = self.target;
@ -943,6 +1020,8 @@ impl Step for Rustc {
// NOTE: the ABI of the beta compiler is different from the ABI of the downloaded compiler,
// so its artifacts can't be reused.
if builder.download_rustc() && compiler.stage != 0 {
trace!(stage = compiler.stage, "`download_rustc` requested");
let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
cp_rustc_component_to_ci_sysroot(
builder,
@ -955,6 +1034,8 @@ impl Step for Rustc {
builder.ensure(Std::new(compiler, target));
if builder.config.keep_stage.contains(&compiler.stage) {
trace!(stage = compiler.stage, "`keep-stage` requested");
builder.info("WARNING: Using a potentially old librustc. This may not behave well.");
builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes");
builder.ensure(RustcLink::from_rustc(self, compiler));
@ -1374,6 +1455,19 @@ impl Step for RustcLink {
}
/// Same as `std_link`, only for librustc
#[cfg_attr(
feature = "tracing",
instrument(
level = "trace",
name = "RustcLink::run",
skip_all,
fields(
compiler = ?self.compiler,
previous_stage_compiler = ?self.previous_stage_compiler,
target = ?self.target,
),
),
)]
fn run(self, builder: &Builder<'_>) {
let compiler = self.compiler;
let previous_stage_compiler = self.previous_stage_compiler;
@ -1462,6 +1556,19 @@ impl Step for CodegenBackend {
}
}
#[cfg_attr(
feature = "tracing",
instrument(
level = "debug",
name = "CodegenBackend::run",
skip_all,
fields(
compiler = ?self.compiler,
target = ?self.target,
backend = ?self.target,
),
),
)]
fn run(self, builder: &Builder<'_>) {
let compiler = self.compiler;
let target = self.target;
@ -1470,6 +1577,7 @@ impl Step for CodegenBackend {
builder.ensure(Rustc::new(compiler, target));
if builder.config.keep_stage.contains(&compiler.stage) {
trace!("`keep-stage` requested");
builder.info(
"WARNING: Using a potentially old codegen backend. \
This may not behave well.",
@ -1617,6 +1725,15 @@ impl Step for Sysroot {
/// Returns the sysroot that `compiler` is supposed to use.
/// For the stage0 compiler, this is stage0-sysroot (because of the initial std build).
/// For all other stages, it's the same stage directory that the compiler lives in.
#[cfg_attr(
feature = "tracing",
instrument(
level = "debug",
name = "Sysroot::run",
skip_all,
fields(compiler = ?self.compiler),
),
)]
fn run(self, builder: &Builder<'_>) -> PathBuf {
let compiler = self.compiler;
let host_dir = builder.out.join(compiler.host);
@ -1633,6 +1750,7 @@ impl Step for Sysroot {
}
};
let sysroot = sysroot_dir(compiler.stage);
trace!(stage = ?compiler.stage, ?sysroot);
builder
.verbose(|| println!("Removing sysroot {} to avoid caching bugs", sysroot.display()));
@ -1787,10 +1905,20 @@ impl Step for Assemble {
/// This will assemble a compiler in `build/$host/stage$stage`. The compiler
/// must have been previously produced by the `stage - 1` builder.build
/// compiler.
#[cfg_attr(
feature = "tracing",
instrument(
level = "debug",
name = "Assemble::run",
skip_all,
fields(target_compiler = ?self.target_compiler),
),
)]
fn run(self, builder: &Builder<'_>) -> Compiler {
let target_compiler = self.target_compiler;
if target_compiler.stage == 0 {
trace!("stage 0 build compiler is always available, simply returning");
assert_eq!(
builder.config.build, target_compiler.host,
"Cannot obtain compiler for non-native build triple at stage 0"
@ -1806,9 +1934,13 @@ impl Step for Assemble {
t!(fs::create_dir_all(&libdir_bin));
if builder.config.llvm_enabled(target_compiler.host) {
trace!("target_compiler.host" = ?target_compiler.host, "LLVM enabled");
let llvm::LlvmResult { llvm_config, .. } =
builder.ensure(llvm::Llvm { target: target_compiler.host });
if !builder.config.dry_run() && builder.config.llvm_tools_enabled {
trace!("LLVM tools enabled");
let llvm_bin_dir =
command(llvm_config).arg("--bindir").run_capture_stdout(builder).stdout();
let llvm_bin_dir = Path::new(llvm_bin_dir.trim());
@ -1818,7 +1950,13 @@ impl Step for Assemble {
// rustup, and lets developers use a locally built toolchain to
// build projects that expect llvm tools to be present in the sysroot
// (e.g. the `bootimage` crate).
#[cfg(feature = "tracing")]
let _llvm_tools_span =
span!(tracing::Level::TRACE, "installing llvm tools to sysroot", ?libdir_bin)
.entered();
for tool in LLVM_TOOLS {
trace!("installing `{tool}`");
let tool_exe = exe(tool, target_compiler.host);
let src_path = llvm_bin_dir.join(&tool_exe);
// When using `download-ci-llvm`, some of the tools
@ -1838,6 +1976,7 @@ impl Step for Assemble {
let maybe_install_llvm_bitcode_linker = |compiler| {
if builder.config.llvm_bitcode_linker_enabled {
trace!("llvm-bitcode-linker enabled, installing");
let src_path = builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker {
compiler,
target: target_compiler.host,
@ -1850,6 +1989,8 @@ impl Step for Assemble {
// If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0.
if builder.download_rustc() {
trace!("`download-rustc` requested, reusing CI compiler for stage > 0");
builder.ensure(Std::new(target_compiler, target_compiler.host));
let sysroot =
builder.ensure(Sysroot { compiler: target_compiler, force_recompile: false });
@ -1879,16 +2020,17 @@ impl Step for Assemble {
//
// FIXME: It may be faster if we build just a stage 1 compiler and then
// use that to bootstrap this compiler forward.
debug!(
"ensuring build compiler is available: compiler(stage = {}, host = {:?})",
target_compiler.stage - 1,
builder.config.build,
);
let mut build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build);
// Build enzyme
let enzyme_install = if builder.config.llvm_enzyme {
Some(builder.ensure(llvm::Enzyme { target: build_compiler.host }))
} else {
None
};
if let Some(enzyme_install) = enzyme_install {
if builder.config.llvm_enzyme {
debug!("`llvm_enzyme` requested");
let enzyme_install = builder.ensure(llvm::Enzyme { target: build_compiler.host });
let lib_ext = std::env::consts::DLL_EXTENSION;
let src_lib = enzyme_install.join("build/Enzyme/libEnzyme-19").with_extension(lib_ext);
let libdir = builder.sysroot_target_libdir(build_compiler, build_compiler.host);
@ -1905,13 +2047,27 @@ impl Step for Assemble {
// link to these. (FIXME: Is that correct? It seems to be correct most
// of the time but I think we do link to these for stage2/bin compilers
// when not performing a full bootstrap).
debug!(
?build_compiler,
"target_compiler.host" = ?target_compiler.host,
"building compiler libraries to link to"
);
let actual_stage = builder.ensure(Rustc::new(build_compiler, target_compiler.host));
// Current build_compiler.stage might be uplifted instead of being built; so update it
// to not fail while linking the artifacts.
debug!(
"(old) build_compiler.stage" = build_compiler.stage,
"(adjusted) build_compiler.stage" = actual_stage,
"temporarily adjusting `build_compiler.stage` to account for uplifted libraries"
);
build_compiler.stage = actual_stage;
#[cfg(feature = "tracing")]
let _codegen_backend_span =
span!(tracing::Level::DEBUG, "building requested codegen backends").entered();
for backend in builder.config.codegen_backends(target_compiler.host) {
if backend == "llvm" {
debug!("llvm codegen backend is already built as part of rustc");
continue; // Already built as part of rustc
}
@ -1921,6 +2077,8 @@ impl Step for Assemble {
backend: backend.clone(),
});
}
#[cfg(feature = "tracing")]
drop(_codegen_backend_span);
let stage = target_compiler.stage;
let host = target_compiler.host;
@ -1980,6 +2138,7 @@ impl Step for Assemble {
}
}
debug!("copying codegen backends to sysroot");
copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
if builder.config.lld_enabled {
@ -1990,6 +2149,11 @@ impl Step for Assemble {
}
if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
debug!(
"llvm and llvm tools enabled; copying `llvm-objcopy` as `rust-objcopy` to \
workaround faulty homebrew `strip`s"
);
// `llvm-strip` is used by rustc, which is actually just a symlink to `llvm-objcopy`, so
// copy and rename `llvm-objcopy`.
//
@ -2022,6 +2186,11 @@ impl Step for Assemble {
// Ensure that `libLLVM.so` ends up in the newly build compiler directory,
// so that it can be found when the newly built `rustc` is run.
debug!(
"target_compiler.host" = ?target_compiler.host,
?sysroot,
"ensuring availability of `libLLVM.so` in compiler directory"
);
dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
dist::maybe_install_llvm_target(builder, target_compiler.host, &sysroot);
@ -2031,6 +2200,7 @@ impl Step for Assemble {
let bindir = sysroot.join("bin");
t!(fs::create_dir_all(bindir));
let compiler = builder.rustc(target_compiler);
debug!(src = ?rustc, dst = ?compiler, "linking compiler binary itself");
builder.copy_link(&rustc, &compiler);
target_compiler
@ -2315,7 +2485,7 @@ pub fn strip_debug(builder: &Builder<'_>, target: TargetSelection, path: &Path)
// FIXME: to make things simpler for now, limit this to the host and target where we know
// `strip -g` is both available and will fix the issue, i.e. on a x64 linux host that is not
// cross-compiling. Expand this to other appropriate targets in the future.
if target != "x86_64-unknown-linux-gnu" || !builder.is_builder_target(&target) || !path.exists()
if target != "x86_64-unknown-linux-gnu" || !builder.is_builder_target(target) || !path.exists()
{
return;
}

View file

@ -16,6 +16,8 @@ use std::{env, fs};
use object::BinaryFormat;
use object::read::archive::ArchiveFile;
#[cfg(feature = "tracing")]
use tracing::instrument;
use crate::core::build_steps::doc::DocumentationFormat;
use crate::core::build_steps::tool::{self, Tool};
@ -30,7 +32,7 @@ use crate::utils::helpers::{
exe, is_dylib, move_file, t, target_supports_cranelift_backend, timeit,
};
use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
use crate::{Compiler, DependencyType, LLVM_TOOLS, Mode};
use crate::{Compiler, DependencyType, LLVM_TOOLS, Mode, trace};
pub fn pkgname(builder: &Builder<'_>, component: &str) -> String {
format!("{}-{}", component, builder.rust_package_vers())
@ -582,7 +584,7 @@ impl Step for DebuggerScripts {
fn skip_host_target_lib(builder: &Builder<'_>, compiler: Compiler) -> bool {
// The only true set of target libraries came from the build triple, so
// let's reduce redundant work by only producing archives from that host.
if !builder.is_builder_target(&compiler.host) {
if !builder.is_builder_target(compiler.host) {
builder.info("\tskipping, not a build host");
true
} else {
@ -637,7 +639,7 @@ fn copy_target_libs(
for (path, dependency_type) in builder.read_stamp_file(stamp) {
if dependency_type == DependencyType::TargetSelfContained {
builder.copy_link(&path, &self_contained_dst.join(path.file_name().unwrap()));
} else if dependency_type == DependencyType::Target || builder.is_builder_target(&target) {
} else if dependency_type == DependencyType::Target || builder.is_builder_target(target) {
builder.copy_link(&path, &dst.join(path.file_name().unwrap()));
}
}
@ -786,7 +788,7 @@ impl Step for Analysis {
fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
let compiler = self.compiler;
let target = self.target;
if !builder.is_builder_target(&compiler.host) {
if !builder.is_builder_target(compiler.host) {
return None;
}
@ -2029,6 +2031,15 @@ fn install_llvm_file(
/// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking.
///
/// Returns whether the files were actually copied.
#[cfg_attr(
feature = "tracing",
instrument(
level = "trace",
name = "maybe_install_llvm",
skip_all,
fields(target = ?target, dst_libdir = ?dst_libdir, install_symlink = install_symlink),
),
)]
fn maybe_install_llvm(
builder: &Builder<'_>,
target: TargetSelection,
@ -2052,6 +2063,7 @@ fn maybe_install_llvm(
// If the LLVM is coming from ourselves (just from CI) though, we
// still want to install it, as it otherwise won't be available.
if builder.is_system_llvm(target) {
trace!("system LLVM requested, no install");
return false;
}
@ -2070,6 +2082,7 @@ fn maybe_install_llvm(
} else if let llvm::LlvmBuildStatus::AlreadyBuilt(llvm::LlvmResult { llvm_config, .. }) =
llvm::prebuilt_llvm_config(builder, target, true)
{
trace!("LLVM already built, installing LLVM files");
let mut cmd = command(llvm_config);
cmd.arg("--libfiles");
builder.verbose(|| println!("running {cmd:?}"));
@ -2092,6 +2105,19 @@ fn maybe_install_llvm(
}
/// Maybe add libLLVM.so to the target lib-dir for linking.
#[cfg_attr(
feature = "tracing",
instrument(
level = "trace",
name = "maybe_install_llvm_target",
skip_all,
fields(
llvm_link_shared = ?builder.llvm_link_shared(),
target = ?target,
sysroot = ?sysroot,
),
),
)]
pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
let dst_libdir = sysroot.join("lib/rustlib").join(target).join("lib");
// We do not need to copy LLVM files into the sysroot if it is not
@ -2103,6 +2129,19 @@ pub fn maybe_install_llvm_target(builder: &Builder<'_>, target: TargetSelection,
}
/// Maybe add libLLVM.so to the runtime lib-dir for rustc itself.
#[cfg_attr(
feature = "tracing",
instrument(
level = "trace",
name = "maybe_install_llvm_runtime",
skip_all,
fields(
llvm_link_shared = ?builder.llvm_link_shared(),
target = ?target,
sysroot = ?sysroot,
),
),
)]
pub fn maybe_install_llvm_runtime(builder: &Builder<'_>, target: TargetSelection, sysroot: &Path) {
let dst_libdir =
sysroot.join(builder.sysroot_libdir_relative(Compiler { stage: 1, host: target }));

View file

@ -16,6 +16,8 @@ use std::{env, fs};
use build_helper::ci::CiEnv;
use build_helper::git::get_closest_merge_commit;
#[cfg(feature = "tracing")]
use tracing::instrument;
use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
use crate::core::config::{Config, TargetSelection};
@ -24,7 +26,7 @@ use crate::utils::exec::command;
use crate::utils::helpers::{
self, exe, get_clang_cl_resource_dir, t, unhashed_basename, up_to_date,
};
use crate::{CLang, GitRepo, Kind};
use crate::{CLang, GitRepo, Kind, trace};
#[derive(Clone)]
pub struct LlvmResult {
@ -516,7 +518,7 @@ impl Step for Llvm {
}
// https://llvm.org/docs/HowToCrossCompileLLVM.html
if !builder.is_builder_target(&target) {
if !builder.is_builder_target(target) {
let LlvmResult { llvm_config, .. } =
builder.ensure(Llvm { target: builder.config.build });
if !builder.config.dry_run() {
@ -668,7 +670,7 @@ fn configure_cmake(
}
cfg.target(&target.triple).host(&builder.config.build.triple);
if !builder.is_builder_target(&target) {
if !builder.is_builder_target(target) {
cfg.define("CMAKE_CROSSCOMPILING", "True");
if target.contains("netbsd") {
@ -934,6 +936,15 @@ impl Step for Enzyme {
}
/// Compile Enzyme for `target`.
#[cfg_attr(
feature = "tracing",
instrument(
level = "debug",
name = "Enzyme::run",
skip_all,
fields(target = ?self.target),
),
)]
fn run(self, builder: &Builder<'_>) -> PathBuf {
builder.require_submodule(
"src/tools/enzyme",
@ -959,7 +970,9 @@ impl Step for Enzyme {
let out_dir = builder.enzyme_out(target);
let stamp = BuildStamp::new(&out_dir).with_prefix("enzyme").add_stamp(smart_stamp_hash);
trace!("checking build stamp to see if we need to rebuild enzyme artifacts");
if stamp.is_up_to_date() {
trace!(?out_dir, "enzyme build artifacts are up to date");
if stamp.stamp().is_empty() {
builder.info(
"Could not determine the Enzyme submodule commit hash. \
@ -973,6 +986,7 @@ impl Step for Enzyme {
return out_dir;
}
trace!(?target, "(re)building enzyme artifacts");
builder.info(&format!("Building Enzyme for {}", target));
t!(stamp.remove());
let _time = helpers::timeit(builder);
@ -994,6 +1008,7 @@ impl Step for Enzyme {
(true, false) => "Release",
(true, true) => "RelWithDebInfo",
};
trace!(?profile);
cfg.out_dir(&out_dir)
.profile(profile)
@ -1118,7 +1133,7 @@ impl Step for Lld {
.define("LLVM_CMAKE_DIR", llvm_cmake_dir)
.define("LLVM_INCLUDE_TESTS", "OFF");
if !builder.is_builder_target(&target) {
if !builder.is_builder_target(target) {
// Use the host llvm-tblgen binary.
cfg.define(
"LLVM_TABLEGEN_EXE",

View file

@ -2743,7 +2743,7 @@ impl Step for Crate {
cargo
} else {
// Also prepare a sysroot for the target.
if !builder.is_builder_target(&target) {
if !builder.is_builder_target(target) {
builder.ensure(compile::Std::new(compiler, target).force_recompile(true));
builder.ensure(RemoteCopyLibs { compiler, target });
}

View file

@ -1,6 +1,9 @@
use std::path::PathBuf;
use std::{env, fs};
#[cfg(feature = "tracing")]
use tracing::instrument;
use crate::core::build_steps::compile::is_lto_stage;
use crate::core::build_steps::toolstate::ToolState;
use crate::core::build_steps::{compile, llvm};
@ -304,6 +307,14 @@ macro_rules! bootstrap_tool {
});
}
#[cfg_attr(
feature = "tracing",
instrument(
level = "debug",
name = $tool_name,
skip_all,
),
)]
fn run(self, builder: &Builder<'_>) -> PathBuf {
$(
for submodule in $submodules {
@ -758,6 +769,15 @@ impl Step for LldWrapper {
run.never()
}
#[cfg_attr(
feature = "tracing",
instrument(
level = "debug",
name = "LldWrapper::run",
skip_all,
fields(build_compiler = ?self.build_compiler, target_compiler = ?self.target_compiler),
),
)]
fn run(self, builder: &Builder<'_>) {
if builder.config.dry_run() {
return;
@ -914,6 +934,10 @@ impl Step for LlvmBitcodeLinker {
});
}
#[cfg_attr(
feature = "tracing",
instrument(level = "debug", name = "LlvmBitcodeLinker::run", skip_all)
)]
fn run(self, builder: &Builder<'_>) -> PathBuf {
let bin_name = "llvm-bitcode-linker";

View file

@ -10,6 +10,8 @@ use std::time::{Duration, Instant};
use std::{env, fs};
use clap::ValueEnum;
#[cfg(feature = "tracing")]
use tracing::instrument;
pub use self::cargo::{Cargo, cargo_profile_var};
pub use crate::Compiler;
@ -21,7 +23,7 @@ use crate::core::config::{DryRun, TargetSelection};
use crate::utils::cache::Cache;
use crate::utils::exec::{BootstrapCommand, command};
use crate::utils::helpers::{self, LldThreads, add_dylib_path, exe, libdir, linker_args, t};
use crate::{Build, Crate};
use crate::{Build, Crate, trace};
mod cargo;
@ -1218,6 +1220,19 @@ impl<'a> Builder<'a> {
/// compiler will run on, *not* the target it will build code for). Explicitly does not take
/// `Compiler` since all `Compiler` instances are meant to be obtained through this function,
/// since it ensures that they are valid (i.e., built and assembled).
#[cfg_attr(
feature = "tracing",
instrument(
level = "trace",
name = "Builder::compiler",
target = "COMPILER",
skip_all,
fields(
stage = stage,
host = ?host,
),
),
)]
pub fn compiler(&self, stage: u32, host: TargetSelection) -> Compiler {
self.ensure(compile::Assemble { target_compiler: Compiler { stage, host } })
}
@ -1233,19 +1248,39 @@ impl<'a> Builder<'a> {
/// sysroot.
///
/// See `force_use_stage1` and `force_use_stage2` for documentation on what each argument is.
#[cfg_attr(
feature = "tracing",
instrument(
level = "trace",
name = "Builder::compiler_for",
target = "COMPILER_FOR",
skip_all,
fields(
stage = stage,
host = ?host,
target = ?target,
),
),
)]
pub fn compiler_for(
&self,
stage: u32,
host: TargetSelection,
target: TargetSelection,
) -> Compiler {
if self.build.force_use_stage2(stage) {
#![allow(clippy::let_and_return)]
let resolved_compiler = if self.build.force_use_stage2(stage) {
trace!(target: "COMPILER_FOR", ?stage, "force_use_stage2");
self.compiler(2, self.config.build)
} else if self.build.force_use_stage1(stage, target) {
trace!(target: "COMPILER_FOR", ?stage, "force_use_stage1");
self.compiler(1, self.config.build)
} else {
trace!(target: "COMPILER_FOR", ?stage, ?host, "no force, fallback to `compiler()`");
self.compiler(stage, host)
}
};
trace!(target: "COMPILER_FOR", ?resolved_compiler);
resolved_compiler
}
pub fn sysroot(&self, compiler: Compiler) -> PathBuf {

View file

@ -1080,7 +1080,7 @@ fn test_is_builder_target() {
let build = Build::new(config);
let builder = Builder::new(&build);
assert!(builder.is_builder_target(&target1));
assert!(!builder.is_builder_target(&target2));
assert!(builder.is_builder_target(target1));
assert!(!builder.is_builder_target(target2));
}
}

View file

@ -2747,6 +2747,15 @@ impl Config {
/// tarball). Typically [`crate::Build::require_submodule`] should be
/// used instead to provide a nice error to the user if the submodule is
/// missing.
#[cfg_attr(
feature = "tracing",
instrument(
level = "trace",
name = "Config::update_submodule",
skip_all,
fields(relative_path = ?relative_path),
),
)]
pub(crate) fn update_submodule(&self, relative_path: &str) {
if !self.submodules() {
return;

View file

@ -329,7 +329,7 @@ than building it.
if target.contains("musl") && !target.contains("unikraft") {
// If this is a native target (host is also musl) and no musl-root is given,
// fall back to the system toolchain in /usr before giving up
if build.musl_root(*target).is_none() && build.is_builder_target(target) {
if build.musl_root(*target).is_none() && build.is_builder_target(*target) {
let target = build.config.target_config.entry(*target).or_default();
target.musl_root = Some("/usr".into());
}

View file

@ -469,6 +469,15 @@ impl Build {
///
/// The given `err_hint` will be shown to the user if the submodule is not
/// checked out and submodule management is disabled.
#[cfg_attr(
feature = "tracing",
instrument(
level = "trace",
name = "Build::require_submodule",
skip_all,
fields(submodule = submodule),
),
)]
pub fn require_submodule(&self, submodule: &str, err_hint: Option<&str>) {
// When testing bootstrap itself, it is much faster to ignore
// submodules. Almost all Steps work fine without their submodules.
@ -739,7 +748,7 @@ impl Build {
/// Note that if LLVM is configured externally then the directory returned
/// will likely be empty.
fn llvm_out(&self, target: TargetSelection) -> PathBuf {
if self.config.llvm_from_ci && self.is_builder_target(&target) {
if self.config.llvm_from_ci && self.is_builder_target(target) {
self.config.ci_llvm_root()
} else {
self.out.join(target).join("llvm")
@ -789,7 +798,7 @@ impl Build {
fn is_system_llvm(&self, target: TargetSelection) -> bool {
match self.config.target_config.get(&target) {
Some(Target { llvm_config: Some(_), .. }) => {
let ci_llvm = self.config.llvm_from_ci && self.is_builder_target(&target);
let ci_llvm = self.config.llvm_from_ci && self.is_builder_target(target);
!ci_llvm
}
// We're building from the in-tree src/llvm-project sources.
@ -1277,7 +1286,7 @@ Executed at: {executed_at}"#,
// need to use CXX compiler as linker to resolve the exception functions
// that are only existed in CXX libraries
Some(self.cxx.borrow()[&target].path().into())
} else if !self.is_builder_target(&target)
} else if !self.is_builder_target(target)
&& helpers::use_host_linker(target)
&& !target.is_msvc()
{
@ -1930,8 +1939,8 @@ to download LLVM rather than building it.
}
/// Checks if the given target is the same as the builder target.
fn is_builder_target(&self, target: &TargetSelection) -> bool {
&self.config.build == target
fn is_builder_target(&self, target: TargetSelection) -> bool {
self.config.build == target
}
}

View file

@ -76,6 +76,14 @@ $ BOOTSTRAP_TRACING=CONFIG_HANDLING=TRACE ./x build library --stage 1
[tracing-env-filter]: https://docs.rs/tracing-subscriber/0.3.19/tracing_subscriber/filter/struct.EnvFilter.html
##### FIXME(#96176): specific tracing for `compiler()` vs `compiler_for()`
The additional targets `COMPILER` and `COMPILER_FOR` are used to help trace what
`builder.compiler()` and `builder.compiler_for()` does. They should be removed
if [#96176][cleanup-compiler-for] is resolved.
[cleanup-compiler-for]: https://github.com/rust-lang/rust/issues/96176
### Using `tracing` in bootstrap
Both `tracing::*` macros and the `tracing::instrument` proc-macro attribute need to be gated behind `tracing` feature. Examples: