]> git.lizzy.rs Git - rust.git/blob - src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
Rollup merge of #102073 - andrewpollack:add-execvp-call-ignore, r=tmandry
[rust.git] / src / tools / rust-analyzer / crates / project-model / src / rustc_cfg.rs
1 //! Runs `rustc --print cfg` to get built-in cfg flags.
2
3 use std::process::Command;
4
5 use anyhow::Result;
6
7 use crate::{cfg_flag::CfgFlag, utf8_stdout, CargoConfig, ManifestPath};
8
9 pub(crate) fn get(
10     cargo_toml: Option<&ManifestPath>,
11     target: Option<&str>,
12     config: &CargoConfig,
13 ) -> Vec<CfgFlag> {
14     let _p = profile::span("rustc_cfg::get");
15     let mut res = Vec::with_capacity(6 * 2 + 1);
16
17     // Some nightly-only cfgs, which are required for stdlib
18     res.push(CfgFlag::Atom("target_thread_local".into()));
19     for ty in ["8", "16", "32", "64", "cas", "ptr"] {
20         for key in ["target_has_atomic", "target_has_atomic_load_store"] {
21             res.push(CfgFlag::KeyValue { key: key.to_string(), value: ty.into() });
22         }
23     }
24
25     match get_rust_cfgs(cargo_toml, target, config) {
26         Ok(rustc_cfgs) => {
27             tracing::debug!(
28                 "rustc cfgs found: {:?}",
29                 rustc_cfgs
30                     .lines()
31                     .map(|it| it.parse::<CfgFlag>().map(|it| it.to_string()))
32                     .collect::<Vec<_>>()
33             );
34             res.extend(rustc_cfgs.lines().filter_map(|it| it.parse().ok()));
35         }
36         Err(e) => tracing::error!("failed to get rustc cfgs: {e:?}"),
37     }
38
39     res
40 }
41
42 fn get_rust_cfgs(
43     cargo_toml: Option<&ManifestPath>,
44     target: Option<&str>,
45     config: &CargoConfig,
46 ) -> Result<String> {
47     if let Some(cargo_toml) = cargo_toml {
48         let mut cargo_config = Command::new(toolchain::cargo());
49         cargo_config.envs(&config.extra_env);
50         cargo_config
51             .current_dir(cargo_toml.parent())
52             .args(&["-Z", "unstable-options", "rustc", "--print", "cfg"])
53             .env("RUSTC_BOOTSTRAP", "1");
54         if let Some(target) = target {
55             cargo_config.args(&["--target", target]);
56         }
57         match utf8_stdout(cargo_config) {
58             Ok(it) => return Ok(it),
59             Err(e) => tracing::debug!("{e:?}: falling back to querying rustc for cfgs"),
60         }
61     }
62     // using unstable cargo features failed, fall back to using plain rustc
63     let mut cmd = Command::new(toolchain::rustc());
64     cmd.envs(&config.extra_env);
65     cmd.args(&["--print", "cfg", "-O"]);
66     if let Some(target) = target {
67         cmd.args(&["--target", target]);
68     }
69     utf8_stdout(cmd)
70 }