Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/project-model/src/toolchain_info/target_tuple.rs')
-rw-r--r--crates/project-model/src/toolchain_info/target_tuple.rs48
1 files changed, 37 insertions, 11 deletions
diff --git a/crates/project-model/src/toolchain_info/target_tuple.rs b/crates/project-model/src/toolchain_info/target_tuple.rs
index 9f12ededb6..12c64b5928 100644
--- a/crates/project-model/src/toolchain_info/target_tuple.rs
+++ b/crates/project-model/src/toolchain_info/target_tuple.rs
@@ -53,7 +53,7 @@ fn rustc_discover_host_tuple(
}
fn cargo_config_build_target(config: &CargoConfigFile) -> Option<Vec<String>> {
- match parse_json_cargo_config_build_target(config) {
+ match parse_toml_cargo_config_build_target(config) {
Ok(v) => v,
Err(e) => {
tracing::debug!("Failed to discover cargo config build target {e:?}");
@@ -63,18 +63,44 @@ fn cargo_config_build_target(config: &CargoConfigFile) -> Option<Vec<String>> {
}
// Parses `"build.target = [target-tuple, target-tuple, ...]"` or `"build.target = "target-tuple"`
-fn parse_json_cargo_config_build_target(
+fn parse_toml_cargo_config_build_target(
config: &CargoConfigFile,
) -> anyhow::Result<Option<Vec<String>>> {
- let target = config.get("build").and_then(|v| v.as_object()).and_then(|m| m.get("target"));
- match target {
- Some(serde_json::Value::String(s)) => Ok(Some(vec![s.to_owned()])),
- Some(v) => serde_json::from_value(v.clone())
- .map(Option::Some)
- .context("Failed to parse `build.target` as an array of target"),
- // t`error: config value `build.target` is not set`, in which case we
- // don't wanna log the error
- None => Ok(None),
+ let Some(config_reader) = config.read() else {
+ return Ok(None);
+ };
+ let Some(target) = config_reader.get_spanned(["build", "target"]) else {
+ return Ok(None);
+ };
+
+ // if the target ends with `.json`, join it to the config file's parent dir.
+ // See https://github.com/rust-lang/cargo/blob/f7acf448fc127df9a77c52cc2bba027790ac4931/src/cargo/core/compiler/compile_kind.rs#L171-L192
+ let join_to_origin_if_json_path = |s: &str, spanned: &toml::Spanned<toml::de::DeValue<'_>>| {
+ if s.ends_with(".json") {
+ config_reader
+ .get_origin_root(spanned)
+ .map(|p| p.join(s).to_string())
+ .unwrap_or_else(|| s.to_owned())
+ } else {
+ s.to_owned()
+ }
+ };
+
+ let parse_err = "Failed to parse `build.target` as an array of target";
+
+ match target.as_ref() {
+ toml::de::DeValue::String(s) => {
+ Ok(Some(vec![join_to_origin_if_json_path(s.as_ref(), target)]))
+ }
+ toml::de::DeValue::Array(arr) => arr
+ .iter()
+ .map(|v| {
+ let s = v.as_ref().as_str().context(parse_err)?;
+ Ok(join_to_origin_if_json_path(s, v))
+ })
+ .collect::<anyhow::Result<_>>()
+ .map(Option::Some),
+ _ => Err(anyhow::anyhow!(parse_err)),
}
}