Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/project-model/src/cargo_workspace.rs')
| -rw-r--r-- | crates/project-model/src/cargo_workspace.rs | 105 |
1 files changed, 18 insertions, 87 deletions
diff --git a/crates/project-model/src/cargo_workspace.rs b/crates/project-model/src/cargo_workspace.rs index ba4946bf0b..836879c75b 100644 --- a/crates/project-model/src/cargo_workspace.rs +++ b/crates/project-model/src/cargo_workspace.rs @@ -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() -} |