summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs')
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs b/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
new file mode 100644
index 000000000..17e244d06
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
@@ -0,0 +1,60 @@
+//! Runs `rustc --print cfg` to get built-in cfg flags.
+
+use std::process::Command;
+
+use anyhow::Result;
+
+use crate::{cfg_flag::CfgFlag, utf8_stdout, ManifestPath};
+
+pub(crate) fn get(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Vec<CfgFlag> {
+ let _p = profile::span("rustc_cfg::get");
+ let mut res = Vec::with_capacity(6 * 2 + 1);
+
+ // Some nightly-only cfgs, which are required for stdlib
+ res.push(CfgFlag::Atom("target_thread_local".into()));
+ for ty in ["8", "16", "32", "64", "cas", "ptr"] {
+ for key in ["target_has_atomic", "target_has_atomic_load_store"] {
+ res.push(CfgFlag::KeyValue { key: key.to_string(), value: ty.into() });
+ }
+ }
+
+ match get_rust_cfgs(cargo_toml, target) {
+ Ok(rustc_cfgs) => {
+ tracing::debug!(
+ "rustc cfgs found: {:?}",
+ rustc_cfgs
+ .lines()
+ .map(|it| it.parse::<CfgFlag>().map(|it| it.to_string()))
+ .collect::<Vec<_>>()
+ );
+ res.extend(rustc_cfgs.lines().filter_map(|it| it.parse().ok()));
+ }
+ Err(e) => tracing::error!("failed to get rustc cfgs: {e:?}"),
+ }
+
+ res
+}
+
+fn get_rust_cfgs(cargo_toml: Option<&ManifestPath>, target: Option<&str>) -> Result<String> {
+ if let Some(cargo_toml) = cargo_toml {
+ let mut cargo_config = Command::new(toolchain::cargo());
+ cargo_config
+ .current_dir(cargo_toml.parent())
+ .args(&["-Z", "unstable-options", "rustc", "--print", "cfg"])
+ .env("RUSTC_BOOTSTRAP", "1");
+ if let Some(target) = target {
+ cargo_config.args(&["--target", target]);
+ }
+ match utf8_stdout(cargo_config) {
+ Ok(it) => return Ok(it),
+ Err(e) => tracing::debug!("{e:?}: falling back to querying rustc for cfgs"),
+ }
+ }
+ // using unstable cargo features failed, fall back to using plain rustc
+ let mut cmd = Command::new(toolchain::rustc());
+ cmd.args(&["--print", "cfg", "-O"]);
+ if let Some(target) = target {
+ cmd.args(&["--target", target]);
+ }
+ utf8_stdout(cmd)
+}