Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/compiler/build_context/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
//! [`BuildContext`] is a (mostly) static information about a build task.

use std::path::Path;

use crate::compiler::BuildConfig;
use crate::compiler::CompileKind;
use crate::compiler::Unit;
Expand Down Expand Up @@ -162,6 +164,18 @@ impl<'a, 'gctx> BuildContext<'a, 'gctx> {
pub fn extra_args_for(&self, unit: &Unit) -> Option<&Vec<String>> {
self.extra_compiler_args.get(unit)
}

/// Gets the path to the sysroot.
///
/// Helper function that uses GlobalContext.
pub fn get_sysroot(&self) -> &'gctx Path {
// cfg::bad_cfg_discovery tests that these panics aren't reachable
let rustc = self
.gctx
.load_global_rustc(Some(self.ws))
.expect("rustc load ok");
self.gctx.get_sysroot(&rustc).expect("sysroot fetch ok")
}
}

#[derive(Copy, Clone, Default, Debug)]
Expand Down
38 changes: 15 additions & 23 deletions src/compiler/build_context/target_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ pub struct TargetInfo {
pub supports_std: Option<bool>,
/// Supported values for `-Csplit-debuginfo=` flag, queried from rustc
support_split_debuginfo: Vec<String>,
/// Path to the sysroot.
pub sysroot: PathBuf,
Comment thread
epage marked this conversation as resolved.
/// Path to the "lib" directory in the sysroot which rustc uses for linking
/// target libraries.
pub sysroot_target_libdir: PathBuf,
Expand Down Expand Up @@ -165,6 +163,8 @@ impl TargetInfo {
/// invocation is cached by [`Rustc::cached_output`].
///
/// Search `Tricky` to learn why querying `rustc` several times is needed.
///
/// When a Workspace is provided,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably an unfinished comment? (noticed while reading the PR).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💩

I have another small refactor PR which I'll likely ship, and I'll remove this comment in that

#[tracing::instrument(skip_all)]
pub fn new(
gctx: &GlobalContext,
Expand All @@ -174,15 +174,25 @@ impl TargetInfo {
) -> CargoResult<TargetInfo> {
let mut rustflags =
extra_args(gctx, requested_kinds, &rustc.host, None, kind, Flags::Rust)?;

let sysroot = gctx.get_sysroot(rustc)?;
let sysroot_target_libdir = sysroot
.join("lib")
.join("rustlib")
.join(match &kind {
CompileKind::Host => rustc.host.as_str(),
CompileKind::Target(target) => target.short_name(),
})
.join("lib");

let mut turn = 0;
loop {
let extra_fingerprint = kind.fingerprint_hash();

// Query rustc for several kinds of info from each line of output:
// 0) file-names (to determine output file prefix/suffix for given crate type)
// 1) sysroot
// 2) split-debuginfo
// 3) cfg
// 1) split-debuginfo
// 2) cfg
//
// Search `--print` to see what we query so far.
let mut process = rustc.workspace_process();
Expand Down Expand Up @@ -216,7 +226,6 @@ impl TargetInfo {
process.arg("--crate-type").arg(crate_type.as_str());
}

process.arg("--print=sysroot");
process.arg("--print=split-debuginfo");
process.arg("--print=crate-name"); // `___` as a delimiter.
process.arg("--print=cfg");
Expand All @@ -238,22 +247,6 @@ impl TargetInfo {
map.insert(crate_type.clone(), out);
}

let Some(line) = lines.next() else {
return error_missing_print_output("sysroot", &process, &output, &error);
};
let sysroot = PathBuf::from(line);
let sysroot_target_libdir = {
let mut libdir = sysroot.clone();
libdir.push("lib");
libdir.push("rustlib");
libdir.push(match &kind {
CompileKind::Host => rustc.host.as_str(),
CompileKind::Target(target) => target.short_name(),
});
libdir.push("lib");
libdir
};

let support_split_debuginfo = {
// HACK: abuse `--print=crate-name` to use `___` as a delimiter.
let mut res = Vec::new();
Expand Down Expand Up @@ -352,7 +345,6 @@ impl TargetInfo {
return Ok(TargetInfo {
crate_type_process,
crate_types: RefCell::new(map),
sysroot,
sysroot_target_libdir,
rustflags: rustflags.into(),
rustdocflags: extra_args(
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/build_runner/compilation_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,7 @@ fn compute_metadata(
// SourceId for stdlib crates is an absolute path inside the sysroot.
// Pass the sysroot as workspace root so that we hash a relative path.
// This avoids the metadata hash changing depending on where the user installed rustc.
&bcx.target_data.get_info(unit.kind).unwrap().sysroot
&bcx.get_sysroot()
} else {
bcx.ws.root()
};
Expand Down
4 changes: 2 additions & 2 deletions src/compiler/rustdoc.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! Utilities for building with rustdoc.

use crate::compiler::BuildContext;
use crate::compiler::build_runner::BuildRunner;
use crate::compiler::unit::Unit;
use crate::compiler::{BuildContext, CompileKind};
use crate::sources::CRATES_IO_REGISTRY;
use crate::util::data_structures::HashMap;
use crate::util::data_structures::HashSet;
Expand Down Expand Up @@ -208,7 +208,7 @@ pub fn add_root_urls(
let std_url = match &map.std {
None | Some(RustdocExternMode::Remote) => None,
Some(RustdocExternMode::Local) => {
let sysroot = &build_runner.bcx.target_data.info(CompileKind::Host).sysroot;
let sysroot = build_runner.bcx.get_sysroot();
let html_root = sysroot.join("share").join("doc").join("rust").join("html");
if html_root.exists() {
let url = Url::from_file_path(&html_root).map_err(|()| {
Expand Down
16 changes: 9 additions & 7 deletions src/compiler/standard_lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ pub fn resolve_std<'gctx>(
crates: &[String],
kinds: &[CompileKind],
) -> CargoResult<(PackageSet<'gctx>, Resolve, ResolvedFeatures)> {
let src_path = detect_sysroot_src_path(target_data)?;
let src_path = detect_sysroot_src_path(ws)?;
let std_ws_manifest_path = src_path.join("Cargo.toml");
let gctx = ws.gctx();
// TODO: Consider doing something to enforce --locked? Or to prevent the
Expand Down Expand Up @@ -217,15 +217,17 @@ fn generate_roots(
Ok(())
}

fn detect_sysroot_src_path(target_data: &RustcTargetData<'_>) -> CargoResult<PathBuf> {
if let Some(s) = target_data.gctx.get_env_os("__CARGO_TESTS_ONLY_SRC_ROOT") {
fn detect_sysroot_src_path(ws: &Workspace<'_>) -> CargoResult<PathBuf> {
if let Some(s) = ws.gctx().get_env_os("__CARGO_TESTS_ONLY_SRC_ROOT") {
return Ok(s.into());
}

// NOTE: This is temporary until we figure out how to acquire the source.
let src_path = target_data
.info(CompileKind::Host)
.sysroot
let rustc = ws.gctx().load_global_rustc(Some(ws))?;
let src_path = ws
.gctx()
.get_sysroot(&rustc)
.expect("able to invoke rustc")
.join("lib")
.join("rustlib")
.join("src")
Expand All @@ -238,7 +240,7 @@ fn detect_sysroot_src_path(target_data: &RustcTargetData<'_>) -> CargoResult<Pat
library, try:\n rustup component add rust-src",
lock
);
match target_data.gctx.get_env("RUSTUP_TOOLCHAIN") {
match ws.gctx().get_env("RUSTUP_TOOLCHAIN") {
Ok(rustup_toolchain) => {
anyhow::bail!("{} --toolchain {}", msg, rustup_toolchain);
}
Expand Down
18 changes: 9 additions & 9 deletions src/compiler/trim_paths.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,24 +85,24 @@ pub(crate) fn trim_paths_remap(build_runner: &BuildRunner<'_, '_>, unit: &Unit)
[
package_remap(build_runner, unit),
build_dir_remap(build_runner),
sysroot_remap(build_runner, unit),
sysroot_remap(build_runner),
]
}

/// Path prefix remap rules for sysroot.
///
/// This remap logic aligns with rustc:
/// <https://github.com/rust-lang/rust/blob/c2ef3516/src/bootstrap/src/lib.rs#L1113-L1116>
fn sysroot_remap(build_runner: &BuildRunner<'_, '_>, unit: &Unit) -> OsString {
fn sysroot_remap(build_runner: &BuildRunner<'_, '_>) -> OsString {
let mut remap = OsString::new();
remap.push({
// See also `detect_sysroot_src_path()`.
let mut sysroot = build_runner.bcx.target_data.info(unit.kind).sysroot.clone();
sysroot.push("lib");
sysroot.push("rustlib");
sysroot.push("src");
sysroot.push("rust");
sysroot
build_runner
.bcx
.get_sysroot()
.join("lib")
.join("rustlib")
.join("src")
.join("rust")
});
remap.push("=");
remap.push("/rustc/");
Expand Down
10 changes: 10 additions & 0 deletions src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ pub struct GlobalContext {
cargo_exe: OnceLock<PathBuf>,
/// The location of the rustdoc executable
rustdoc: OnceLock<PathBuf>,
/// The path to the sysroot
sysroot: OnceLock<PathBuf>,
/// Whether we are printing extra verbose messages
extra_verbose: bool,
/// `frozen` is the same as `locked`, but additionally will not access the
Expand Down Expand Up @@ -379,6 +381,7 @@ impl GlobalContext {
cli_config: None,
cargo_exe: Default::default(),
rustdoc: Default::default(),
sysroot: Default::default(),
extra_verbose: false,
frozen: false,
locked: false,
Expand Down Expand Up @@ -610,6 +613,13 @@ impl GlobalContext {
.map(AsRef::as_ref)
}

/// Get the sysroot path.
pub fn get_sysroot<'gctx>(&'gctx self, rustc: &Rustc) -> CargoResult<&'gctx Path> {
self.sysroot
.try_borrow_with(|| rustc.sysroot(self))
.map(AsRef::as_ref)
}
Comment thread
epage marked this conversation as resolved.

/// Which package sources have been updated, used to ensure it is only done once.
pub fn updated_sources(&self) -> MutexGuard<'_, HashSet<SourceId>> {
self.updated_sources.lock().unwrap()
Expand Down
4 changes: 2 additions & 2 deletions src/ops/cargo_fix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ use semver::Version;
use tracing::{debug, trace, warn};

pub use self::fix_edition::fix_edition;
use crate::compiler::CompileKind;
use crate::compiler::RustcTargetData;
use crate::ops::resolve::WorkspaceResolve;
use crate::ops::{self, CompileOptions};
Expand Down Expand Up @@ -185,7 +184,8 @@ pub fn fix(
wrapper.env(IDIOMS_ENV_INTERNAL, "1");
}

let sysroot = &target_data.info(CompileKind::Host).sysroot;
let rustc = gctx.load_global_rustc(Some(original_ws))?;
let sysroot = gctx.get_sysroot(&rustc).expect("able to invoke rustc");
if sysroot.is_dir() {
wrapper.env(SYSROOT_INTERNAL, sysroot);
}
Expand Down
18 changes: 17 additions & 1 deletion src/util/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use std::hash::{Hash, Hasher};
use std::path::{Path, PathBuf};
use std::sync::Mutex;

use anyhow::Context as _;
use anyhow::{Context as _, bail};
use cargo_util::{ProcessBuilder, ProcessError, paths};
use filetime::FileTime;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -64,6 +64,7 @@ impl Rustc {
.wrapped(wrapper.as_deref());
apply_env_config(gctx, &mut cmd)?;
cmd.env(crate::CARGO_ENV, gctx.cargo_exe()?);

cmd.arg("-vV");
let verbose_version = cache.cached_output(&cmd, 0)?.0;

Expand Down Expand Up @@ -159,6 +160,21 @@ impl Rustc {
.unwrap()
.cached_output(cmd, extra_fingerprint)
}

/// Use the rustc executable to fetch the sysroot path.
pub fn sysroot(&self, gctx: &GlobalContext) -> CargoResult<PathBuf> {
Comment thread
epage marked this conversation as resolved.
let mut cmd = self.workspace_process();
apply_env_config(gctx, &mut cmd)?;
cmd.env(crate::CARGO_ENV, gctx.cargo_exe()?);
cmd.arg("--print=sysroot");

let (stdout, _) = self.cached_output(&cmd, 0)?;
let path: PathBuf = stdout.trim().into();
if !path.exists() {
bail!("sysroot path \"{}\" does not exist", path.display());
}
Comment thread
epage marked this conversation as resolved.
Ok(path)
}
}

/// It is a well known fact that `rustc` is not the fastest compiler in the
Expand Down
Loading