mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-12 05:08:52 +00:00
Cleanup toolchain info fetching
This commit is contained in:
parent
dc6cea57a2
commit
0f95e60da3
13 changed files with 197 additions and 230 deletions
|
@ -1,7 +1,7 @@
|
||||||
use chalk_ir::{AdtId, TyKind};
|
use chalk_ir::{AdtId, TyKind};
|
||||||
use either::Either;
|
use either::Either;
|
||||||
use hir_def::db::DefDatabase;
|
use hir_def::db::DefDatabase;
|
||||||
use project_model::{target_data_layout::RustcDataLayoutConfig, Sysroot};
|
use project_model::{toolchain_info::QueryConfig, Sysroot};
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use syntax::ToSmolStr;
|
use syntax::ToSmolStr;
|
||||||
use test_fixture::WithFixture;
|
use test_fixture::WithFixture;
|
||||||
|
@ -17,8 +17,8 @@ use crate::{
|
||||||
mod closure;
|
mod closure;
|
||||||
|
|
||||||
fn current_machine_data_layout() -> String {
|
fn current_machine_data_layout() -> String {
|
||||||
project_model::target_data_layout::get(
|
project_model::toolchain_info::target_data_layout::get(
|
||||||
RustcDataLayoutConfig::Rustc(&Sysroot::empty()),
|
QueryConfig::Rustc(&Sysroot::empty()),
|
||||||
None,
|
None,
|
||||||
&FxHashMap::default(),
|
&FxHashMap::default(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -178,13 +178,13 @@ impl WorkspaceBuildScripts {
|
||||||
.current_dir(current_dir)
|
.current_dir(current_dir)
|
||||||
.args(["rustc", "-Z", "unstable-options", "--print", "target-libdir"])
|
.args(["rustc", "-Z", "unstable-options", "--print", "target-libdir"])
|
||||||
.env("RUSTC_BOOTSTRAP", "1");
|
.env("RUSTC_BOOTSTRAP", "1");
|
||||||
if let Ok(it) = utf8_stdout(cargo_config) {
|
if let Ok(it) = utf8_stdout(&mut cargo_config) {
|
||||||
return Ok(it);
|
return Ok(it);
|
||||||
}
|
}
|
||||||
let mut cmd = sysroot.tool(Tool::Rustc);
|
let mut cmd = sysroot.tool(Tool::Rustc);
|
||||||
cmd.envs(extra_env);
|
cmd.envs(extra_env);
|
||||||
cmd.args(["--print", "target-libdir"]);
|
cmd.args(["--print", "target-libdir"]);
|
||||||
utf8_stdout(cmd)
|
utf8_stdout(&mut cmd)
|
||||||
})()?;
|
})()?;
|
||||||
|
|
||||||
let target_libdir = AbsPathBuf::try_from(Utf8PathBuf::from(target_libdir))
|
let target_libdir = AbsPathBuf::try_from(Utf8PathBuf::from(target_libdir))
|
||||||
|
|
|
@ -85,7 +85,7 @@ pub(crate) fn cargo_config_env(
|
||||||
}
|
}
|
||||||
// if successful we receive `env.key.value = "value" per entry
|
// if successful we receive `env.key.value = "value" per entry
|
||||||
tracing::debug!("Discovering cargo config env by {:?}", cargo_config);
|
tracing::debug!("Discovering cargo config env by {:?}", cargo_config);
|
||||||
utf8_stdout(cargo_config)
|
utf8_stdout(&mut cargo_config)
|
||||||
.map(parse_output_cargo_config_env)
|
.map(parse_output_cargo_config_env)
|
||||||
.inspect(|env| {
|
.inspect(|env| {
|
||||||
tracing::debug!("Discovered cargo config env: {:?}", env);
|
tracing::debug!("Discovered cargo config env: {:?}", env);
|
||||||
|
|
|
@ -15,15 +15,14 @@
|
||||||
//! procedural macros).
|
//! procedural macros).
|
||||||
//! * Lowering of concrete model to a [`base_db::CrateGraph`]
|
//! * Lowering of concrete model to a [`base_db::CrateGraph`]
|
||||||
|
|
||||||
|
pub mod project_json;
|
||||||
|
pub mod toolchain_info;
|
||||||
|
|
||||||
mod build_dependencies;
|
mod build_dependencies;
|
||||||
mod cargo_workspace;
|
mod cargo_workspace;
|
||||||
mod env;
|
mod env;
|
||||||
mod manifest_path;
|
mod manifest_path;
|
||||||
pub mod project_json;
|
|
||||||
mod rustc_cfg;
|
|
||||||
mod sysroot;
|
mod sysroot;
|
||||||
pub mod target_data_layout;
|
|
||||||
mod target_triple;
|
|
||||||
mod workspace;
|
mod workspace;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -182,7 +181,7 @@ impl fmt::Display for ProjectManifest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn utf8_stdout(mut cmd: Command) -> anyhow::Result<String> {
|
fn utf8_stdout(cmd: &mut Command) -> anyhow::Result<String> {
|
||||||
let output = cmd.output().with_context(|| format!("{cmd:?} failed"))?;
|
let output = cmd.output().with_context(|| format!("{cmd:?} failed"))?;
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
match String::from_utf8(output.stderr) {
|
match String::from_utf8(output.stderr) {
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
//! Runs `rustc --print cfg` to get built-in cfg flags.
|
|
||||||
|
|
||||||
use anyhow::Context;
|
|
||||||
use cfg::CfgAtom;
|
|
||||||
use intern::Symbol;
|
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
use toolchain::Tool;
|
|
||||||
|
|
||||||
use crate::{utf8_stdout, ManifestPath, Sysroot};
|
|
||||||
|
|
||||||
/// Determines how `rustc --print cfg` is discovered and invoked.
|
|
||||||
pub(crate) enum RustcCfgConfig<'a> {
|
|
||||||
/// Use `rustc --print cfg`, either from with the binary from the sysroot or by discovering via
|
|
||||||
/// [`toolchain::rustc`].
|
|
||||||
Rustc(&'a Sysroot),
|
|
||||||
/// Use `cargo --print cfg`, either from with the binary from the sysroot or by discovering via
|
|
||||||
/// [`toolchain::cargo`].
|
|
||||||
Cargo(&'a Sysroot, &'a ManifestPath),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn get(
|
|
||||||
target: Option<&str>,
|
|
||||||
extra_env: &FxHashMap<String, String>,
|
|
||||||
config: RustcCfgConfig<'_>,
|
|
||||||
) -> Vec<CfgAtom> {
|
|
||||||
let _p = tracing::info_span!("rustc_cfg::get").entered();
|
|
||||||
let mut res: Vec<_> = Vec::with_capacity(7 * 2 + 1);
|
|
||||||
|
|
||||||
// Some nightly-only cfgs, which are required for stdlib
|
|
||||||
res.push(CfgAtom::Flag(Symbol::intern("target_thread_local")));
|
|
||||||
for key in ["target_has_atomic", "target_has_atomic_load_store"] {
|
|
||||||
for ty in ["8", "16", "32", "64", "cas", "ptr"] {
|
|
||||||
res.push(CfgAtom::KeyValue { key: Symbol::intern(key), value: Symbol::intern(ty) });
|
|
||||||
}
|
|
||||||
res.push(CfgAtom::Flag(Symbol::intern(key)));
|
|
||||||
}
|
|
||||||
|
|
||||||
let rustc_cfgs = get_rust_cfgs(target, extra_env, config);
|
|
||||||
|
|
||||||
let rustc_cfgs = match rustc_cfgs {
|
|
||||||
Ok(cfgs) => cfgs,
|
|
||||||
Err(e) => {
|
|
||||||
tracing::error!(?e, "failed to get rustc cfgs");
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let rustc_cfgs = rustc_cfgs.lines().map(crate::parse_cfg).collect::<Result<Vec<_>, _>>();
|
|
||||||
|
|
||||||
match rustc_cfgs {
|
|
||||||
Ok(rustc_cfgs) => {
|
|
||||||
tracing::debug!(?rustc_cfgs, "rustc cfgs found");
|
|
||||||
res.extend(rustc_cfgs);
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
tracing::error!(?e, "failed to get rustc cfgs")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
res
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_rust_cfgs(
|
|
||||||
target: Option<&str>,
|
|
||||||
extra_env: &FxHashMap<String, String>,
|
|
||||||
config: RustcCfgConfig<'_>,
|
|
||||||
) -> anyhow::Result<String> {
|
|
||||||
let sysroot = match config {
|
|
||||||
RustcCfgConfig::Cargo(sysroot, cargo_toml) => {
|
|
||||||
let mut cmd = sysroot.tool(Tool::Cargo);
|
|
||||||
|
|
||||||
cmd.envs(extra_env);
|
|
||||||
cmd.current_dir(cargo_toml.parent())
|
|
||||||
.args(["rustc", "-Z", "unstable-options", "--print", "cfg"])
|
|
||||||
.env("RUSTC_BOOTSTRAP", "1");
|
|
||||||
if let Some(target) = target {
|
|
||||||
cmd.args(["--target", target]);
|
|
||||||
}
|
|
||||||
|
|
||||||
match utf8_stdout(cmd) {
|
|
||||||
Ok(it) => return Ok(it),
|
|
||||||
Err(e) => {
|
|
||||||
tracing::warn!("failed to run `cargo rustc --print cfg`, falling back to invoking rustc directly: {e}");
|
|
||||||
sysroot
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RustcCfgConfig::Rustc(sysroot) => sysroot,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut cmd = sysroot.tool(Tool::Rustc);
|
|
||||||
cmd.envs(extra_env);
|
|
||||||
cmd.args(["--print", "cfg", "-O"]);
|
|
||||||
if let Some(target) = target {
|
|
||||||
cmd.args(["--target", target]);
|
|
||||||
}
|
|
||||||
|
|
||||||
utf8_stdout(cmd).context("unable to fetch cfgs via `rustc --print cfg -O`")
|
|
||||||
}
|
|
|
@ -440,7 +440,7 @@ fn discover_sysroot_dir(
|
||||||
rustc.envs(extra_env);
|
rustc.envs(extra_env);
|
||||||
rustc.current_dir(current_dir).args(["--print", "sysroot"]);
|
rustc.current_dir(current_dir).args(["--print", "sysroot"]);
|
||||||
tracing::debug!("Discovering sysroot by {:?}", rustc);
|
tracing::debug!("Discovering sysroot by {:?}", rustc);
|
||||||
let stdout = utf8_stdout(rustc)?;
|
let stdout = utf8_stdout(&mut rustc)?;
|
||||||
Ok(AbsPathBuf::assert(Utf8PathBuf::from(stdout)))
|
Ok(AbsPathBuf::assert(Utf8PathBuf::from(stdout)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -472,7 +472,7 @@ fn discover_sysroot_src_dir_or_add_component(
|
||||||
rustup.envs(extra_env);
|
rustup.envs(extra_env);
|
||||||
rustup.current_dir(current_dir).args(["component", "add", "rust-src"]);
|
rustup.current_dir(current_dir).args(["component", "add", "rust-src"]);
|
||||||
tracing::info!("adding rust-src component by {:?}", rustup);
|
tracing::info!("adding rust-src component by {:?}", rustup);
|
||||||
utf8_stdout(rustup).ok()?;
|
utf8_stdout(&mut rustup).ok()?;
|
||||||
get_rust_src(sysroot_path)
|
get_rust_src(sysroot_path)
|
||||||
})
|
})
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
//! Runs `rustc --print target-spec-json` to get the target_data_layout.
|
|
||||||
|
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
use toolchain::Tool;
|
|
||||||
|
|
||||||
use crate::{utf8_stdout, ManifestPath, Sysroot};
|
|
||||||
|
|
||||||
/// Determines how `rustc --print target-spec-json` is discovered and invoked.
|
|
||||||
pub enum RustcDataLayoutConfig<'a> {
|
|
||||||
/// Use `rustc --print target-spec-json`, either from with the binary from the sysroot or by discovering via
|
|
||||||
/// [`toolchain::rustc`].
|
|
||||||
Rustc(&'a Sysroot),
|
|
||||||
/// Use `cargo --print target-spec-json`, either from with the binary from the sysroot or by discovering via
|
|
||||||
/// [`toolchain::cargo`].
|
|
||||||
Cargo(&'a Sysroot, &'a ManifestPath),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get(
|
|
||||||
config: RustcDataLayoutConfig<'_>,
|
|
||||||
target: Option<&str>,
|
|
||||||
extra_env: &FxHashMap<String, String>,
|
|
||||||
) -> anyhow::Result<String> {
|
|
||||||
let process = |output: String| {
|
|
||||||
(|| Some(output.split_once(r#""data-layout": ""#)?.1.split_once('"')?.0.to_owned()))()
|
|
||||||
.ok_or_else(|| {
|
|
||||||
anyhow::format_err!("could not fetch target-spec-json from command output")
|
|
||||||
})
|
|
||||||
};
|
|
||||||
let sysroot = match config {
|
|
||||||
RustcDataLayoutConfig::Cargo(sysroot, cargo_toml) => {
|
|
||||||
let mut cmd = sysroot.tool(Tool::Cargo);
|
|
||||||
cmd.envs(extra_env);
|
|
||||||
cmd.current_dir(cargo_toml.parent())
|
|
||||||
.args([
|
|
||||||
"rustc",
|
|
||||||
"-Z",
|
|
||||||
"unstable-options",
|
|
||||||
"--print",
|
|
||||||
"target-spec-json",
|
|
||||||
"--",
|
|
||||||
"-Z",
|
|
||||||
"unstable-options",
|
|
||||||
])
|
|
||||||
.env("RUSTC_BOOTSTRAP", "1");
|
|
||||||
if let Some(target) = target {
|
|
||||||
cmd.args(["--target", target]);
|
|
||||||
}
|
|
||||||
match utf8_stdout(cmd) {
|
|
||||||
Ok(output) => return process(output),
|
|
||||||
Err(e) => {
|
|
||||||
tracing::warn!("failed to run `cargo rustc --print target-spec-json`, falling back to invoking rustc directly: {e}");
|
|
||||||
sysroot
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
RustcDataLayoutConfig::Rustc(sysroot) => sysroot,
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut cmd = Sysroot::tool(sysroot, Tool::Rustc);
|
|
||||||
cmd.envs(extra_env)
|
|
||||||
.args(["-Z", "unstable-options", "--print", "target-spec-json"])
|
|
||||||
.env("RUSTC_BOOTSTRAP", "1");
|
|
||||||
if let Some(target) = target {
|
|
||||||
cmd.args(["--target", target]);
|
|
||||||
}
|
|
||||||
process(utf8_stdout(cmd)?)
|
|
||||||
}
|
|
13
crates/project-model/src/toolchain_info.rs
Normal file
13
crates/project-model/src/toolchain_info.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
pub mod rustc_cfg;
|
||||||
|
pub mod target_data_layout;
|
||||||
|
pub mod target_triple;
|
||||||
|
|
||||||
|
use crate::{ManifestPath, Sysroot};
|
||||||
|
|
||||||
|
pub enum QueryConfig<'a> {
|
||||||
|
/// Directly invoke `rustc` to query the desired information.
|
||||||
|
Rustc(&'a Sysroot),
|
||||||
|
/// Attempt to use cargo to query the desired information, honoring cargo configurations.
|
||||||
|
/// If this fails, falls back to invoking `rustc` directly.
|
||||||
|
Cargo(&'a Sysroot, &'a ManifestPath),
|
||||||
|
}
|
78
crates/project-model/src/toolchain_info/rustc_cfg.rs
Normal file
78
crates/project-model/src/toolchain_info/rustc_cfg.rs
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
//! Get the built-in cfg flags for the to be compile platform.
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
|
use cfg::CfgAtom;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
|
use toolchain::Tool;
|
||||||
|
|
||||||
|
use crate::{toolchain_info::QueryConfig, utf8_stdout};
|
||||||
|
|
||||||
|
/// Uses `rustc --print cfg` to fetch the builtin cfgs.
|
||||||
|
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::error!(?e, "failed to get rustc cfgs");
|
||||||
|
return vec![];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let rustc_cfgs = rustc_cfgs.lines().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; 3] = ["--print", "cfg", "-O"];
|
||||||
|
let sysroot = match config {
|
||||||
|
QueryConfig::Cargo(sysroot, cargo_toml) => {
|
||||||
|
let mut cmd = sysroot.tool(Tool::Cargo);
|
||||||
|
cmd.envs(extra_env);
|
||||||
|
cmd.current_dir(cargo_toml.parent()).env("RUSTC_BOOTSTRAP", "1");
|
||||||
|
cmd.args(["rustc", "-Z", "unstable-options"]).args(RUSTC_ARGS);
|
||||||
|
if let Some(target) = target {
|
||||||
|
cmd.args(["--target", target]);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QueryConfig::Rustc(sysroot) => sysroot,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut cmd = sysroot.tool(Tool::Rustc);
|
||||||
|
cmd.envs(extra_env);
|
||||||
|
cmd.args(RUSTC_ARGS);
|
||||||
|
if let Some(target) = target {
|
||||||
|
cmd.args(["--target", target]);
|
||||||
|
}
|
||||||
|
|
||||||
|
utf8_stdout(&mut cmd).with_context(|| format!("unable to fetch cfgs via `{cmd:?}`"))
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
//! Runs `rustc --print target-spec-json` to get the target_data_layout.
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
|
use rustc_hash::FxHashMap;
|
||||||
|
use toolchain::Tool;
|
||||||
|
|
||||||
|
use crate::{toolchain_info::QueryConfig, utf8_stdout, Sysroot};
|
||||||
|
|
||||||
|
/// Uses `rustc --print target-spec-json`.
|
||||||
|
pub fn get(
|
||||||
|
config: QueryConfig<'_>,
|
||||||
|
target: Option<&str>,
|
||||||
|
extra_env: &FxHashMap<String, String>,
|
||||||
|
) -> anyhow::Result<String> {
|
||||||
|
const RUSTC_ARGS: [&str; 2] = ["--print", "target-spec-json"];
|
||||||
|
let process = |output: String| {
|
||||||
|
(|| Some(output.split_once(r#""data-layout": ""#)?.1.split_once('"')?.0.to_owned()))()
|
||||||
|
.ok_or_else(|| {
|
||||||
|
anyhow::format_err!("could not parse target-spec-json from command output")
|
||||||
|
})
|
||||||
|
};
|
||||||
|
let sysroot = match config {
|
||||||
|
QueryConfig::Cargo(sysroot, cargo_toml) => {
|
||||||
|
let mut cmd = sysroot.tool(Tool::Cargo);
|
||||||
|
cmd.envs(extra_env);
|
||||||
|
cmd.current_dir(cargo_toml.parent()).env("RUSTC_BOOTSTRAP", "1");
|
||||||
|
cmd.args(["rustc", "-Z", "unstable-options"]).args(RUSTC_ARGS).args([
|
||||||
|
"--",
|
||||||
|
"-Z",
|
||||||
|
"unstable-options",
|
||||||
|
]);
|
||||||
|
if let Some(target) = target {
|
||||||
|
cmd.args(["--target", target]);
|
||||||
|
}
|
||||||
|
match utf8_stdout(&mut cmd) {
|
||||||
|
Ok(output) => return process(output),
|
||||||
|
Err(e) => {
|
||||||
|
tracing::warn!(%e, "failed to run `{cmd:?}`, falling back to invoking rustc directly");
|
||||||
|
sysroot
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
QueryConfig::Rustc(sysroot) => sysroot,
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut cmd = Sysroot::tool(sysroot, Tool::Rustc);
|
||||||
|
cmd.envs(extra_env)
|
||||||
|
.env("RUSTC_BOOTSTRAP", "1")
|
||||||
|
.args(["-Z", "unstable-options"])
|
||||||
|
.args(RUSTC_ARGS);
|
||||||
|
if let Some(target) = target {
|
||||||
|
cmd.args(["--target", target]);
|
||||||
|
}
|
||||||
|
utf8_stdout(&mut cmd)
|
||||||
|
.with_context(|| format!("unable to fetch target-data-layout via `{cmd:?}`"))
|
||||||
|
.and_then(process)
|
||||||
|
}
|
|
@ -1,33 +1,29 @@
|
||||||
//! Runs `rustc --print -vV` to get the host target.
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use toolchain::Tool;
|
use toolchain::Tool;
|
||||||
|
|
||||||
use crate::{utf8_stdout, ManifestPath, Sysroot};
|
use crate::{toolchain_info::QueryConfig, utf8_stdout, ManifestPath, Sysroot};
|
||||||
|
|
||||||
pub(super) enum TargetTipleConfig<'a> {
|
/// For cargo, runs `cargo -Zunstable-options config get build.target` to get the configured project target(s).
|
||||||
#[expect(dead_code)]
|
/// For rustc, runs `rustc --print -vV` to get the host target.
|
||||||
Rustc(&'a Sysroot),
|
pub fn get(
|
||||||
Cargo(&'a Sysroot, &'a ManifestPath),
|
config: QueryConfig<'_>,
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn get(
|
|
||||||
config: TargetTipleConfig<'_>,
|
|
||||||
target: Option<&str>,
|
target: Option<&str>,
|
||||||
extra_env: &FxHashMap<String, String>,
|
extra_env: &FxHashMap<String, String>,
|
||||||
) -> anyhow::Result<Vec<String>> {
|
) -> anyhow::Result<Vec<String>> {
|
||||||
|
let _p = tracing::info_span!("target_triple::get").entered();
|
||||||
if let Some(target) = target {
|
if let Some(target) = target {
|
||||||
return Ok(vec![target.to_owned()]);
|
return Ok(vec![target.to_owned()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let sysroot = match config {
|
let sysroot = match config {
|
||||||
TargetTipleConfig::Cargo(sysroot, cargo_toml) => {
|
QueryConfig::Cargo(sysroot, cargo_toml) => {
|
||||||
match cargo_config_build_target(cargo_toml, extra_env, sysroot) {
|
match cargo_config_build_target(cargo_toml, extra_env, sysroot) {
|
||||||
Some(it) => return Ok(it),
|
Some(it) => return Ok(it),
|
||||||
None => sysroot,
|
None => sysroot,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TargetTipleConfig::Rustc(sysroot) => sysroot,
|
QueryConfig::Rustc(sysroot) => sysroot,
|
||||||
};
|
};
|
||||||
rustc_discover_host_triple(extra_env, sysroot).map(|it| vec![it])
|
rustc_discover_host_triple(extra_env, sysroot).map(|it| vec![it])
|
||||||
}
|
}
|
||||||
|
@ -36,11 +32,11 @@ fn rustc_discover_host_triple(
|
||||||
extra_env: &FxHashMap<String, String>,
|
extra_env: &FxHashMap<String, String>,
|
||||||
sysroot: &Sysroot,
|
sysroot: &Sysroot,
|
||||||
) -> anyhow::Result<String> {
|
) -> anyhow::Result<String> {
|
||||||
let mut rustc = sysroot.tool(Tool::Rustc);
|
let mut cmd = sysroot.tool(Tool::Rustc);
|
||||||
rustc.envs(extra_env);
|
cmd.envs(extra_env);
|
||||||
rustc.arg("-vV");
|
cmd.arg("-vV");
|
||||||
tracing::debug!("Discovering host platform by {:?}", rustc);
|
let stdout = utf8_stdout(&mut cmd)
|
||||||
let stdout = utf8_stdout(rustc).context("Failed to discover host platform")?;
|
.with_context(|| format!("unable to discover host platform via `{cmd:?}`"))?;
|
||||||
let field = "host: ";
|
let field = "host: ";
|
||||||
let target = stdout.lines().find_map(|l| l.strip_prefix(field));
|
let target = stdout.lines().find_map(|l| l.strip_prefix(field));
|
||||||
if let Some(target) = target {
|
if let Some(target) = target {
|
||||||
|
@ -56,20 +52,18 @@ fn cargo_config_build_target(
|
||||||
extra_env: &FxHashMap<String, String>,
|
extra_env: &FxHashMap<String, String>,
|
||||||
sysroot: &Sysroot,
|
sysroot: &Sysroot,
|
||||||
) -> Option<Vec<String>> {
|
) -> Option<Vec<String>> {
|
||||||
let mut cargo_config = sysroot.tool(Tool::Cargo);
|
let mut cmd = sysroot.tool(Tool::Cargo);
|
||||||
cargo_config.envs(extra_env);
|
cmd.envs(extra_env);
|
||||||
cargo_config
|
cmd.current_dir(cargo_toml.parent()).env("RUSTC_BOOTSTRAP", "1");
|
||||||
.current_dir(cargo_toml.parent())
|
cmd.args(["-Z", "unstable-options", "config", "get", "build.target"]);
|
||||||
.args(["-Z", "unstable-options", "config", "get", "build.target"])
|
|
||||||
.env("RUSTC_BOOTSTRAP", "1");
|
|
||||||
// if successful we receive `build.target = "target-triple"`
|
// if successful we receive `build.target = "target-triple"`
|
||||||
// or `build.target = ["<target 1>", ..]`
|
// or `build.target = ["<target 1>", ..]`
|
||||||
tracing::debug!("Discovering cargo config target by {:?}", cargo_config);
|
|
||||||
// this might be `error: config value `build.target` is not set` in which case we
|
// this might be `error: config value `build.target` is not set` in which case we
|
||||||
// don't wanna log the error
|
// don't wanna log the error
|
||||||
utf8_stdout(cargo_config).and_then(parse_output_cargo_config_build_target).ok()
|
utf8_stdout(&mut cmd).and_then(parse_output_cargo_config_build_target).ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parses `"build.target = [target-triple, target-triple, ...]"` or `"build.target = "target-triple"`
|
||||||
fn parse_output_cargo_config_build_target(stdout: String) -> anyhow::Result<Vec<String>> {
|
fn parse_output_cargo_config_build_target(stdout: String) -> anyhow::Result<Vec<String>> {
|
||||||
let trimmed = stdout.trim_start_matches("build.target = ").trim_matches('"');
|
let trimmed = stdout.trim_start_matches("build.target = ").trim_matches('"');
|
||||||
|
|
|
@ -25,10 +25,8 @@ use crate::{
|
||||||
cargo_workspace::{CargoMetadataConfig, DepKind, PackageData, RustLibSource},
|
cargo_workspace::{CargoMetadataConfig, DepKind, PackageData, RustLibSource},
|
||||||
env::{cargo_config_env, inject_cargo_env, inject_cargo_package_env, inject_rustc_tool_env},
|
env::{cargo_config_env, inject_cargo_env, inject_cargo_package_env, inject_rustc_tool_env},
|
||||||
project_json::{Crate, CrateArrayIdx},
|
project_json::{Crate, CrateArrayIdx},
|
||||||
rustc_cfg::{self, RustcCfgConfig},
|
|
||||||
sysroot::{SysrootCrate, SysrootMode},
|
sysroot::{SysrootCrate, SysrootMode},
|
||||||
target_data_layout::{self, RustcDataLayoutConfig},
|
toolchain_info::{rustc_cfg, target_data_layout, target_triple, QueryConfig},
|
||||||
target_triple::{self, TargetTipleConfig},
|
|
||||||
utf8_stdout, CargoConfig, CargoWorkspace, CfgOverrides, InvocationStrategy, ManifestPath,
|
utf8_stdout, CargoConfig, CargoWorkspace, CfgOverrides, InvocationStrategy, ManifestPath,
|
||||||
Package, ProjectJson, ProjectManifest, Sysroot, TargetData, TargetKind, WorkspaceBuildScripts,
|
Package, ProjectJson, ProjectManifest, Sysroot, TargetData, TargetKind, WorkspaceBuildScripts,
|
||||||
};
|
};
|
||||||
|
@ -177,7 +175,7 @@ fn get_toolchain_version(
|
||||||
extra_env: &FxHashMap<String, String>,
|
extra_env: &FxHashMap<String, String>,
|
||||||
prefix: &str,
|
prefix: &str,
|
||||||
) -> Result<Option<Version>, anyhow::Error> {
|
) -> Result<Option<Version>, anyhow::Error> {
|
||||||
let cargo_version = utf8_stdout({
|
let cargo_version = utf8_stdout(&mut {
|
||||||
let mut cmd = Sysroot::tool(sysroot, tool);
|
let mut cmd = Sysroot::tool(sysroot, tool);
|
||||||
cmd.envs(extra_env);
|
cmd.envs(extra_env);
|
||||||
cmd.arg("--version").current_dir(current_dir);
|
cmd.arg("--version").current_dir(current_dir);
|
||||||
|
@ -262,7 +260,7 @@ impl ProjectWorkspace {
|
||||||
None => Err(None),
|
None => Err(None),
|
||||||
};
|
};
|
||||||
let targets = target_triple::get(
|
let targets = target_triple::get(
|
||||||
TargetTipleConfig::Cargo(&sysroot, cargo_toml),
|
QueryConfig::Cargo(&sysroot, cargo_toml),
|
||||||
config.target.as_deref(),
|
config.target.as_deref(),
|
||||||
&config.extra_env,
|
&config.extra_env,
|
||||||
)
|
)
|
||||||
|
@ -312,14 +310,14 @@ impl ProjectWorkspace {
|
||||||
"cargo ",
|
"cargo ",
|
||||||
)?;
|
)?;
|
||||||
let rustc_cfg = rustc_cfg::get(
|
let rustc_cfg = rustc_cfg::get(
|
||||||
|
QueryConfig::Cargo(&sysroot, cargo_toml),
|
||||||
targets.first().map(Deref::deref),
|
targets.first().map(Deref::deref),
|
||||||
&config.extra_env,
|
&config.extra_env,
|
||||||
RustcCfgConfig::Cargo(&sysroot, cargo_toml),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let cfg_overrides = config.cfg_overrides.clone();
|
let cfg_overrides = config.cfg_overrides.clone();
|
||||||
let data_layout = target_data_layout::get(
|
let data_layout = target_data_layout::get(
|
||||||
RustcDataLayoutConfig::Cargo(&sysroot, cargo_toml),
|
QueryConfig::Cargo(&sysroot, cargo_toml),
|
||||||
targets.first().map(Deref::deref),
|
targets.first().map(Deref::deref),
|
||||||
&config.extra_env,
|
&config.extra_env,
|
||||||
);
|
);
|
||||||
|
@ -378,8 +376,8 @@ impl ProjectWorkspace {
|
||||||
project_json.sysroot_src.clone(),
|
project_json.sysroot_src.clone(),
|
||||||
&config.sysroot_query_metadata,
|
&config.sysroot_query_metadata,
|
||||||
);
|
);
|
||||||
let cfg_config = RustcCfgConfig::Rustc(&sysroot);
|
let cfg_config = QueryConfig::Rustc(&sysroot);
|
||||||
let data_layout_config = RustcDataLayoutConfig::Rustc(&sysroot);
|
let data_layout_config = QueryConfig::Rustc(&sysroot);
|
||||||
let toolchain = match get_toolchain_version(
|
let toolchain = match get_toolchain_version(
|
||||||
project_json.path(),
|
project_json.path(),
|
||||||
&sysroot,
|
&sysroot,
|
||||||
|
@ -395,7 +393,7 @@ impl ProjectWorkspace {
|
||||||
};
|
};
|
||||||
|
|
||||||
let target = config.target.as_deref();
|
let target = config.target.as_deref();
|
||||||
let rustc_cfg = rustc_cfg::get(target, &config.extra_env, cfg_config);
|
let rustc_cfg = rustc_cfg::get(cfg_config, target, &config.extra_env);
|
||||||
let data_layout = target_data_layout::get(data_layout_config, target, &config.extra_env);
|
let data_layout = target_data_layout::get(data_layout_config, target, &config.extra_env);
|
||||||
ProjectWorkspace {
|
ProjectWorkspace {
|
||||||
kind: ProjectWorkspaceKind::Json(project_json),
|
kind: ProjectWorkspaceKind::Json(project_json),
|
||||||
|
@ -432,17 +430,14 @@ impl ProjectWorkspace {
|
||||||
};
|
};
|
||||||
|
|
||||||
let targets = target_triple::get(
|
let targets = target_triple::get(
|
||||||
TargetTipleConfig::Cargo(&sysroot, detached_file),
|
QueryConfig::Cargo(&sysroot, detached_file),
|
||||||
config.target.as_deref(),
|
config.target.as_deref(),
|
||||||
&config.extra_env,
|
&config.extra_env,
|
||||||
)
|
)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
let rustc_cfg = rustc_cfg::get(None, &config.extra_env, RustcCfgConfig::Rustc(&sysroot));
|
let rustc_cfg = rustc_cfg::get(QueryConfig::Rustc(&sysroot), None, &config.extra_env);
|
||||||
let data_layout = target_data_layout::get(
|
let data_layout =
|
||||||
RustcDataLayoutConfig::Rustc(&sysroot),
|
target_data_layout::get(QueryConfig::Rustc(&sysroot), None, &config.extra_env);
|
||||||
None,
|
|
||||||
&config.extra_env,
|
|
||||||
);
|
|
||||||
|
|
||||||
let cargo_script = CargoWorkspace::fetch_metadata(
|
let cargo_script = CargoWorkspace::fetch_metadata(
|
||||||
detached_file,
|
detached_file,
|
||||||
|
@ -954,7 +949,7 @@ fn project_json_to_crate_graph(
|
||||||
|
|
||||||
let target_cfgs = match target.as_deref() {
|
let target_cfgs = match target.as_deref() {
|
||||||
Some(target) => cfg_cache.entry(target).or_insert_with(|| {
|
Some(target) => cfg_cache.entry(target).or_insert_with(|| {
|
||||||
rustc_cfg::get(Some(target), extra_env, RustcCfgConfig::Rustc(sysroot))
|
rustc_cfg::get(QueryConfig::Rustc(sysroot), Some(target), extra_env)
|
||||||
}),
|
}),
|
||||||
None => &rustc_cfg,
|
None => &rustc_cfg,
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,10 +10,10 @@ use ide::{AnalysisHost, DiagnosticCode, DiagnosticsConfig};
|
||||||
use itertools::Either;
|
use itertools::Either;
|
||||||
use paths::Utf8PathBuf;
|
use paths::Utf8PathBuf;
|
||||||
use profile::StopWatch;
|
use profile::StopWatch;
|
||||||
use project_model::target_data_layout::RustcDataLayoutConfig;
|
use project_model::toolchain_info::{target_data_layout, QueryConfig};
|
||||||
use project_model::{
|
use project_model::{
|
||||||
target_data_layout, CargoConfig, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind,
|
CargoConfig, ManifestPath, ProjectWorkspace, ProjectWorkspaceKind, RustLibSource, Sysroot,
|
||||||
RustLibSource, Sysroot, SysrootQueryMetadata,
|
SysrootQueryMetadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice};
|
use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice};
|
||||||
|
@ -79,11 +79,8 @@ impl Tester {
|
||||||
&cargo_config.extra_env,
|
&cargo_config.extra_env,
|
||||||
&SysrootQueryMetadata::CargoMetadata(Default::default()),
|
&SysrootQueryMetadata::CargoMetadata(Default::default()),
|
||||||
);
|
);
|
||||||
let data_layout = target_data_layout::get(
|
let data_layout =
|
||||||
RustcDataLayoutConfig::Rustc(&sysroot),
|
target_data_layout::get(QueryConfig::Rustc(&sysroot), None, &cargo_config.extra_env);
|
||||||
None,
|
|
||||||
&cargo_config.extra_env,
|
|
||||||
);
|
|
||||||
|
|
||||||
let workspace = ProjectWorkspace {
|
let workspace = ProjectWorkspace {
|
||||||
kind: ProjectWorkspaceKind::DetachedFile {
|
kind: ProjectWorkspaceKind::DetachedFile {
|
||||||
|
|
Loading…
Reference in a new issue