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
use std::{path::PathBuf, process::Command};

use anyhow::{bail, Context, Result};

const TOOLCHAIN_TOML: &str = include_str!("../rust-toolchain.toml");

pub fn toolchain() -> Result<String> {
  let config: toml::Value = toml::from_str(TOOLCHAIN_TOML)?;
  Ok(
    config
      .get("toolchain")
      .context("Missing toolchain key")?
      .get("channel")
      .context("Missing channel key")?
      .as_str()
      .unwrap()
      .to_string(),
  )
}

pub fn miri_sysroot() -> Result<PathBuf> {
  if let Ok(sysroot) = std::env::var("MIRI_SYSROOT") {
    return Ok(sysroot.into());
  }

  let mut cmd = Command::new("cargo");
  if let Ok(toolchain) = toolchain() {
    cmd.arg(format!("+{}", toolchain));
  }

  let output = cmd.args(["miri", "setup", "--print-sysroot"]).output()?;

  if !output.status.success() {
    bail!("Command failed");
  }

  let stdout = String::from_utf8(output.stdout)?;
  Ok(PathBuf::from(stdout.trim_end()))
}