aboutsummaryrefslogtreecommitdiff
path: root/crates/project_model/src/cargo_workspace.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/project_model/src/cargo_workspace.rs')
-rw-r--r--crates/project_model/src/cargo_workspace.rs48
1 files changed, 42 insertions, 6 deletions
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs
index 1700cb8a7..2ee4e88b2 100644
--- a/crates/project_model/src/cargo_workspace.rs
+++ b/crates/project_model/src/cargo_workspace.rs
@@ -3,9 +3,10 @@
3use std::{ 3use std::{
4 convert::TryInto, 4 convert::TryInto,
5 ffi::OsStr, 5 ffi::OsStr,
6 io::BufReader,
6 ops, 7 ops,
7 path::{Path, PathBuf}, 8 path::{Path, PathBuf},
8 process::Command, 9 process::{Command, Stdio},
9}; 10};
10 11
11use anyhow::{Context, Result}; 12use anyhow::{Context, Result};
@@ -15,6 +16,7 @@ use cargo_metadata::{BuildScript, CargoOpt, Message, MetadataCommand, PackageId}
15use itertools::Itertools; 16use itertools::Itertools;
16use paths::{AbsPath, AbsPathBuf}; 17use paths::{AbsPath, AbsPathBuf};
17use rustc_hash::FxHashMap; 18use rustc_hash::FxHashMap;
19use stdx::JodChild;
18 20
19use crate::cfg_flag::CfgFlag; 21use crate::cfg_flag::CfgFlag;
20use crate::utf8_stdout; 22use crate::utf8_stdout;
@@ -80,19 +82,35 @@ pub type Package = Idx<PackageData>;
80 82
81pub type Target = Idx<TargetData>; 83pub type Target = Idx<TargetData>;
82 84
85/// Information associated with a cargo crate
83#[derive(Debug, Clone, Eq, PartialEq)] 86#[derive(Debug, Clone, Eq, PartialEq)]
84pub struct PackageData { 87pub struct PackageData {
88 /// Version given in the `Cargo.toml`
85 pub version: String, 89 pub version: String,
90 /// Name as given in the `Cargo.toml`
86 pub name: String, 91 pub name: String,
92 /// Path containing the `Cargo.toml`
87 pub manifest: AbsPathBuf, 93 pub manifest: AbsPathBuf,
94 /// Targets provided by the crate (lib, bin, example, test, ...)
88 pub targets: Vec<Target>, 95 pub targets: Vec<Target>,
96 /// Is this package a member of the current workspace
89 pub is_member: bool, 97 pub is_member: bool,
98 /// List of packages this package depends on
90 pub dependencies: Vec<PackageDependency>, 99 pub dependencies: Vec<PackageDependency>,
100 /// Rust edition for this package
91 pub edition: Edition, 101 pub edition: Edition,
102 /// List of features to activate
92 pub features: Vec<String>, 103 pub features: Vec<String>,
104 /// List of config flags defined by this package's build script
93 pub cfgs: Vec<CfgFlag>, 105 pub cfgs: Vec<CfgFlag>,
106 /// List of cargo-related environment variables with their value
107 ///
108 /// If the package has a build script which defines environment variables,
109 /// they can also be found here.
94 pub envs: Vec<(String, String)>, 110 pub envs: Vec<(String, String)>,
111 /// Directory where a build script might place its output
95 pub out_dir: Option<AbsPathBuf>, 112 pub out_dir: Option<AbsPathBuf>,
113 /// Path to the proc-macro library file if this package exposes proc-macros
96 pub proc_macro_dylib_path: Option<AbsPathBuf>, 114 pub proc_macro_dylib_path: Option<AbsPathBuf>,
97} 115}
98 116
@@ -102,12 +120,18 @@ pub struct PackageDependency {
102 pub name: String, 120 pub name: String,
103} 121}
104 122
123/// Information associated with a package's target
105#[derive(Debug, Clone, Eq, PartialEq)] 124#[derive(Debug, Clone, Eq, PartialEq)]
106pub struct TargetData { 125pub struct TargetData {
126 /// Package that provided this target
107 pub package: Package, 127 pub package: Package,
128 /// Name as given in the `Cargo.toml` or generated from the file name
108 pub name: String, 129 pub name: String,
130 /// Path to the main source file of the target
109 pub root: AbsPathBuf, 131 pub root: AbsPathBuf,
132 /// Kind of target
110 pub kind: TargetKind, 133 pub kind: TargetKind,
134 /// Is this target a proc-macro
111 pub is_proc_macro: bool, 135 pub is_proc_macro: bool,
112} 136}
113 137
@@ -149,6 +173,7 @@ impl CargoWorkspace {
149 pub fn from_cargo_metadata( 173 pub fn from_cargo_metadata(
150 cargo_toml: &AbsPath, 174 cargo_toml: &AbsPath,
151 config: &CargoConfig, 175 config: &CargoConfig,
176 progress: &dyn Fn(String),
152 ) -> Result<CargoWorkspace> { 177 ) -> Result<CargoWorkspace> {
153 let mut meta = MetadataCommand::new(); 178 let mut meta = MetadataCommand::new();
154 meta.cargo_path(toolchain::cargo()); 179 meta.cargo_path(toolchain::cargo());
@@ -198,6 +223,9 @@ impl CargoWorkspace {
198 meta.other_options(vec![String::from("--filter-platform"), target]); 223 meta.other_options(vec![String::from("--filter-platform"), target]);
199 } 224 }
200 225
226 // FIXME: Currently MetadataCommand is not based on parse_stream,
227 // So we just report it as a whole
228 progress("metadata".to_string());
201 let mut meta = meta.exec().with_context(|| { 229 let mut meta = meta.exec().with_context(|| {
202 let cwd: Option<AbsPathBuf> = 230 let cwd: Option<AbsPathBuf> =
203 std::env::current_dir().ok().and_then(|p| p.try_into().ok()); 231 std::env::current_dir().ok().and_then(|p| p.try_into().ok());
@@ -221,7 +249,7 @@ impl CargoWorkspace {
221 let mut envs = FxHashMap::default(); 249 let mut envs = FxHashMap::default();
222 let mut proc_macro_dylib_paths = FxHashMap::default(); 250 let mut proc_macro_dylib_paths = FxHashMap::default();
223 if config.load_out_dirs_from_check { 251 if config.load_out_dirs_from_check {
224 let resources = load_extern_resources(cargo_toml, config)?; 252 let resources = load_extern_resources(cargo_toml, config, progress)?;
225 out_dir_by_id = resources.out_dirs; 253 out_dir_by_id = resources.out_dirs;
226 cfgs = resources.cfgs; 254 cfgs = resources.cfgs;
227 envs = resources.env; 255 envs = resources.env;
@@ -346,6 +374,7 @@ pub(crate) struct ExternResources {
346pub(crate) fn load_extern_resources( 374pub(crate) fn load_extern_resources(
347 cargo_toml: &Path, 375 cargo_toml: &Path,
348 cargo_features: &CargoConfig, 376 cargo_features: &CargoConfig,
377 progress: &dyn Fn(String),
349) -> Result<ExternResources> { 378) -> Result<ExternResources> {
350 let mut cmd = Command::new(toolchain::cargo()); 379 let mut cmd = Command::new(toolchain::cargo());
351 cmd.args(&["check", "--message-format=json", "--manifest-path"]).arg(cargo_toml); 380 cmd.args(&["check", "--message-format=json", "--manifest-path"]).arg(cargo_toml);
@@ -373,11 +402,14 @@ pub(crate) fn load_extern_resources(
373 } 402 }
374 } 403 }
375 404
376 let output = cmd.output()?; 405 cmd.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null());
377 406
378 let mut res = ExternResources::default(); 407 let mut child = cmd.spawn().map(JodChild)?;
408 let child_stdout = child.stdout.take().unwrap();
409 let stdout = BufReader::new(child_stdout);
379 410
380 for message in cargo_metadata::Message::parse_stream(output.stdout.as_slice()) { 411 let mut res = ExternResources::default();
412 for message in cargo_metadata::Message::parse_stream(stdout) {
381 if let Ok(message) = message { 413 if let Ok(message) = message {
382 match message { 414 match message {
383 Message::BuildScriptExecuted(BuildScript { 415 Message::BuildScriptExecuted(BuildScript {
@@ -410,6 +442,8 @@ pub(crate) fn load_extern_resources(
410 res.env.insert(package_id, env); 442 res.env.insert(package_id, env);
411 } 443 }
412 Message::CompilerArtifact(message) => { 444 Message::CompilerArtifact(message) => {
445 progress(format!("metadata {}", message.target.name));
446
413 if message.target.kind.contains(&"proc-macro".to_string()) { 447 if message.target.kind.contains(&"proc-macro".to_string()) {
414 let package_id = message.package_id; 448 let package_id = message.package_id;
415 // Skip rmeta file 449 // Skip rmeta file
@@ -420,7 +454,9 @@ pub(crate) fn load_extern_resources(
420 } 454 }
421 } 455 }
422 } 456 }
423 Message::CompilerMessage(_) => (), 457 Message::CompilerMessage(message) => {
458 progress(message.target.name.clone());
459 }
424 Message::Unknown => (), 460 Message::Unknown => (),
425 Message::BuildFinished(_) => {} 461 Message::BuildFinished(_) => {}
426 Message::TextLine(_) => {} 462 Message::TextLine(_) => {}