Discover rustc_cfg through unstable cargo options

This commit is contained in:
Lukas Wirth 2021-05-08 18:17:18 +02:00
parent 526040eea8
commit 8989fb8315
3 changed files with 83 additions and 33 deletions

View File

@ -201,31 +201,12 @@ pub fn from_cargo_metadata(
if let Some(parent) = cargo_toml.parent() { if let Some(parent) = cargo_toml.parent() {
meta.current_dir(parent.to_path_buf()); meta.current_dir(parent.to_path_buf());
} }
let target = if let Some(target) = config.target.as_ref() { let target = if let Some(target) = &config.target {
Some(target.clone()) Some(target.clone())
} else if let stdout @ Some(_) = cargo_config_build_target(cargo_toml) {
stdout
} else { } else {
// cargo metadata defaults to giving information for _all_ targets. rustc_discover_host_triple(cargo_toml)
// In the absence of a preference from the user, we use the host platform.
let mut rustc = Command::new(toolchain::rustc());
rustc.current_dir(cargo_toml.parent().unwrap()).arg("-vV");
log::debug!("Discovering host platform by {:?}", rustc);
match utf8_stdout(rustc) {
Ok(stdout) => {
let field = "host: ";
let target = stdout.lines().find_map(|l| l.strip_prefix(field));
if let Some(target) = target {
Some(target.to_string())
} else {
// If we fail to resolve the host platform, it's not the end of the world.
log::info!("rustc -vV did not report host platform, got:\n{}", stdout);
None
}
}
Err(e) => {
log::warn!("Failed to discover host platform: {}", e);
None
}
}
}; };
if let Some(target) = target { if let Some(target) = target {
meta.other_options(vec![String::from("--filter-platform"), target]); meta.other_options(vec![String::from("--filter-platform"), target]);
@ -368,3 +349,47 @@ fn is_unique(&self, name: &str) -> bool {
self.packages.iter().filter(|(_, v)| v.name == name).count() == 1 self.packages.iter().filter(|(_, v)| v.name == name).count() == 1
} }
} }
fn rustc_discover_host_triple(cargo_toml: &AbsPath) -> Option<String> {
let mut rustc = Command::new(toolchain::rustc());
rustc.current_dir(cargo_toml.parent().unwrap()).arg("-vV");
log::debug!("Discovering host platform by {:?}", rustc);
match utf8_stdout(rustc) {
Ok(stdout) => {
let field = "host: ";
let target = stdout.lines().find_map(|l| l.strip_prefix(field));
if let Some(target) = target {
Some(target.to_string())
} else {
// If we fail to resolve the host platform, it's not the end of the world.
log::info!("rustc -vV did not report host platform, got:\n{}", stdout);
None
}
}
Err(e) => {
log::warn!("Failed to discover host platform: {}", e);
None
}
}
}
fn cargo_config_build_target(cargo_toml: &AbsPath) -> Option<String> {
let mut cargo_config = Command::new(toolchain::cargo());
cargo_config.current_dir(cargo_toml.parent().unwrap()).args(&[
"+nightly",
"-Z",
"unstable-options",
"config",
"get",
"build.target",
]);
// if successful we receive `build.target = "target-triple"`
log::debug!("Discovering cargo config target by {:?}", cargo_config);
match utf8_stdout(cargo_config) {
Ok(stdout) => stdout
.strip_prefix("build.target = \"")
.and_then(|stdout| stdout.strip_suffix('"'))
.map(ToOwned::to_owned),
Err(_) => None,
}
}

View File

@ -2,9 +2,11 @@
use std::process::Command; use std::process::Command;
use paths::AbsPath;
use crate::{cfg_flag::CfgFlag, utf8_stdout}; use crate::{cfg_flag::CfgFlag, utf8_stdout};
pub(crate) fn get(target: Option<&str>) -> Vec<CfgFlag> { pub(crate) fn get(cargo_toml: Option<&AbsPath>, target: Option<&str>) -> Vec<CfgFlag> {
let _p = profile::span("rustc_cfg::get"); let _p = profile::span("rustc_cfg::get");
let mut res = Vec::with_capacity(6 * 2 + 1); let mut res = Vec::with_capacity(6 * 2 + 1);
@ -17,12 +19,34 @@ pub(crate) fn get(target: Option<&str>) -> Vec<CfgFlag> {
} }
let rustc_cfgs = { let rustc_cfgs = {
let mut cmd = Command::new(toolchain::rustc()); cargo_toml
cmd.args(&["--print", "cfg", "-O"]); .and_then(|cargo_toml| {
if let Some(target) = target { let mut cargo_config = Command::new(toolchain::cargo());
cmd.args(&["--target", target]); cargo_config.current_dir(cargo_toml.parent().unwrap()).args(&[
} "+nightly",
utf8_stdout(cmd) "-Z",
"unstable-options",
"rustc",
"--print",
"cfg",
]);
if let Some(target) = target {
cargo_config.args(&["--target", target]);
}
utf8_stdout(cargo_config).ok()
})
.map_or_else(
|| {
// using unstable cargo features failed, fall back to using plain rustc
let mut cmd = Command::new(toolchain::rustc());
cmd.args(&["--print", "cfg", "-O"]);
if let Some(target) = target {
cmd.args(&["--target", target]);
}
utf8_stdout(cmd)
},
Ok,
)
}; };
match rustc_cfgs { match rustc_cfgs {

View File

@ -143,7 +143,8 @@ pub fn load(
} else { } else {
None None
}; };
let rustc_cfg = rustc_cfg::get(config.target.as_deref());
let rustc_cfg = rustc_cfg::get(Some(&cargo_toml), config.target.as_deref());
ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg } ProjectWorkspace::Cargo { cargo, sysroot, rustc, rustc_cfg }
} }
}; };
@ -159,7 +160,7 @@ pub fn load_inline(
Some(path) => Some(Sysroot::load(path)?), Some(path) => Some(Sysroot::load(path)?),
None => None, None => None,
}; };
let rustc_cfg = rustc_cfg::get(target); let rustc_cfg = rustc_cfg::get(None, target);
Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg }) Ok(ProjectWorkspace::Json { project: project_json, sysroot, rustc_cfg })
} }
@ -310,7 +311,7 @@ fn project_json_to_crate_graph(
let target_cfgs = match krate.target.as_deref() { let target_cfgs = match krate.target.as_deref() {
Some(target) => { Some(target) => {
cfg_cache.entry(target).or_insert_with(|| rustc_cfg::get(Some(target))) cfg_cache.entry(target).or_insert_with(|| rustc_cfg::get(None, Some(target)))
} }
None => &rustc_cfg, None => &rustc_cfg,
}; };