-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Cleanup target fetching for cargo metadata
- Loading branch information
Showing
10 changed files
with
213 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
use anyhow::Context; | ||
use rustc_hash::FxHashMap; | ||
use toolchain::Tool; | ||
|
||
use crate::{utf8_stdout, ManifestPath, Sysroot}; | ||
|
||
/// Determines how `rustc --print target-spec-json` is discovered and invoked. | ||
pub(super) enum TargetTipleConfig<'a> { | ||
/// Use `rustc --print target-spec-json`, either from with the binary from the sysroot or by discovering via | ||
/// [`toolchain::rustc`]. | ||
#[expect(dead_code)] | ||
Rustc(&'a Sysroot), | ||
/// Use `cargo --print target-spec-json`, either from with the binary from the sysroot or by discovering via | ||
/// [`toolchain::cargo`]. | ||
Cargo(&'a Sysroot, &'a ManifestPath), | ||
} | ||
|
||
pub(super) fn get( | ||
config: TargetTipleConfig<'_>, | ||
target: Option<&str>, | ||
extra_env: &FxHashMap<String, String>, | ||
) -> anyhow::Result<Vec<String>> { | ||
if let Some(target) = target { | ||
return Ok(vec![target.to_owned()]); | ||
} | ||
|
||
let sysroot = match config { | ||
TargetTipleConfig::Cargo(sysroot, cargo_toml) => { | ||
match cargo_config_build_target(cargo_toml, extra_env, sysroot) { | ||
Ok(it) => return Ok(it), | ||
Err(e) => { | ||
tracing::warn!("failed to run `cargo rustc --print cfg`, falling back to invoking rustc directly: {e}"); | ||
sysroot | ||
} | ||
} | ||
} | ||
TargetTipleConfig::Rustc(sysroot) => sysroot, | ||
}; | ||
rustc_discover_host_triple(extra_env, sysroot).map(|it| vec![it]) | ||
} | ||
|
||
fn rustc_discover_host_triple( | ||
extra_env: &FxHashMap<String, String>, | ||
sysroot: &Sysroot, | ||
) -> anyhow::Result<String> { | ||
let mut rustc = sysroot.tool(Tool::Rustc); | ||
rustc.envs(extra_env); | ||
rustc.arg("-vV"); | ||
tracing::debug!("Discovering host platform by {:?}", rustc); | ||
let stdout = utf8_stdout(rustc).context("Failed to discover host platform")?; | ||
let field = "host: "; | ||
let target = stdout.lines().find_map(|l| l.strip_prefix(field)); | ||
if let Some(target) = target { | ||
Ok(target.to_owned()) | ||
} else { | ||
// If we fail to resolve the host platform, it's not the end of the world. | ||
Err(anyhow::format_err!("rustc -vV did not report host platform, got:\n{}", stdout)) | ||
} | ||
} | ||
|
||
fn cargo_config_build_target( | ||
cargo_toml: &ManifestPath, | ||
extra_env: &FxHashMap<String, String>, | ||
sysroot: &Sysroot, | ||
) -> anyhow::Result<Vec<String>> { | ||
let mut cargo_config = sysroot.tool(Tool::Cargo); | ||
cargo_config.envs(extra_env); | ||
cargo_config | ||
.current_dir(cargo_toml.parent()) | ||
.args(["-Z", "unstable-options", "config", "get", "build.target"]) | ||
.env("RUSTC_BOOTSTRAP", "1"); | ||
// if successful we receive `build.target = "target-triple"` | ||
// or `build.target = ["<target 1>", ..]` | ||
tracing::debug!("Discovering cargo config target by {:?}", cargo_config); | ||
utf8_stdout(cargo_config).and_then(parse_output_cargo_config_build_target) | ||
} | ||
|
||
fn parse_output_cargo_config_build_target(stdout: String) -> anyhow::Result<Vec<String>> { | ||
let trimmed = stdout.trim_start_matches("build.target = ").trim_matches('"'); | ||
|
||
if !trimmed.starts_with('[') { | ||
return Ok([trimmed.to_owned()].to_vec()); | ||
} | ||
|
||
serde_json::from_str(trimmed).context("Failed to parse `build.target` as an array of target") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.