bootstrap: remap compiler vs non-compiler sources differently

- Map compiler sources (corresponding to `rustc-dev` dist component)
  with `/rustc-dev/{hash}`.
- Map non-compiler sources (corresponding to `rust-src` dist component
  or other non-compiler sources) with `/rustc/{hash}`.

This allows the compiler to have the possibility of opportunistically
reverse the mapping. This is because

- `rust-src` unpacks sources to a path like
  `$sysroot/lib/rustlib/src/rust`, whereas
- `rustc-dev` unpacks sources to a path like
  `$sysroot/lib/rustlib/rustc-src/rust`

(Notice the `src` vs `rustc-src` difference.)
This commit is contained in:
Jieyou Xu 2025-05-30 09:50:06 +08:00
parent e0d014a3df
commit 8976a6ee07
No known key found for this signature in database
GPG key ID: 045B995028EA6AFC
2 changed files with 70 additions and 10 deletions

View file

@ -11,7 +11,7 @@ use crate::utils::build_stamp;
use crate::utils::helpers::{self, LldThreads, check_cfg_arg, linker_args, linker_flags};
use crate::{
BootstrapCommand, CLang, Compiler, Config, DocTests, DryRun, EXTRA_CHECK_CFGS, GitRepo, Mode,
TargetSelection, command, prepare_behaviour_dump_dir, t,
RemapScheme, TargetSelection, command, prepare_behaviour_dump_dir, t,
};
/// Represents flag values in `String` form with whitespace delimiter to pass it to the compiler
@ -920,13 +920,46 @@ impl Builder<'_> {
hostflags.arg(format!("-Ctarget-feature={sign}crt-static"));
}
if let Some(map_to) = self.build.debuginfo_map_to(GitRepo::Rustc) {
let map = format!("{}={}", self.build.src.display(), map_to);
cargo.env("RUSTC_DEBUGINFO_MAP", map);
// `rustc` needs to know the remapping scheme, in order to know how to reverse it (unremap)
// later. Two env vars are set and made available to the compiler
//
// - `CFG_VIRTUAL_RUST_SOURCE_BASE_DIR`: `rust-src` remap scheme (`NonCompiler`)
// - `CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR`: `rustc-dev` remap scheme (`Compiler`)
//
// Keep this scheme in sync with `rustc_metadata::rmeta::decoder`'s
// `try_to_translate_virtual_to_real`.
//
// `RUSTC_DEBUGINFO_MAP` is used to pass through to the underlying rustc
// `--remap-path-prefix`.
match mode {
Mode::Rustc | Mode::Codegen => {
if let Some(ref map_to) =
self.build.debuginfo_map_to(GitRepo::Rustc, RemapScheme::NonCompiler)
{
cargo.env("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR", map_to);
}
// `rustc` needs to know the virtual `/rustc/$hash` we're mapping to,
// in order to opportunistically reverse it later.
cargo.env("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR", map_to);
if let Some(ref map_to) =
self.build.debuginfo_map_to(GitRepo::Rustc, RemapScheme::Compiler)
{
// When building compiler sources, we want to apply the compiler remap scheme.
cargo.env(
"RUSTC_DEBUGINFO_MAP",
format!("{}={}", self.build.src.display(), map_to),
);
cargo.env("CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR", map_to);
}
}
Mode::Std | Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd => {
if let Some(ref map_to) =
self.build.debuginfo_map_to(GitRepo::Rustc, RemapScheme::NonCompiler)
{
cargo.env(
"RUSTC_DEBUGINFO_MAP",
format!("{}={}", self.build.src.display(), map_to),
);
}
}
}
if self.config.rust_remap_debuginfo {

View file

@ -272,6 +272,16 @@ impl Mode {
}
}
/// When `rust.rust_remap_debuginfo` is requested, the compiler needs to know how to
/// opportunistically unremap compiler vs non-compiler sources. We use two schemes,
/// [`RemapScheme::Compiler`] and [`RemapScheme::NonCompiler`].
pub enum RemapScheme {
/// The [`RemapScheme::Compiler`] scheme will remap to `/rustc-dev/{hash}`.
Compiler,
/// The [`RemapScheme::NonCompiler`] scheme will remap to `/rustc/{hash}`.
NonCompiler,
}
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum CLang {
C,
@ -1210,7 +1220,7 @@ Executed at: {executed_at}"#,
})
}
fn debuginfo_map_to(&self, which: GitRepo) -> Option<String> {
fn debuginfo_map_to(&self, which: GitRepo, remap_scheme: RemapScheme) -> Option<String> {
if !self.config.rust_remap_debuginfo {
return None;
}
@ -1218,7 +1228,24 @@ Executed at: {executed_at}"#,
match which {
GitRepo::Rustc => {
let sha = self.rust_sha().unwrap_or(&self.version);
Some(format!("/rustc/{sha}"))
match remap_scheme {
RemapScheme::Compiler => {
// For compiler sources, remap via `/rustc-dev/{sha}` to allow
// distinguishing between compiler sources vs library sources, since
// `rustc-dev` dist component places them under
// `$sysroot/lib/rustlib/rustc-src/rust` as opposed to `rust-src`'s
// `$sysroot/lib/rustlib/src/rust`.
//
// Keep this scheme in sync with `rustc_metadata::rmeta::decoder`'s
// `try_to_translate_virtual_to_real`.
Some(format!("/rustc-dev/{sha}"))
}
RemapScheme::NonCompiler => {
// For non-compiler sources, use `/rustc/{sha}` remapping scheme.
Some(format!("/rustc/{sha}"))
}
}
}
GitRepo::Llvm => Some(String::from("/rustc/llvm")),
}
@ -1285,7 +1312,7 @@ Executed at: {executed_at}"#,
base.push("-fno-omit-frame-pointer".into());
}
if let Some(map_to) = self.debuginfo_map_to(which) {
if let Some(map_to) = self.debuginfo_map_to(which, RemapScheme::NonCompiler) {
let map = format!("{}={}", self.src.display(), map_to);
let cc = self.cc(target);
if cc.ends_with("clang") || cc.ends_with("gcc") {