diff options
author | Aleksey Kladov <[email protected]> | 2020-07-23 17:57:27 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-07-23 18:03:17 +0100 |
commit | 7c0743293e5720a5be7b44b4a781b2982d63152a (patch) | |
tree | 151555d84672f020f79eb4cf34bb5e67ec106615 /crates/ra_project_model/src/lib.rs | |
parent | 243b997df4dfc07910d38022828bc0f1d4745c57 (diff) |
Require quotes around key-value cfg flags in rust-project.json
This matches rustc command-line flags, as well as the build.rs format.
Diffstat (limited to 'crates/ra_project_model/src/lib.rs')
-rw-r--r-- | crates/ra_project_model/src/lib.rs | 77 |
1 files changed, 30 insertions, 47 deletions
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 8053712ff..300e75135 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -3,11 +3,12 @@ | |||
3 | mod cargo_workspace; | 3 | mod cargo_workspace; |
4 | mod project_json; | 4 | mod project_json; |
5 | mod sysroot; | 5 | mod sysroot; |
6 | mod cfg_flag; | ||
6 | 7 | ||
7 | use std::{ | 8 | use std::{ |
8 | fs::{self, read_dir, ReadDir}, | 9 | fs::{self, read_dir, ReadDir}, |
9 | io, | 10 | io, |
10 | process::{Command, Output}, | 11 | process::Command, |
11 | }; | 12 | }; |
12 | 13 | ||
13 | use anyhow::{bail, Context, Result}; | 14 | use anyhow::{bail, Context, Result}; |
@@ -15,13 +16,15 @@ use paths::{AbsPath, AbsPathBuf}; | |||
15 | use ra_cfg::CfgOptions; | 16 | use ra_cfg::CfgOptions; |
16 | use ra_db::{CrateGraph, CrateId, CrateName, Edition, Env, FileId}; | 17 | use ra_db::{CrateGraph, CrateId, CrateName, Edition, Env, FileId}; |
17 | use rustc_hash::{FxHashMap, FxHashSet}; | 18 | use rustc_hash::{FxHashMap, FxHashSet}; |
18 | use stdx::split_delim; | 19 | |
20 | use crate::cfg_flag::CfgFlag; | ||
19 | 21 | ||
20 | pub use crate::{ | 22 | pub use crate::{ |
21 | cargo_workspace::{CargoConfig, CargoWorkspace, Package, Target, TargetKind}, | 23 | cargo_workspace::{CargoConfig, CargoWorkspace, Package, Target, TargetKind}, |
22 | project_json::{ProjectJson, ProjectJsonData}, | 24 | project_json::{ProjectJson, ProjectJsonData}, |
23 | sysroot::Sysroot, | 25 | sysroot::Sysroot, |
24 | }; | 26 | }; |
27 | |||
25 | pub use ra_proc_macro::ProcMacroClient; | 28 | pub use ra_proc_macro::ProcMacroClient; |
26 | 29 | ||
27 | #[derive(Debug, Clone, Eq, PartialEq)] | 30 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -250,7 +253,7 @@ impl ProjectWorkspace { | |||
250 | let mut crate_graph = CrateGraph::default(); | 253 | let mut crate_graph = CrateGraph::default(); |
251 | match self { | 254 | match self { |
252 | ProjectWorkspace::Json { project } => { | 255 | ProjectWorkspace::Json { project } => { |
253 | let mut target_cfg_map = FxHashMap::<Option<&str>, CfgOptions>::default(); | 256 | let mut cfg_cache: FxHashMap<Option<&str>, Vec<CfgFlag>> = FxHashMap::default(); |
254 | let crates: FxHashMap<_, _> = project | 257 | let crates: FxHashMap<_, _> = project |
255 | .crates | 258 | .crates |
256 | .iter() | 259 | .iter() |
@@ -266,11 +269,12 @@ impl ProjectWorkspace { | |||
266 | .map(|it| proc_macro_client.by_dylib_path(&it)); | 269 | .map(|it| proc_macro_client.by_dylib_path(&it)); |
267 | 270 | ||
268 | let target = krate.target.as_deref().or(target); | 271 | let target = krate.target.as_deref().or(target); |
269 | let target_cfgs = target_cfg_map | 272 | let target_cfgs = cfg_cache |
270 | .entry(target.clone()) | 273 | .entry(target) |
271 | .or_insert_with(|| get_rustc_cfg_options(target.as_deref())); | 274 | .or_insert_with(|| get_rustc_cfg_options(target)); |
272 | let mut cfg_options = krate.cfg.clone(); | 275 | |
273 | cfg_options.append(target_cfgs); | 276 | let mut cfg_options = CfgOptions::default(); |
277 | cfg_options.extend(target_cfgs.iter().chain(krate.cfg.iter()).cloned()); | ||
274 | 278 | ||
275 | // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env | 279 | // FIXME: No crate name in json definition such that we cannot add OUT_DIR to env |
276 | Some(( | 280 | Some(( |
@@ -307,7 +311,8 @@ impl ProjectWorkspace { | |||
307 | } | 311 | } |
308 | } | 312 | } |
309 | ProjectWorkspace::Cargo { cargo, sysroot } => { | 313 | ProjectWorkspace::Cargo { cargo, sysroot } => { |
310 | let mut cfg_options = get_rustc_cfg_options(target); | 314 | let mut cfg_options = CfgOptions::default(); |
315 | cfg_options.extend(get_rustc_cfg_options(target)); | ||
311 | 316 | ||
312 | let sysroot_crates: FxHashMap<_, _> = sysroot | 317 | let sysroot_crates: FxHashMap<_, _> = sysroot |
313 | .crates() | 318 | .crates() |
@@ -354,6 +359,7 @@ impl ProjectWorkspace { | |||
354 | 359 | ||
355 | // Add test cfg for non-sysroot crates | 360 | // Add test cfg for non-sysroot crates |
356 | cfg_options.insert_atom("test".into()); | 361 | cfg_options.insert_atom("test".into()); |
362 | cfg_options.insert_atom("debug_assertions".into()); | ||
357 | 363 | ||
358 | // Next, create crates for each package, target pair | 364 | // Next, create crates for each package, target pair |
359 | for pkg in cargo.packages() { | 365 | for pkg in cargo.packages() { |
@@ -367,15 +373,7 @@ impl ProjectWorkspace { | |||
367 | for feature in cargo[pkg].features.iter() { | 373 | for feature in cargo[pkg].features.iter() { |
368 | opts.insert_key_value("feature".into(), feature.into()); | 374 | opts.insert_key_value("feature".into(), feature.into()); |
369 | } | 375 | } |
370 | for cfg in cargo[pkg].cfgs.iter() { | 376 | opts.extend(cargo[pkg].cfgs.iter().cloned()); |
371 | match cfg.find('=') { | ||
372 | Some(split) => opts.insert_key_value( | ||
373 | cfg[..split].into(), | ||
374 | cfg[split + 1..].trim_matches('"').into(), | ||
375 | ), | ||
376 | None => opts.insert_atom(cfg.into()), | ||
377 | }; | ||
378 | } | ||
379 | opts | 377 | opts |
380 | }; | 378 | }; |
381 | let mut env = Env::default(); | 379 | let mut env = Env::default(); |
@@ -503,51 +501,35 @@ impl ProjectWorkspace { | |||
503 | } | 501 | } |
504 | } | 502 | } |
505 | 503 | ||
506 | fn get_rustc_cfg_options(target: Option<&str>) -> CfgOptions { | 504 | fn get_rustc_cfg_options(target: Option<&str>) -> Vec<CfgFlag> { |
507 | let mut cfg_options = CfgOptions::default(); | 505 | let mut res = Vec::new(); |
508 | 506 | ||
509 | // Some nightly-only cfgs, which are required for stdlib | 507 | // Some nightly-only cfgs, which are required for stdlib |
510 | { | 508 | res.push(CfgFlag::Atom("target_thread_local".into())); |
511 | cfg_options.insert_atom("target_thread_local".into()); | 509 | for &ty in ["8", "16", "32", "64", "cas", "ptr"].iter() { |
512 | for &target_has_atomic in ["8", "16", "32", "64", "cas", "ptr"].iter() { | 510 | for &key in ["target_has_atomic", "target_has_atomic_load_store"].iter() { |
513 | cfg_options.insert_key_value("target_has_atomic".into(), target_has_atomic.into()); | 511 | res.push(CfgFlag::KeyValue { key: key.to_string(), value: ty.into() }); |
514 | cfg_options | ||
515 | .insert_key_value("target_has_atomic_load_store".into(), target_has_atomic.into()); | ||
516 | } | 512 | } |
517 | } | 513 | } |
518 | 514 | ||
519 | let rustc_cfgs = || -> Result<String> { | 515 | let rustc_cfgs = { |
520 | // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here. | ||
521 | let mut cmd = Command::new(ra_toolchain::rustc()); | 516 | let mut cmd = Command::new(ra_toolchain::rustc()); |
522 | cmd.args(&["--print", "cfg", "-O"]); | 517 | cmd.args(&["--print", "cfg", "-O"]); |
523 | if let Some(target) = target { | 518 | if let Some(target) = target { |
524 | cmd.args(&["--target", target]); | 519 | cmd.args(&["--target", target]); |
525 | } | 520 | } |
526 | let output = output(cmd)?; | 521 | utf8_stdout(cmd) |
527 | Ok(String::from_utf8(output.stdout)?) | 522 | }; |
528 | }(); | ||
529 | 523 | ||
530 | match rustc_cfgs { | 524 | match rustc_cfgs { |
531 | Ok(rustc_cfgs) => { | 525 | Ok(rustc_cfgs) => res.extend(rustc_cfgs.lines().map(|it| it.parse().unwrap())), |
532 | for line in rustc_cfgs.lines() { | ||
533 | match split_delim(line, '=') { | ||
534 | None => cfg_options.insert_atom(line.into()), | ||
535 | Some((key, value)) => { | ||
536 | let value = value.trim_matches('"'); | ||
537 | cfg_options.insert_key_value(key.into(), value.into()); | ||
538 | } | ||
539 | } | ||
540 | } | ||
541 | } | ||
542 | Err(e) => log::error!("failed to get rustc cfgs: {:#}", e), | 526 | Err(e) => log::error!("failed to get rustc cfgs: {:#}", e), |
543 | } | 527 | } |
544 | 528 | ||
545 | cfg_options.insert_atom("debug_assertions".into()); | 529 | res |
546 | |||
547 | cfg_options | ||
548 | } | 530 | } |
549 | 531 | ||
550 | fn output(mut cmd: Command) -> Result<Output> { | 532 | fn utf8_stdout(mut cmd: Command) -> Result<String> { |
551 | let output = cmd.output().with_context(|| format!("{:?} failed", cmd))?; | 533 | let output = cmd.output().with_context(|| format!("{:?} failed", cmd))?; |
552 | if !output.status.success() { | 534 | if !output.status.success() { |
553 | match String::from_utf8(output.stderr) { | 535 | match String::from_utf8(output.stderr) { |
@@ -557,5 +539,6 @@ fn output(mut cmd: Command) -> Result<Output> { | |||
557 | _ => bail!("{:?} failed, {}", cmd, output.status), | 539 | _ => bail!("{:?} failed, {}", cmd, output.status), |
558 | } | 540 | } |
559 | } | 541 | } |
560 | Ok(output) | 542 | let stdout = String::from_utf8(output.stdout)?; |
543 | Ok(stdout) | ||
561 | } | 544 | } |