summaryrefslogtreecommitdiffstats
path: root/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs
blob: 42c06ad0ed3717ba1388d721f8b806080e5f1ab7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//! Runs `rustc --print target-spec-json` to get the target_data_layout.
use std::process::Command;

use anyhow::Result;
use rustc_hash::FxHashMap;

use crate::{utf8_stdout, ManifestPath};

pub fn get(
    cargo_toml: Option<&ManifestPath>,
    target: Option<&str>,
    extra_env: &FxHashMap<String, String>,
) -> Result<String> {
    let output = (|| {
        if let Some(cargo_toml) = cargo_toml {
            let mut cmd = Command::new(toolchain::rustc());
            cmd.envs(extra_env);
            cmd.current_dir(cargo_toml.parent())
                .args(["-Z", "unstable-options", "rustc", "--print", "target-spec-json"])
                .env("RUSTC_BOOTSTRAP", "1");
            if let Some(target) = target {
                cmd.args(["--target", target]);
            }
            match utf8_stdout(cmd) {
                Ok(it) => return Ok(it),
                Err(e) => tracing::debug!("{e:?}: falling back to querying rustc for cfgs"),
            }
        }
        // using unstable cargo features failed, fall back to using plain rustc
        let mut cmd = Command::new(toolchain::rustc());
        cmd.envs(extra_env)
            .args(["-Z", "unstable-options", "--print", "target-spec-json"])
            .env("RUSTC_BOOTSTRAP", "1");
        if let Some(target) = target {
            cmd.args(["--target", target]);
        }
        utf8_stdout(cmd)
    })()?;
    (|| Some(output.split_once(r#""data-layout": ""#)?.1.split_once('"')?.0.to_owned()))()
        .ok_or_else(|| anyhow::format_err!("could not fetch target-spec-json from command output"))
}