]> git.proxmox.com Git - rustc.git/blame - src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
New upstream version 1.74.1+dfsg1
[rustc.git] / src / tools / rust-analyzer / crates / project-model / src / rustc_cfg.rs
CommitLineData
064997fb
FG
1//! Runs `rustc --print cfg` to get built-in cfg flags.
2
3use std::process::Command;
4
781aab86 5use anyhow::Context;
2b03887a 6use rustc_hash::FxHashMap;
064997fb 7
781aab86
FG
8use crate::{cfg_flag::CfgFlag, utf8_stdout, ManifestPath, Sysroot};
9
10/// Determines how `rustc --print cfg` is discovered and invoked.
11///
12/// There options are supported:
13/// - [`RustcCfgConfig::Cargo`], which relies on `cargo rustc --print cfg`
14/// and `RUSTC_BOOTSTRAP`.
15/// - [`RustcCfgConfig::Explicit`], which uses an explicit path to the `rustc`
16/// binary in the sysroot.
17/// - [`RustcCfgConfig::Discover`], which uses [`toolchain::rustc`].
18pub(crate) enum RustcCfgConfig<'a> {
19 Cargo(&'a ManifestPath),
20 Explicit(&'a Sysroot),
21 Discover,
22}
064997fb 23
2b03887a 24pub(crate) fn get(
2b03887a
FG
25 target: Option<&str>,
26 extra_env: &FxHashMap<String, String>,
781aab86 27 config: RustcCfgConfig<'_>,
2b03887a 28) -> Vec<CfgFlag> {
064997fb
FG
29 let _p = profile::span("rustc_cfg::get");
30 let mut res = Vec::with_capacity(6 * 2 + 1);
31
32 // Some nightly-only cfgs, which are required for stdlib
33 res.push(CfgFlag::Atom("target_thread_local".into()));
34 for ty in ["8", "16", "32", "64", "cas", "ptr"] {
35 for key in ["target_has_atomic", "target_has_atomic_load_store"] {
36 res.push(CfgFlag::KeyValue { key: key.to_string(), value: ty.into() });
37 }
38 }
39
add651ee
FG
40 // Add miri cfg, which is useful for mir eval in stdlib
41 res.push(CfgFlag::Atom("miri".into()));
42
781aab86
FG
43 let rustc_cfgs = get_rust_cfgs(target, extra_env, config);
44
45 let rustc_cfgs = match rustc_cfgs {
46 Ok(cfgs) => cfgs,
47 Err(e) => {
48 tracing::error!(?e, "failed to get rustc cfgs");
49 return res;
50 }
51 };
52
53 let rustc_cfgs =
54 rustc_cfgs.lines().map(|it| it.parse::<CfgFlag>()).collect::<Result<Vec<_>, _>>();
55
56 match rustc_cfgs {
064997fb 57 Ok(rustc_cfgs) => {
781aab86
FG
58 tracing::debug!(?rustc_cfgs, "rustc cfgs found");
59 res.extend(rustc_cfgs);
60 }
61 Err(e) => {
62 tracing::error!(?e, "failed to get rustc cfgs")
064997fb 63 }
064997fb
FG
64 }
65
66 res
67}
68
2b03887a 69fn get_rust_cfgs(
2b03887a
FG
70 target: Option<&str>,
71 extra_env: &FxHashMap<String, String>,
781aab86 72 config: RustcCfgConfig<'_>,
add651ee 73) -> anyhow::Result<String> {
781aab86
FG
74 let mut cmd = match config {
75 RustcCfgConfig::Cargo(cargo_toml) => {
76 let mut cmd = Command::new(toolchain::cargo());
77 cmd.envs(extra_env);
78 cmd.current_dir(cargo_toml.parent())
79 .args(["rustc", "-Z", "unstable-options", "--print", "cfg"])
80 .env("RUSTC_BOOTSTRAP", "1");
81 if let Some(target) = target {
82 cmd.args(["--target", target]);
83 }
84
85 return utf8_stdout(cmd).context("Unable to run `cargo rustc`");
064997fb 86 }
781aab86
FG
87 RustcCfgConfig::Explicit(sysroot) => {
88 let rustc: std::path::PathBuf = sysroot.discover_rustc()?.into();
89 tracing::debug!(?rustc, "using explicit rustc from sysroot");
90 Command::new(rustc)
064997fb 91 }
781aab86
FG
92 RustcCfgConfig::Discover => {
93 let rustc = toolchain::rustc();
94 tracing::debug!(?rustc, "using rustc from env");
95 Command::new(rustc)
96 }
97 };
98
2b03887a 99 cmd.envs(extra_env);
9c376795 100 cmd.args(["--print", "cfg", "-O"]);
064997fb 101 if let Some(target) = target {
9c376795 102 cmd.args(["--target", target]);
064997fb 103 }
781aab86
FG
104
105 utf8_stdout(cmd).context("Unable to run `rustc`")
064997fb 106}