Merge #8774
8774: feat: Honor `.cargo/config.toml` r=matklad a=Veykril  Implements `cargo/.config` build target and cfg access by using unstable cargo options: - `cargo config get` to read the target triple out of the config to pass to `cargo metadata` --filter-platform - `cargo rustc --print` to read out the `rustc_cfgs`, this causes us to honor `rustflags` and the like. If those commands fail, due to not having a nightly toolchain present for example, they will fall back to invoking rustc directly as we currently do. I personally think it should be fine to use these unstable options as they are unlikely to change(even if they did it shouldn't be a problem due to the fallback) and don't burden the user if they do not have a nightly toolchain at hand since we fall back to the previous behaviour. cc #8741 Closes #6604, Closes #5904, Closes #8430, Closes #8480 Co-authored-by: Lukas Wirth <lukastw97@gmail.com>
This commit is contained in:
commit
6c0cdc5f55
@ -201,31 +201,12 @@ impl CargoWorkspace {
|
|||||||
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,43 @@ impl CargoWorkspace {
|
|||||||
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(&["-Z", "unstable-options", "config", "get", "build.target"])
|
||||||
|
.env("RUSTC_BOOTSTRAP", "1");
|
||||||
|
// 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,9 +2,12 @@
|
|||||||
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
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);
|
||||||
|
|
||||||
@ -16,19 +19,39 @@ pub(crate) fn get(target: Option<&str>) -> Vec<CfgFlag> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let rustc_cfgs = {
|
match get_rust_cfgs(cargo_toml, target) {
|
||||||
let mut cmd = Command::new(toolchain::rustc());
|
|
||||||
cmd.args(&["--print", "cfg", "-O"]);
|
|
||||||
if let Some(target) = target {
|
|
||||||
cmd.args(&["--target", target]);
|
|
||||||
}
|
|
||||||
utf8_stdout(cmd)
|
|
||||||
};
|
|
||||||
|
|
||||||
match rustc_cfgs {
|
|
||||||
Ok(rustc_cfgs) => res.extend(rustc_cfgs.lines().map(|it| it.parse().unwrap())),
|
Ok(rustc_cfgs) => res.extend(rustc_cfgs.lines().map(|it| it.parse().unwrap())),
|
||||||
Err(e) => log::error!("failed to get rustc cfgs: {:#}", e),
|
Err(e) => log::error!("failed to get rustc cfgs: {:#}", e),
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_rust_cfgs(cargo_toml: Option<&AbsPath>, target: Option<&str>) -> Result<String> {
|
||||||
|
let cargo_rust_cfgs = match cargo_toml {
|
||||||
|
Some(cargo_toml) => {
|
||||||
|
let mut cargo_config = Command::new(toolchain::cargo());
|
||||||
|
cargo_config
|
||||||
|
.current_dir(cargo_toml.parent().unwrap())
|
||||||
|
.args(&["-Z", "unstable-options", "rustc", "--print", "cfg"])
|
||||||
|
.env("RUSTC_BOOTSTRAP", "1");
|
||||||
|
if let Some(target) = target {
|
||||||
|
cargo_config.args(&["--target", target]);
|
||||||
|
}
|
||||||
|
utf8_stdout(cargo_config).ok()
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
match cargo_rust_cfgs {
|
||||||
|
Some(stdout) => Ok(stdout),
|
||||||
|
None => {
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -143,7 +143,8 @@ impl ProjectWorkspace {
|
|||||||
} 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 @@ impl ProjectWorkspace {
|
|||||||
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,
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user