Skip to content
33 changes: 3 additions & 30 deletions src/compiler/build_context/target_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::compiler::CrateType;
use crate::compiler::apply_env_config;
use crate::context::{GlobalContext, StringList, TargetConfig};
use crate::util::interning::InternedString;
use crate::util::rustc::{get_rustflags_from_build_config, get_rustflags_from_env};
use crate::util::{CargoResult, Rustc};
use crate::workspace::{Dependency, Package, Target, TargetKind, Workspace};

Expand Down Expand Up @@ -168,8 +169,6 @@ 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,
#[tracing::instrument(skip_all)]
pub fn new(
gctx: &GlobalContext,
Expand Down Expand Up @@ -825,27 +824,7 @@ fn extra_args(
/// Gets compiler flags from environment variables.
/// See [`extra_args`] for more.
fn rustflags_from_env(gctx: &GlobalContext, flags: Flags) -> Option<Vec<String>> {
// First try CARGO_ENCODED_RUSTFLAGS from the environment.
// Prefer this over RUSTFLAGS since it's less prone to encoding errors.
if let Ok(a) = gctx.get_env(format!("CARGO_ENCODED_{}", flags.as_env())) {
if a.is_empty() {
return Some(Vec::new());
}
return Some(a.split('\x1f').map(str::to_string).collect());
}

// Then try RUSTFLAGS from the environment
if let Ok(a) = gctx.get_env(flags.as_env()) {
let args = a
.split(' ')
.map(str::trim)
.filter(|s| !s.is_empty())
.map(str::to_string);
return Some(args.collect());
}

// No rustflags to be collected from the environment
None
get_rustflags_from_env(gctx, flags.as_env())
}

/// Gets compiler flags from `[target]` section in the config.
Expand Down Expand Up @@ -916,13 +895,7 @@ fn rustflags_from_host(
/// Gets compiler flags from `[build]` section in the config.
/// See [`extra_args`] for more.
fn rustflags_from_build(gctx: &GlobalContext, flag: Flags) -> CargoResult<Option<Vec<String>>> {
// Then the `build.rustflags` value.
let build = gctx.build_config()?;
let list = match flag {
Flags::Rust => &build.rustflags,
Flags::Rustdoc => &build.rustdocflags,
};
Ok(list.as_ref().map(|l| l.as_slice().to_vec()))
get_rustflags_from_build_config(gctx, matches!(flag, Flags::Rustdoc))
}

/// Whether a host artifact must take its configuration solely from `[host]` and ignore `[target]`.
Expand Down
97 changes: 96 additions & 1 deletion src/util/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,16 @@ impl Rustc {
let mut cmd = self.workspace_process();
apply_env_config(gctx, &mut cmd)?;
cmd.env(crate::CARGO_ENV, gctx.cargo_exe()?);
if let Some(rustflags) = get_rustflags_from_env(gctx, "RUSTFLAGS") {
cmd.args(&rustflags);
} else if let Some(rustflags) = get_rustflags_from_build_config(gctx, false)? {
cmd.args(&rustflags);
}
cmd.arg("--print=sysroot");

let (stdout, _) = self.cached_output(&cmd, 0)?;
let (stdout, _) = self
.cached_output(&cmd, 0)
.with_context(|| "failed to run `rustc` to find the sysroot location")?;
let path: PathBuf = stdout.trim().into();
if !path.exists() {
bail!("sysroot path \"{}\" does not exist", path.display());
Expand Down Expand Up @@ -407,3 +414,91 @@ fn process_fingerprint(cmd: &ProcessBuilder, extra_fingerprint: u64) -> u64 {
env.hash(&mut hasher);
Hasher::finish(&hasher)
}

/// Gets compiler flags from environment variables.
pub(crate) fn get_rustflags_from_env(
gctx: &GlobalContext,
env_name: &'static str,
) -> Option<Vec<String>> {
// First try CARGO_ENCODED_RUSTFLAGS from the environment.
// Prefer this over RUSTFLAGS since it's less prone to encoding errors.
if let Ok(a) = gctx.get_env(format!("CARGO_ENCODED_{}", env_name)) {
if a.is_empty() {
return Some(Vec::new());
}
return Some(a.split('\x1f').map(str::to_string).collect());
}

// Then try RUSTFLAGS from the environment
if let Ok(a) = gctx.get_env(env_name) {
let args = a
.split(' ')
.map(str::trim)
.filter(|s| !s.is_empty())
.map(str::to_string);
return Some(args.collect());
}

// No rustflags to be collected from the environment
None
}

/// Gets compiler flags from `[build]` section in the config.
pub(crate) fn get_rustflags_from_build_config(
gctx: &GlobalContext,
is_rustdoc: bool,
) -> CargoResult<Option<Vec<String>>> {
// Then the `build.rustflags` value.
let build = gctx.build_config()?;
let list = if is_rustdoc {
&build.rustdocflags
} else {
&build.rustflags
};
Ok(list.as_ref().map(|l| l.as_slice().to_vec()))
}

#[cfg(test)]
mod tests {
use crate::GlobalContext;
use crate::context::{ConfigValue, Definition};
use crate::util::data_structures::HashMap;
use std::path::Path;

#[test]
fn sysroot_fetch_respects_env_rustflags() {
let mut gctx = GlobalContext::default().unwrap();

let rustflags = HashMap::from_iter([("RUSTFLAGS".to_string(), "--sysroot=.".to_string())]);
gctx.set_env(rustflags);

let rustc = gctx.load_global_rustc(None).unwrap();
let sysroot = rustc.sysroot(&gctx).unwrap();
assert_eq!(sysroot, Path::new("."));
}

#[test]
fn sysroot_fetch_respects_build_rustflags() {
let mut gctx = GlobalContext::default().unwrap();
gctx.set_env(HashMap::default());

let definition = Definition::Cli(None);
let rustflags = ConfigValue::List(
vec![ConfigValue::String(
"--sysroot=.".to_string(),
definition.clone(),
)],
definition.clone(),
);
let build = ConfigValue::Table(
HashMap::from_iter([("rustflags".to_string(), rustflags)]),
definition,
);
gctx.set_values(HashMap::from_iter([("build".to_string(), build)]))
.unwrap();

let rustc = gctx.load_global_rustc(None).unwrap();
let sysroot = rustc.sysroot(&gctx).unwrap();
assert_eq!(sysroot, Path::new("."));
}
}
48 changes: 24 additions & 24 deletions tests/testsuite/rustflags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn env_rustflags_normal_source() {
.env("RUSTFLAGS", "-Z bogus")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -42,7 +42,7 @@ Caused by:
.env("RUSTFLAGS", "-Z bogus")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -53,7 +53,7 @@ Caused by:
.env("RUSTFLAGS", "-Z bogus")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -64,7 +64,7 @@ Caused by:
.env("RUSTFLAGS", "-Z bogus")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -75,7 +75,7 @@ Caused by:
.env("RUSTFLAGS", "-Z bogus")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand Down Expand Up @@ -172,7 +172,7 @@ fn env_rustflags_normal_source_with_target() {
.env("RUSTFLAGS", "-Z bogus")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -184,7 +184,7 @@ Caused by:
.env("RUSTFLAGS", "-Z bogus")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -196,7 +196,7 @@ Caused by:
.env("RUSTFLAGS", "-Z bogus")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -208,7 +208,7 @@ Caused by:
.env("RUSTFLAGS", "-Z bogus")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -220,7 +220,7 @@ Caused by:
.env("RUSTFLAGS", "-Z bogus")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand Down Expand Up @@ -348,7 +348,7 @@ fn env_rustflags_recompile() {
.env("RUSTFLAGS", "-Z bogus")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -367,7 +367,7 @@ fn env_rustflags_recompile2() {
.env("RUSTFLAGS", "-Z bogus")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand Down Expand Up @@ -417,7 +417,7 @@ fn build_rustflags_normal_source() {
p.cargo("check --lib")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -427,7 +427,7 @@ Caused by:
p.cargo("check --bin=a")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -437,7 +437,7 @@ Caused by:
p.cargo("check --example=b")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -447,7 +447,7 @@ Caused by:
p.cargo("test")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -457,7 +457,7 @@ Caused by:
p.cargo("bench")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand Down Expand Up @@ -574,7 +574,7 @@ fn build_rustflags_normal_source_with_target() {
.arg(host)
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -585,7 +585,7 @@ Caused by:
.arg(host)
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -596,7 +596,7 @@ Caused by:
.arg(host)
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -607,7 +607,7 @@ Caused by:
.arg(host)
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -618,7 +618,7 @@ Caused by:
.arg(host)
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand Down Expand Up @@ -724,7 +724,7 @@ fn build_rustflags_recompile() {
p.cargo("check")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand All @@ -751,7 +751,7 @@ fn build_rustflags_recompile2() {
p.cargo("check")
.with_status(101)
.with_stderr_data(str![[r#"
[ERROR] failed to run `rustc` to learn about target-specific information
[ERROR] failed to run `rustc` to find the sysroot location

Caused by:
[..]bogus[..]
Expand Down