project_model/toolchain_info/
rustc_cfg.rs
use anyhow::Context;
use cfg::CfgAtom;
use rustc_hash::FxHashMap;
use toolchain::Tool;
use crate::{toolchain_info::QueryConfig, utf8_stdout};
pub fn get(
config: QueryConfig<'_>,
target: Option<&str>,
extra_env: &FxHashMap<String, String>,
) -> Vec<CfgAtom> {
let _p = tracing::info_span!("rustc_cfg::get").entered();
let rustc_cfgs = rustc_print_cfg(target, extra_env, config);
let rustc_cfgs = match rustc_cfgs {
Ok(cfgs) => cfgs,
Err(e) => {
tracing::warn!(?e, "failed to get rustc cfgs");
return vec![];
}
};
let unstable = vec![
r#"target_has_atomic_equal_alignment="8""#,
r#"target_has_atomic_equal_alignment="16""#,
r#"target_has_atomic_equal_alignment="32""#,
r#"target_has_atomic_equal_alignment="64""#,
r#"target_has_atomic_equal_alignment="128""#,
r#"target_has_atomic_equal_alignment="ptr""#,
r#"target_has_atomic_load_store"#,
r#"target_has_atomic_load_store="8""#,
r#"target_has_atomic_load_store="16""#,
r#"target_has_atomic_load_store="32""#,
r#"target_has_atomic_load_store="64""#,
r#"target_has_atomic_load_store="128""#,
r#"target_has_atomic_load_store="ptr""#,
r#"target_thread_local"#,
r#"target_has_atomic"#,
];
let rustc_cfgs =
rustc_cfgs.lines().chain(unstable).map(crate::parse_cfg).collect::<Result<Vec<_>, _>>();
match rustc_cfgs {
Ok(rustc_cfgs) => {
tracing::debug!(?rustc_cfgs, "rustc cfgs found");
rustc_cfgs
}
Err(e) => {
tracing::error!(?e, "failed to parse rustc cfgs");
vec![]
}
}
}
fn rustc_print_cfg(
target: Option<&str>,
extra_env: &FxHashMap<String, String>,
config: QueryConfig<'_>,
) -> anyhow::Result<String> {
const RUSTC_ARGS: [&str; 2] = ["--print", "cfg"];
let (sysroot, current_dir) = match config {
QueryConfig::Cargo(sysroot, cargo_toml) => {
let mut cmd = sysroot.tool(Tool::Cargo, cargo_toml.parent());
cmd.envs(extra_env);
cmd.args(["rustc", "-Z", "unstable-options"]).args(RUSTC_ARGS);
if let Some(target) = target {
cmd.args(["--target", target]);
}
cmd.args(["--", "-O"]);
match utf8_stdout(&mut cmd) {
Ok(it) => return Ok(it),
Err(e) => {
tracing::warn!(
%e,
"failed to run `{cmd:?}`, falling back to invoking rustc directly"
);
(sysroot, cargo_toml.parent().as_ref())
}
}
}
QueryConfig::Rustc(sysroot, current_dir) => (sysroot, current_dir),
};
let mut cmd = sysroot.tool(Tool::Rustc, current_dir);
cmd.envs(extra_env);
cmd.args(RUSTC_ARGS);
cmd.arg("-O");
if let Some(target) = target {
cmd.args(["--target", target]);
}
utf8_stdout(&mut cmd).with_context(|| format!("unable to fetch cfgs via `{cmd:?}`"))
}
#[cfg(test)]
mod tests {
use paths::{AbsPathBuf, Utf8PathBuf};
use crate::{ManifestPath, Sysroot};
use super::*;
#[test]
fn cargo() {
let manifest_path = concat!(env!("CARGO_MANIFEST_DIR"), "/Cargo.toml");
let sysroot = Sysroot::empty();
let manifest_path =
ManifestPath::try_from(AbsPathBuf::assert(Utf8PathBuf::from(manifest_path))).unwrap();
let cfg = QueryConfig::Cargo(&sysroot, &manifest_path);
assert_ne!(get(cfg, None, &FxHashMap::default()), vec![]);
}
#[test]
fn rustc() {
let sysroot = Sysroot::empty();
let cfg = QueryConfig::Rustc(&sysroot, env!("CARGO_MANIFEST_DIR").as_ref());
assert_ne!(get(cfg, None, &FxHashMap::default()), vec![]);
}
}