diff options
Diffstat (limited to 'crates/project_model')
| -rw-r--r-- | crates/project_model/src/cargo_workspace.rs | 67 | ||||
| -rw-r--r-- | crates/project_model/src/rustc_cfg.rs | 45 | ||||
| -rw-r--r-- | crates/project_model/src/workspace.rs | 7 |
3 files changed, 82 insertions, 37 deletions
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs index bc6e20341..b18699b77 100644 --- a/crates/project_model/src/cargo_workspace.rs +++ b/crates/project_model/src/cargo_workspace.rs | |||
| @@ -201,31 +201,12 @@ impl CargoWorkspace { | |||
| 201 | if let Some(parent) = cargo_toml.parent() { | 201 | if let Some(parent) = cargo_toml.parent() { |
| 202 | meta.current_dir(parent.to_path_buf()); | 202 | meta.current_dir(parent.to_path_buf()); |
| 203 | } | 203 | } |
| 204 | let target = if let Some(target) = config.target.as_ref() { | 204 | let target = if let Some(target) = &config.target { |
| 205 | Some(target.clone()) | 205 | Some(target.clone()) |
| 206 | } else if let stdout @ Some(_) = cargo_config_build_target(cargo_toml) { | ||
| 207 | stdout | ||
| 206 | } else { | 208 | } else { |
| 207 | // cargo metadata defaults to giving information for _all_ targets. | 209 | rustc_discover_host_triple(cargo_toml) |
| 208 | // In the absence of a preference from the user, we use the host platform. | ||
| 209 | let mut rustc = Command::new(toolchain::rustc()); | ||
| 210 | rustc.current_dir(cargo_toml.parent().unwrap()).arg("-vV"); | ||
| 211 | log::debug!("Discovering host platform by {:?}", rustc); | ||
| 212 | match utf8_stdout(rustc) { | ||
| 213 | Ok(stdout) => { | ||
| 214 | let field = "host: "; | ||
| 215 | let target = stdout.lines().find_map(|l| l.strip_prefix(field)); | ||
| 216 | if let Some(target) = target { | ||
| 217 | Some(target.to_string()) | ||
| 218 | } else { | ||
| 219 | // If we fail to resolve the host platform, it's not the end of the world. | ||
| 220 | log::info!("rustc -vV did not report host platform, got:\n{}", stdout); | ||
| 221 | None | ||
| 222 | } | ||
| 223 | } | ||
| 224 | Err(e) => { | ||
| 225 | log::warn!("Failed to discover host platform: {}", e); | ||
| 226 | None | ||
| 227 | } | ||
| 228 | } | ||
| 229 | }; | 210 | }; |
| 230 | if let Some(target) = target { | 211 | if let Some(target) = target { |
| 231 | meta.other_options(vec![String::from("--filter-platform"), target]); | 212 | meta.other_options(vec![String::from("--filter-platform"), target]); |
| @@ -368,3 +349,43 @@ impl CargoWorkspace { | |||
| 368 | self.packages.iter().filter(|(_, v)| v.name == name).count() == 1 | 349 | self.packages.iter().filter(|(_, v)| v.name == name).count() == 1 |
| 369 | } | 350 | } |
| 370 | } | 351 | } |
| 352 | |||
| 353 | fn rustc_discover_host_triple(cargo_toml: &AbsPath) -> Option<String> { | ||
| 354 | let mut rustc = Command::new(toolchain::rustc()); | ||
| 355 | rustc.current_dir(cargo_toml.parent().unwrap()).arg("-vV"); | ||
| 356 | log::debug!("Discovering host platform by {:?}", rustc); | ||
| 357 | match utf8_stdout(rustc) { | ||
| 358 | Ok(stdout) => { | ||
| 359 | let field = "host: "; | ||
| 360 | let target = stdout.lines().find_map(|l| l.strip_prefix(field)); | ||
| 361 | if let Some(target) = target { | ||
| 362 | Some(target.to_string()) | ||
| 363 | } else { | ||
| 364 | // If we fail to resolve the host platform, it's not the end of the world. | ||
| 365 | log::info!("rustc -vV did not report host platform, got:\n{}", stdout); | ||
| 366 | None | ||
| 367 | } | ||
| 368 | } | ||
| 369 | Err(e) => { | ||
| 370 | log::warn!("Failed to discover host platform: {}", e); | ||
| 371 | None | ||
| 372 | } | ||
| 373 | } | ||
| 374 | } | ||
| 375 | |||
| 376 | fn cargo_config_build_target(cargo_toml: &AbsPath) -> Option<String> { | ||
| 377 | let mut cargo_config = Command::new(toolchain::cargo()); | ||
| 378 | cargo_config | ||
| 379 | .current_dir(cargo_toml.parent().unwrap()) | ||
| 380 | .args(&["-Z", "unstable-options", "config", "get", "build.target"]) | ||
| 381 | .env("RUSTC_BOOTSTRAP", "1"); | ||
| 382 | // if successful we receive `build.target = "target-triple"` | ||
| 383 | log::debug!("Discovering cargo config target by {:?}", cargo_config); | ||
| 384 | match utf8_stdout(cargo_config) { | ||
| 385 | Ok(stdout) => stdout | ||
| 386 | .strip_prefix("build.target = \"") | ||
| 387 | .and_then(|stdout| stdout.strip_suffix('"')) | ||
| 388 | .map(ToOwned::to_owned), | ||
| 389 | Err(_) => None, | ||
| 390 | } | ||
| 391 | } | ||
diff --git a/crates/project_model/src/rustc_cfg.rs b/crates/project_model/src/rustc_cfg.rs index 312708575..012eab256 100644 --- a/crates/project_model/src/rustc_cfg.rs +++ b/crates/project_model/src/rustc_cfg.rs | |||
| @@ -2,9 +2,12 @@ | |||
| 2 | 2 | ||
| 3 | use std::process::Command; | 3 | use std::process::Command; |
| 4 | 4 | ||
| 5 | use anyhow::Result; | ||
| 6 | use paths::AbsPath; | ||
| 7 | |||
| 5 | use crate::{cfg_flag::CfgFlag, utf8_stdout}; | 8 | use crate::{cfg_flag::CfgFlag, utf8_stdout}; |
| 6 | 9 | ||
| 7 | pub(crate) fn get(target: Option<&str>) -> Vec<CfgFlag> { | 10 | pub(crate) fn get(cargo_toml: Option<&AbsPath>, target: Option<&str>) -> Vec<CfgFlag> { |
| 8 | let _p = profile::span("rustc_cfg::get"); | 11 | let _p = profile::span("rustc_cfg::get"); |
| 9 | let mut res = Vec::with_capacity(6 * 2 + 1); | 12 | let mut res = Vec::with_capacity(6 * 2 + 1); |
| 10 | 13 | ||
| @@ -16,19 +19,39 @@ pub(crate) fn get(target: Option<&str>) -> Vec<CfgFlag> { | |||
| 16 | } | 19 | } |
| 17 | } | 20 | } |
| 18 | 21 | ||
| 19 | let rustc_cfgs = { | 22 | match get_rust_cfgs(cargo_toml, target) { |
| 20 | let mut cmd = Command::new(toolchain::rustc()); | ||
| 21 | cmd.args(&["--print", "cfg", "-O"]); | ||
| 22 | if let Some(target) = target { | ||
| 23 | cmd.args(&["--target", target]); | ||
| 24 | } | ||
| 25 | utf8_stdout(cmd) | ||
| 26 | }; | ||
| 27 | |||
| 28 | match rustc_cfgs { | ||
| 29 | Ok(rustc_cfgs) => res.extend(rustc_cfgs.lines().map(|it| it.parse().unwrap())), | 23 | Ok(rustc_cfgs) => res.extend(rustc_cfgs.lines().map(|it| it.parse().unwrap())), |
| 30 | Err(e) => log::error!("failed to get rustc cfgs: {:#}", e), | 24 | Err(e) => log::error!("failed to get rustc cfgs: {:#}", e), |
| 31 | } | 25 | } |
| 32 | 26 | ||
| 33 | res | 27 | res |
| 34 | } | 28 | } |
| 29 | |||
| 30 | fn get_rust_cfgs(cargo_toml: Option<&AbsPath>, target: Option<&str>) -> Result<String> { | ||
| 31 | let cargo_rust_cfgs = match cargo_toml { | ||
| 32 | Some(cargo_toml) => { | ||
| 33 | let mut cargo_config = Command::new(toolchain::cargo()); | ||
| 34 | cargo_config | ||
| 35 | .current_dir(cargo_toml.parent().unwrap()) | ||
| 36 | .args(&["-Z", "unstable-options", "rustc", "--print", "cfg"]) | ||
| 37 | .env("RUSTC_BOOTSTRAP", "1"); | ||
| 38 | if let Some(target) = target { | ||
| 39 | cargo_config.args(&["--target", target]); | ||
| 40 | } | ||
| 41 | utf8_stdout(cargo_config).ok() | ||
| 42 | } | ||
| 43 | None => None, | ||
| 44 | }; | ||
| 45 | match cargo_rust_cfgs { | ||
| 46 | Some(stdout) => Ok(stdout), | ||
| 47 | None => { | ||
| 48 | // using unstable cargo features failed, fall back to using plain rustc | ||
| 49 | let mut cmd = Command::new(toolchain::rustc()); | ||
| 50 | cmd.args(&["--print", "cfg", "-O"]); | ||
| 51 | if let Some(target) = target { | ||
| 52 | cmd.args(&["--target", target]); | ||
| 53 | } | ||
| 54 | utf8_stdout(cmd) | ||
| 55 | } | ||
| 56 | } | ||
| 57 | } | ||
diff --git a/crates/project_model/src/workspace.rs b/crates/project_model/src/workspace.rs index 2fcd0f8fa..84c702fdf 100644 --- a/crates/project_model/src/workspace.rs +++ b/crates/project_model/src/workspace.rs | |||
| @@ -143,7 +143,8 @@ impl ProjectWorkspace { | |||
| 143 | } else { | 143 | } else { |
| 144 | None | 144 | None |
| 145 | }; | 145 | }; |
| 146 | let rustc_cfg = rustc_cfg::get(config.target.as_deref()); | 146 | |
| 147 | let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref()); | ||
| 147 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } | 148 | ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } |
| 148 | } | 149 | } |
| 149 | }; | 150 | }; |
| @@ -159,7 +160,7 @@ impl ProjectWorkspace { | |||
| 159 | Some(path) => Some(Sysroot::load(path)?), | 160 | Some(path) => Some(Sysroot::load(path)?), |
| 160 | None => None, | 161 | None => None, |
| 161 | }; | 162 | }; |
| 162 | let rustc_cfg = rustc_cfg::get(target); | 163 | let rustc_cfg = rustc_cfg::get(None, target); |
| 163 | Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg }) | 164 | Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg }) |
| 164 | } | 165 | } |
| 165 | 166 | ||
| @@ -310,7 +311,7 @@ fn project_json_to_crate_graph( | |||
| 310 | 311 | ||
| 311 | let target_cfgs = match krate.target.as_deref() { | 312 | let target_cfgs = match krate.target.as_deref() { |
| 312 | Some(target) => { | 313 | Some(target) => { |
| 313 | cfg_cache.entry(target).or_insert_with(|| rustc_cfg::get(Some(target))) | 314 | cfg_cache.entry(target).or_insert_with(|| rustc_cfg::get(None, Some(target))) |
| 314 | } | 315 | } |
| 315 | None => &rustc_cfg, | 316 | None => &rustc_cfg, |
| 316 | }; | 317 | }; |
