mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-11-03 05:13:35 +00:00
Cleanup target fetching for cargo metadata
This commit is contained in:
parent
633a10cb58
commit
029261f9cc
10 changed files with 209 additions and 140 deletions
|
|
@ -13,8 +13,8 @@ use serde_json::from_value;
|
|||
use span::Edition;
|
||||
use toolchain::Tool;
|
||||
|
||||
use crate::{utf8_stdout, ManifestPath, Sysroot, SysrootQueryMetadata};
|
||||
use crate::{CfgOverrides, InvocationStrategy};
|
||||
use crate::{ManifestPath, Sysroot, SysrootQueryMetadata};
|
||||
|
||||
/// [`CargoWorkspace`] represents the logical structure of, well, a Cargo
|
||||
/// workspace. It pretty closely mirrors `cargo metadata` output.
|
||||
|
|
@ -251,6 +251,18 @@ impl TargetKind {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct CargoMetadataConfig {
|
||||
/// List of features to activate.
|
||||
pub features: CargoFeatures,
|
||||
/// rustc targets
|
||||
pub targets: Vec<String>,
|
||||
/// Extra args to pass to the cargo command.
|
||||
pub extra_args: Vec<String>,
|
||||
/// Extra env vars to set when invoking the cargo command
|
||||
pub extra_env: FxHashMap<String, String>,
|
||||
}
|
||||
|
||||
// Deserialize helper for the cargo metadata
|
||||
#[derive(Deserialize, Default)]
|
||||
struct PackageMetadata {
|
||||
|
|
@ -265,7 +277,7 @@ impl CargoWorkspace {
|
|||
pub fn fetch_metadata(
|
||||
cargo_toml: &ManifestPath,
|
||||
current_dir: &AbsPath,
|
||||
config: &CargoConfig,
|
||||
config: &CargoMetadataConfig,
|
||||
sysroot: &Sysroot,
|
||||
locked: bool,
|
||||
progress: &dyn Fn(String),
|
||||
|
|
@ -276,14 +288,12 @@ impl CargoWorkspace {
|
|||
fn fetch_metadata_(
|
||||
cargo_toml: &ManifestPath,
|
||||
current_dir: &AbsPath,
|
||||
config: &CargoConfig,
|
||||
config: &CargoMetadataConfig,
|
||||
sysroot: &Sysroot,
|
||||
locked: bool,
|
||||
no_deps: bool,
|
||||
progress: &dyn Fn(String),
|
||||
) -> anyhow::Result<(cargo_metadata::Metadata, Option<anyhow::Error>)> {
|
||||
let targets = find_list_of_build_targets(config, cargo_toml, sysroot);
|
||||
|
||||
let cargo = sysroot.tool(Tool::Cargo);
|
||||
let mut meta = MetadataCommand::new();
|
||||
meta.cargo_path(cargo.get_program());
|
||||
|
|
@ -319,12 +329,9 @@ impl CargoWorkspace {
|
|||
}
|
||||
}
|
||||
|
||||
if !targets.is_empty() {
|
||||
other_options.append(
|
||||
&mut targets
|
||||
.into_iter()
|
||||
.flat_map(|target| ["--filter-platform".to_owned(), target])
|
||||
.collect(),
|
||||
if !config.targets.is_empty() {
|
||||
other_options.extend(
|
||||
config.targets.iter().flat_map(|it| ["--filter-platform".to_owned(), it.clone()]),
|
||||
);
|
||||
}
|
||||
// The manifest is a rust file, so this means its a script manifest
|
||||
|
|
@ -596,79 +603,3 @@ impl CargoWorkspace {
|
|||
self.is_virtual_workspace
|
||||
}
|
||||
}
|
||||
|
||||
fn find_list_of_build_targets(
|
||||
config: &CargoConfig,
|
||||
cargo_toml: &ManifestPath,
|
||||
sysroot: &Sysroot,
|
||||
) -> Vec<String> {
|
||||
if let Some(target) = &config.target {
|
||||
return [target.into()].to_vec();
|
||||
}
|
||||
|
||||
let build_targets = cargo_config_build_target(cargo_toml, &config.extra_env, sysroot);
|
||||
if !build_targets.is_empty() {
|
||||
return build_targets;
|
||||
}
|
||||
|
||||
rustc_discover_host_triple(cargo_toml, &config.extra_env, sysroot).into_iter().collect()
|
||||
}
|
||||
|
||||
fn rustc_discover_host_triple(
|
||||
cargo_toml: &ManifestPath,
|
||||
extra_env: &FxHashMap<String, String>,
|
||||
sysroot: &Sysroot,
|
||||
) -> Option<String> {
|
||||
let mut rustc = sysroot.tool(Tool::Rustc);
|
||||
rustc.envs(extra_env);
|
||||
rustc.current_dir(cargo_toml.parent()).arg("-vV");
|
||||
tracing::debug!("Discovering host platform by {:?}", rustc);
|
||||
match utf8_stdout(rustc) {
|
||||
Ok(stdout) => {
|
||||
let field = "host: ";
|
||||
let target = stdout.lines().find_map(|l| l.strip_prefix(field));
|
||||
if let Some(target) = target {
|
||||
Some(target.to_owned())
|
||||
} else {
|
||||
// If we fail to resolve the host platform, it's not the end of the world.
|
||||
tracing::info!("rustc -vV did not report host platform, got:\n{}", stdout);
|
||||
None
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
tracing::warn!("Failed to discover host platform: {}", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn cargo_config_build_target(
|
||||
cargo_toml: &ManifestPath,
|
||||
extra_env: &FxHashMap<String, String>,
|
||||
sysroot: &Sysroot,
|
||||
) -> Vec<String> {
|
||||
let mut cargo_config = sysroot.tool(Tool::Cargo);
|
||||
cargo_config.envs(extra_env);
|
||||
cargo_config
|
||||
.current_dir(cargo_toml.parent())
|
||||
.args(["-Z", "unstable-options", "config", "get", "build.target"])
|
||||
.env("RUSTC_BOOTSTRAP", "1");
|
||||
// if successful we receive `build.target = "target-triple"`
|
||||
// or `build.target = ["<target 1>", ..]`
|
||||
tracing::debug!("Discovering cargo config target by {:?}", cargo_config);
|
||||
utf8_stdout(cargo_config).map(parse_output_cargo_config_build_target).unwrap_or_default()
|
||||
}
|
||||
|
||||
fn parse_output_cargo_config_build_target(stdout: String) -> Vec<String> {
|
||||
let trimmed = stdout.trim_start_matches("build.target = ").trim_matches('"');
|
||||
|
||||
if !trimmed.starts_with('[') {
|
||||
return [trimmed.to_owned()].to_vec();
|
||||
}
|
||||
|
||||
let res = serde_json::from_str(trimmed);
|
||||
if let Err(e) = &res {
|
||||
tracing::warn!("Failed to parse `build.target` as an array of target: {}`", e);
|
||||
}
|
||||
res.unwrap_or_default()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue