diff options
author | Emil Lauridsen <[email protected]> | 2020-03-16 12:43:29 +0000 |
---|---|---|
committer | Emil Lauridsen <[email protected]> | 2020-03-17 13:47:05 +0000 |
commit | 33c6c7abc6621f8b0cf083a98f7e4788cf4b5b54 (patch) | |
tree | 4b763fd11f25db269eacd9302042a54b50eda174 /crates/ra_project_model/src | |
parent | 2720e2374be951bb762ff2815dd67c7ffe3419b7 (diff) |
Support loading OUT_DIR from cargo check at launch
Diffstat (limited to 'crates/ra_project_model/src')
-rw-r--r-- | crates/ra_project_model/src/cargo_workspace.rs | 67 | ||||
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 43 |
2 files changed, 101 insertions, 9 deletions
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index 4fea459d5..eeeb10233 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs | |||
@@ -3,8 +3,9 @@ | |||
3 | use std::path::{Path, PathBuf}; | 3 | use std::path::{Path, PathBuf}; |
4 | 4 | ||
5 | use anyhow::{Context, Result}; | 5 | use anyhow::{Context, Result}; |
6 | use cargo_metadata::{CargoOpt, MetadataCommand}; | 6 | use cargo_metadata::{CargoOpt, Message, MetadataCommand, PackageId}; |
7 | use ra_arena::{impl_arena_id, Arena, RawId}; | 7 | use ra_arena::{impl_arena_id, Arena, RawId}; |
8 | use ra_cargo_watch::run_cargo; | ||
8 | use ra_db::Edition; | 9 | use ra_db::Edition; |
9 | use rustc_hash::FxHashMap; | 10 | use rustc_hash::FxHashMap; |
10 | use serde::Deserialize; | 11 | use serde::Deserialize; |
@@ -35,11 +36,19 @@ pub struct CargoFeatures { | |||
35 | /// List of features to activate. | 36 | /// List of features to activate. |
36 | /// This will be ignored if `cargo_all_features` is true. | 37 | /// This will be ignored if `cargo_all_features` is true. |
37 | pub features: Vec<String>, | 38 | pub features: Vec<String>, |
39 | |||
40 | /// Runs cargo check on launch to figure out the correct values of OUT_DIR | ||
41 | pub load_out_dirs_from_check: bool, | ||
38 | } | 42 | } |
39 | 43 | ||
40 | impl Default for CargoFeatures { | 44 | impl Default for CargoFeatures { |
41 | fn default() -> Self { | 45 | fn default() -> Self { |
42 | CargoFeatures { no_default_features: false, all_features: true, features: Vec::new() } | 46 | CargoFeatures { |
47 | no_default_features: false, | ||
48 | all_features: true, | ||
49 | features: Vec::new(), | ||
50 | load_out_dirs_from_check: false, | ||
51 | } | ||
43 | } | 52 | } |
44 | } | 53 | } |
45 | 54 | ||
@@ -60,6 +69,7 @@ struct PackageData { | |||
60 | dependencies: Vec<PackageDependency>, | 69 | dependencies: Vec<PackageDependency>, |
61 | edition: Edition, | 70 | edition: Edition, |
62 | features: Vec<String>, | 71 | features: Vec<String>, |
72 | out_dir: Option<PathBuf>, | ||
63 | } | 73 | } |
64 | 74 | ||
65 | #[derive(Debug, Clone)] | 75 | #[derive(Debug, Clone)] |
@@ -131,6 +141,9 @@ impl Package { | |||
131 | ) -> impl Iterator<Item = &'a PackageDependency> + 'a { | 141 | ) -> impl Iterator<Item = &'a PackageDependency> + 'a { |
132 | ws.packages[self].dependencies.iter() | 142 | ws.packages[self].dependencies.iter() |
133 | } | 143 | } |
144 | pub fn out_dir(self, ws: &CargoWorkspace) -> Option<&Path> { | ||
145 | ws.packages[self].out_dir.as_ref().map(|od| od.as_path()) | ||
146 | } | ||
134 | } | 147 | } |
135 | 148 | ||
136 | impl Target { | 149 | impl Target { |
@@ -173,6 +186,12 @@ impl CargoWorkspace { | |||
173 | let meta = meta.exec().with_context(|| { | 186 | let meta = meta.exec().with_context(|| { |
174 | format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display()) | 187 | format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display()) |
175 | })?; | 188 | })?; |
189 | |||
190 | let mut out_dir_by_id = FxHashMap::default(); | ||
191 | if cargo_features.load_out_dirs_from_check { | ||
192 | out_dir_by_id = load_out_dirs(cargo_toml, cargo_features); | ||
193 | } | ||
194 | |||
176 | let mut pkg_by_id = FxHashMap::default(); | 195 | let mut pkg_by_id = FxHashMap::default(); |
177 | let mut packages = Arena::default(); | 196 | let mut packages = Arena::default(); |
178 | let mut targets = Arena::default(); | 197 | let mut targets = Arena::default(); |
@@ -193,6 +212,7 @@ impl CargoWorkspace { | |||
193 | edition, | 212 | edition, |
194 | dependencies: Vec::new(), | 213 | dependencies: Vec::new(), |
195 | features: Vec::new(), | 214 | features: Vec::new(), |
215 | out_dir: out_dir_by_id.get(&id).cloned(), | ||
196 | }); | 216 | }); |
197 | let pkg_data = &mut packages[pkg]; | 217 | let pkg_data = &mut packages[pkg]; |
198 | pkg_by_id.insert(id, pkg); | 218 | pkg_by_id.insert(id, pkg); |
@@ -252,3 +272,46 @@ impl CargoWorkspace { | |||
252 | &self.workspace_root | 272 | &self.workspace_root |
253 | } | 273 | } |
254 | } | 274 | } |
275 | |||
276 | pub fn load_out_dirs( | ||
277 | cargo_toml: &Path, | ||
278 | cargo_features: &CargoFeatures, | ||
279 | ) -> FxHashMap<PackageId, PathBuf> { | ||
280 | let mut args: Vec<String> = vec![ | ||
281 | "check".to_string(), | ||
282 | "--message-format=json".to_string(), | ||
283 | "--manifest-path".to_string(), | ||
284 | format!("{}", cargo_toml.display()), | ||
285 | ]; | ||
286 | |||
287 | if cargo_features.all_features { | ||
288 | args.push("--all-features".to_string()); | ||
289 | } else if cargo_features.no_default_features { | ||
290 | // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures` | ||
291 | // https://github.com/oli-obk/cargo_metadata/issues/79 | ||
292 | args.push("--no-default-features".to_string()); | ||
293 | } else if !cargo_features.features.is_empty() { | ||
294 | for feature in &cargo_features.features { | ||
295 | args.push(feature.clone()); | ||
296 | } | ||
297 | } | ||
298 | |||
299 | let mut res = FxHashMap::default(); | ||
300 | let mut child = run_cargo(&args, cargo_toml.parent(), |message| { | ||
301 | match message { | ||
302 | Message::BuildScriptExecuted(message) => { | ||
303 | let package_id = message.package_id; | ||
304 | let out_dir = message.out_dir; | ||
305 | res.insert(package_id, out_dir); | ||
306 | } | ||
307 | |||
308 | Message::CompilerArtifact(_) => (), | ||
309 | Message::CompilerMessage(_) => (), | ||
310 | Message::Unknown => (), | ||
311 | } | ||
312 | true | ||
313 | }); | ||
314 | |||
315 | let _ = child.wait(); | ||
316 | res | ||
317 | } | ||
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 897874813..43f834253 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -150,6 +150,21 @@ impl ProjectWorkspace { | |||
150 | } | 150 | } |
151 | } | 151 | } |
152 | 152 | ||
153 | pub fn out_dirs(&self) -> Vec<PathBuf> { | ||
154 | match self { | ||
155 | ProjectWorkspace::Json { project: _project } => vec![], | ||
156 | ProjectWorkspace::Cargo { cargo, sysroot: _sysroot } => { | ||
157 | let mut out_dirs = Vec::with_capacity(cargo.packages().len()); | ||
158 | for pkg in cargo.packages() { | ||
159 | if let Some(out_dir) = pkg.out_dir(&cargo) { | ||
160 | out_dirs.push(out_dir.to_path_buf()); | ||
161 | } | ||
162 | } | ||
163 | out_dirs | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | |||
153 | pub fn n_packages(&self) -> usize { | 168 | pub fn n_packages(&self) -> usize { |
154 | match self { | 169 | match self { |
155 | ProjectWorkspace::Json { project } => project.crates.len(), | 170 | ProjectWorkspace::Json { project } => project.crates.len(), |
@@ -162,7 +177,8 @@ impl ProjectWorkspace { | |||
162 | pub fn to_crate_graph( | 177 | pub fn to_crate_graph( |
163 | &self, | 178 | &self, |
164 | default_cfg_options: &CfgOptions, | 179 | default_cfg_options: &CfgOptions, |
165 | outdirs: &FxHashMap<String, (ExternSourceId, String)>, | 180 | additional_out_dirs: &FxHashMap<String, PathBuf>, |
181 | extern_source_roots: &FxHashMap<PathBuf, ExternSourceId>, | ||
166 | load: &mut dyn FnMut(&Path) -> Option<FileId>, | 182 | load: &mut dyn FnMut(&Path) -> Option<FileId>, |
167 | ) -> CrateGraph { | 183 | ) -> CrateGraph { |
168 | let mut crate_graph = CrateGraph::default(); | 184 | let mut crate_graph = CrateGraph::default(); |
@@ -237,9 +253,11 @@ impl ProjectWorkspace { | |||
237 | 253 | ||
238 | let mut env = Env::default(); | 254 | let mut env = Env::default(); |
239 | let mut extern_source = ExternSource::default(); | 255 | let mut extern_source = ExternSource::default(); |
240 | if let Some((id, path)) = outdirs.get(krate.name(&sysroot)) { | 256 | if let Some(path) = additional_out_dirs.get(krate.name(&sysroot)) { |
241 | env.set("OUT_DIR", path.clone()); | 257 | env.set("OUT_DIR", path.to_string_lossy().to_string()); |
242 | extern_source.set_extern_path(&path, *id); | 258 | if let Some(extern_source_id) = extern_source_roots.get(path) { |
259 | extern_source.set_extern_path(&path, *extern_source_id); | ||
260 | } | ||
243 | } | 261 | } |
244 | 262 | ||
245 | let crate_id = crate_graph.add_crate_root( | 263 | let crate_id = crate_graph.add_crate_root( |
@@ -292,9 +310,20 @@ impl ProjectWorkspace { | |||
292 | }; | 310 | }; |
293 | let mut env = Env::default(); | 311 | let mut env = Env::default(); |
294 | let mut extern_source = ExternSource::default(); | 312 | let mut extern_source = ExternSource::default(); |
295 | if let Some((id, path)) = outdirs.get(pkg.name(&cargo)) { | 313 | if let Some(out_dir) = dbg!(pkg.out_dir(cargo)) { |
296 | env.set("OUT_DIR", path.clone()); | 314 | env.set("OUT_DIR", out_dir.to_string_lossy().to_string()); |
297 | extern_source.set_extern_path(&path, *id); | 315 | if let Some(extern_source_id) = |
316 | dbg!(dbg!(&extern_source_roots).get(out_dir)) | ||
317 | { | ||
318 | extern_source.set_extern_path(&out_dir, *extern_source_id); | ||
319 | } | ||
320 | } else { | ||
321 | if let Some(path) = additional_out_dirs.get(pkg.name(&cargo)) { | ||
322 | env.set("OUT_DIR", path.to_string_lossy().to_string()); | ||
323 | if let Some(extern_source_id) = extern_source_roots.get(path) { | ||
324 | extern_source.set_extern_path(&path, *extern_source_id); | ||
325 | } | ||
326 | } | ||
298 | } | 327 | } |
299 | let crate_id = crate_graph.add_crate_root( | 328 | let crate_id = crate_graph.add_crate_root( |
300 | file_id, | 329 | file_id, |