aboutsummaryrefslogtreecommitdiff
path: root/crates/project_model
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-05-08 17:17:18 +0100
committerLukas Wirth <[email protected]>2021-05-08 17:17:18 +0100
commit8989fb8315538aece975663c3be4aba867e9ee86 (patch)
treed44aa077a01ccae27a94b01c58e7ecec3e3d2709 /crates/project_model
parent526040eea8886a748dfd0a5449526f37a8bcf6af (diff)
Discover rustc_cfg through unstable cargo options
Diffstat (limited to 'crates/project_model')
-rw-r--r--crates/project_model/src/cargo_workspace.rs71
-rw-r--r--crates/project_model/src/rustc_cfg.rs38
-rw-r--r--crates/project_model/src/workspace.rs7
3 files changed, 83 insertions, 33 deletions
diff --git a/crates/project_model/src/cargo_workspace.rs b/crates/project_model/src/cargo_workspace.rs
index bc6e20341..f1ad00d36 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,47 @@ 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
353fn 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
376fn cargo_config_build_target(cargo_toml: &AbsPath) -> Option<String> {
377 let mut cargo_config = Command::new(toolchain::cargo());
378 cargo_config.current_dir(cargo_toml.parent().unwrap()).args(&[
379 "+nightly",
380 "-Z",
381 "unstable-options",
382 "config",
383 "get",
384 "build.target",
385 ]);
386 // if successful we receive `build.target = "target-triple"`
387 log::debug!("Discovering cargo config target by {:?}", cargo_config);
388 match utf8_stdout(cargo_config) {
389 Ok(stdout) => stdout
390 .strip_prefix("build.target = \"")
391 .and_then(|stdout| stdout.strip_suffix('"'))
392 .map(ToOwned::to_owned),
393 Err(_) => None,
394 }
395}
diff --git a/crates/project_model/src/rustc_cfg.rs b/crates/project_model/src/rustc_cfg.rs
index 312708575..6de40cfe2 100644
--- a/crates/project_model/src/rustc_cfg.rs
+++ b/crates/project_model/src/rustc_cfg.rs
@@ -2,9 +2,11 @@
2 2
3use std::process::Command; 3use std::process::Command;
4 4
5use paths::AbsPath;
6
5use crate::{cfg_flag::CfgFlag, utf8_stdout}; 7use crate::{cfg_flag::CfgFlag, utf8_stdout};
6 8
7pub(crate) fn get(target: Option<&str>) -> Vec<CfgFlag> { 9pub(crate) fn get(cargo_toml: Option<&AbsPath>, target: Option<&str>) -> Vec<CfgFlag> {
8 let _p = profile::span("rustc_cfg::get"); 10 let _p = profile::span("rustc_cfg::get");
9 let mut res = Vec::with_capacity(6 * 2 + 1); 11 let mut res = Vec::with_capacity(6 * 2 + 1);
10 12
@@ -17,12 +19,34 @@ pub(crate) fn get(target: Option<&str>) -> Vec<CfgFlag> {
17 } 19 }
18 20
19 let rustc_cfgs = { 21 let rustc_cfgs = {
20 let mut cmd = Command::new(toolchain::rustc()); 22 cargo_toml
21 cmd.args(&["--print", "cfg", "-O"]); 23 .and_then(|cargo_toml| {
22 if let Some(target) = target { 24 let mut cargo_config = Command::new(toolchain::cargo());
23 cmd.args(&["--target", target]); 25 cargo_config.current_dir(cargo_toml.parent().unwrap()).args(&[
24 } 26 "+nightly",
25 utf8_stdout(cmd) 27 "-Z",
28 "unstable-options",
29 "rustc",
30 "--print",
31 "cfg",
32 ]);
33 if let Some(target) = target {
34 cargo_config.args(&["--target", target]);
35 }
36 utf8_stdout(cargo_config).ok()
37 })
38 .map_or_else(
39 || {
40 // using unstable cargo features failed, fall back to using plain rustc
41 let mut cmd = Command::new(toolchain::rustc());
42 cmd.args(&["--print", "cfg", "-O"]);
43 if let Some(target) = target {
44 cmd.args(&["--target", target]);
45 }
46 utf8_stdout(cmd)
47 },
48 Ok,
49 )
26 }; 50 };
27 51
28 match rustc_cfgs { 52 match rustc_cfgs {
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 };