Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rustc: Simplify --sysroot code after rust#103660 #325

Merged
merged 1 commit into from
Dec 2, 2023
Merged
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
103 changes: 30 additions & 73 deletions marker_rustc_driver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ pub mod lint_pass;

use std::env;
use std::ops::Deref;
use std::process::Command;

use camino::{Utf8Path, Utf8PathBuf};
use camino::Utf8Path;
use marker_adapter::{LintCrateInfo, LINT_CRATES_ENV};
use marker_error::Context;

Expand All @@ -49,8 +48,10 @@ use crate::conversion::rustc::RustcConverter;
const RUSTC_TOOLCHAIN_VERSION: &str = "nightly-2023-11-16";
// endregion replace rust toolchain dev

pub const MARKER_SYSROOT_ENV: &str = "MARKER_SYSROOT";

struct DefaultCallbacks {
env_vars: Vec<(&'static str, String)>,
env_vars: Vec<&'static str>,
}
impl rustc_driver::Callbacks for DefaultCallbacks {
fn config(&mut self, config: &mut rustc_interface::Config) {
Expand All @@ -62,7 +63,7 @@ impl rustc_driver::Callbacks for DefaultCallbacks {
}

struct MarkerCallback {
env_vars: Vec<(&'static str, String)>,
env_vars: Vec<&'static str>,
lint_crates: Vec<LintCrateInfo>,
}

Expand Down Expand Up @@ -105,12 +106,15 @@ impl rustc_driver::Callbacks for MarkerCallback {
}
}

fn register_tracked_env(sess: &mut rustc_session::parse::ParseSess, vars: &[(&'static str, String)]) {
fn register_tracked_env(sess: &mut rustc_session::parse::ParseSess, vars: &[&'static str]) {
use rustc_span::Symbol;
let env = sess.env_depinfo.get_mut();

for (key, value) in vars {
env.insert((Symbol::intern(key), Some(Symbol::intern(value))));
for key in vars {
env.insert((
Symbol::intern(key),
Some(Symbol::intern(&std::env::var(key).unwrap_or_default())),
));
}
}

Expand Down Expand Up @@ -167,17 +171,6 @@ fn arg_value<'a, T: Deref<Target = str>>(
None
}

fn toolchain_path(home: Option<String>, toolchain: Option<String>) -> Option<Utf8PathBuf> {
home.and_then(|home| {
toolchain.map(|toolchain| {
let mut path = Utf8PathBuf::from(home);
path.push("toolchains");
path.push(toolchain);
path
})
})
}

fn display_help() {
println!(
"\
Expand Down Expand Up @@ -208,15 +201,24 @@ pub fn try_main(args: impl Iterator<Item = String>) -> Result<(), MainError> {
// values. These are usually driver-independent and handled by the adapter.
let mut orig_args: Vec<String> = args.collect();

let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true);
let has_sys_root_arg = sys_root_arg.is_some();

// Further invocation of rustc require the `--sysroot` flag. We add it here
// in preparation.
if !has_sys_root_arg {
let sys_root = find_sys_root(sys_root_arg);
orig_args.extend(["--sysroot".into(), sys_root]);
};
// Rustc will by default use the location of the rustc library as the system
// root. Custom drivers, like Clippy, rustdoc, and Miri have options to override
// this directory. This seems to be required for cross compiling and cases where
// the driver is invoked directly.
//
// I haven't found a definite explanation which circumstances require it, but
// it's probably best to support the same behavior. This code is an adaptation
// of Clippy's solution, with the deviation, that we add the `--sysroot` directly
// and have a `MARKER_` prefix for the `SYSROOT` environment value. This is similar
// to Miri's `MIRI_SYSROOT` variable.
//
// The `ui_test` crate used by `marker_uitest` seems to also fiddle around with
// the system root, if custom dependencies are defined.
if arg_value(&orig_args, "--sysroot", |_| true).is_none()
&& let Ok(env_sys_root) = std::env::var(MARKER_SYSROOT_ENV)
{
orig_args.extend(vec!["--sysroot".into(), env_sys_root]);
}

// make "marker_rustc_driver --rustc" work like a subcommand that passes
// all args to "rustc" for example `marker_rustc_driver --rustc --version`
Expand Down Expand Up @@ -270,7 +272,7 @@ pub fn try_main(args: impl Iterator<Item = String>) -> Result<(), MainError> {
let in_primary_package = env::var("CARGO_PRIMARY_PACKAGE").is_ok();

let enable_marker = !cap_lints_allow && (!no_deps || in_primary_package);
let env_vars = vec![(LINT_CRATES_ENV, std::env::var(LINT_CRATES_ENV).unwrap_or_default())];
let env_vars = vec![LINT_CRATES_ENV, MARKER_SYSROOT_ENV];
if !enable_marker {
rustc_driver::RunCompiler::new(&orig_args, &mut DefaultCallbacks { env_vars }).run()?;
return Ok(());
Expand Down Expand Up @@ -306,51 +308,6 @@ pub fn try_main(args: impl Iterator<Item = String>) -> Result<(), MainError> {
Ok(())
}

/// Get the sysroot, looking from most specific to this invocation to the least:
/// - command line
/// - runtime environment
/// - `SYSROOT`
/// - `RUSTUP_HOME`, `MULTIRUST_HOME`, `RUSTUP_TOOLCHAIN`, `MULTIRUST_TOOLCHAIN`
/// - sysroot from rustc in the path
/// - compile-time environment
/// - `SYSROOT`
/// - `RUSTUP_HOME`, `MULTIRUST_HOME`, `RUSTUP_TOOLCHAIN`, `MULTIRUST_TOOLCHAIN`
fn find_sys_root(sys_root_arg: Option<&str>) -> String {
sys_root_arg
.map(Utf8PathBuf::from)
.or_else(|| std::env::var("SYSROOT").ok().map(Utf8PathBuf::from))
.or_else(|| {
let home = std::env::var("RUSTUP_HOME")
.or_else(|_| std::env::var("MULTIRUST_HOME"))
.ok();
let toolchain = std::env::var("RUSTUP_TOOLCHAIN")
.or_else(|_| std::env::var("MULTIRUST_TOOLCHAIN"))
.ok();
toolchain_path(home, toolchain)
})
.or_else(|| {
Command::new("rustc")
.arg("--print")
.arg("sysroot")
.output()
.ok()
.and_then(|out| String::from_utf8(out.stdout).ok())
.map(|s| Utf8PathBuf::from(s.trim()))
})
.or_else(|| option_env!("SYSROOT").map(Utf8PathBuf::from))
.or_else(|| {
let home = option_env!("RUSTUP_HOME")
.or(option_env!("MULTIRUST_HOME"))
.map(ToString::to_string);
let toolchain = option_env!("RUSTUP_TOOLCHAIN")
.or(option_env!("MULTIRUST_TOOLCHAIN"))
.map(ToString::to_string);
toolchain_path(home, toolchain)
})
.map(Utf8PathBuf::into_string)
.expect("need to specify SYSROOT env var during marker compilation, or use rustup or multirust")
}

pub enum MainError {
Custom(marker_error::Error),
Rustc(rustc_span::ErrorGuaranteed),
Expand Down