1use std::{
2 env,
3 ffi::OsString,
4 path::{Path, PathBuf},
5 process::Command,
6};
7
8use anyhow::{Result, anyhow};
9use serde::Deserialize;
10
11#[cfg(target_os = "windows")]
12pub const LIB_PATH: &str = "PATH";
13#[cfg(any(target_os = "linux", target_os = "freebsd"))]
14pub const LIB_PATH: &str = "LD_LIBRARY_PATH";
15#[cfg(target_os = "macos")]
16pub const LIB_PATH: &str = "DYLD_FALLBACK_LIBRARY_PATH";
17
18pub const EXIT_ERR: i32 = -1;
19
20pub const FLUX_SYSROOT: &str = "FLUX_SYSROOT";
21
22const FLUX_DRIVER: &str = "FLUX_DRIVER";
23
24pub fn flux_sysroot_dir() -> PathBuf {
26 env::var_os(FLUX_SYSROOT).map_or_else(default_flux_sysroot_dir, PathBuf::from)
27}
28
29#[derive(Deserialize)]
30pub struct ToolchainToml {
31 toolchain: ToolchainSpec,
32}
33
34#[derive(Deserialize)]
35pub struct ToolchainSpec {
36 channel: String,
37}
38
39fn default_flux_sysroot_dir() -> PathBuf {
41 home::home_dir()
42 .expect("Couldn't find home directory")
43 .join(".flux")
44}
45
46pub fn get_flux_driver_path(sysroot: &Path) -> Result<PathBuf> {
47 let path = if let Some(path) = env::var_os(FLUX_DRIVER) {
48 PathBuf::from(path)
49 } else {
50 let mut path = sysroot.join("flux-driver");
51 if cfg!(target_os = "windows") {
52 path.set_extension("exe");
53 }
54 path
55 };
56 if !path.is_file() {
57 return Err(anyhow!("path to flux-driver {:?} does not exist or is not a file", path));
58 }
59 Ok(path)
60}
61
62pub fn get_rust_toolchain() -> Result<String> {
63 let toolchain_str = include_str!("../../../rust-toolchain.toml");
64 let toolchain_file: ToolchainToml = toml::from_str(toolchain_str)?;
65 Ok(toolchain_file.toolchain.channel)
66}
67
68pub fn get_binary_path(toolchain: &str, bin: &str) -> anyhow::Result<PathBuf> {
69 let output = Command::new("rustup")
70 .args(["which", "--toolchain", toolchain, bin])
71 .output()
72 .map_err(|e| anyhow!("failed to run `rustup which`: {e}"))?;
73
74 if !output.status.success() {
75 return Err(anyhow!("`rustup which` failed: {}", String::from_utf8_lossy(&output.stderr)));
76 }
77
78 Ok(PathBuf::from(
79 String::from_utf8(output.stdout)
80 .map_err(|e| anyhow!("invalid utf8 from `rustup which` output: {e}"))?
81 .trim()
82 .to_string(),
83 ))
84}
85
86pub fn get_rust_sysroot(toolchain: &str) -> Result<PathBuf> {
87 let out = Command::new("rustc")
88 .arg(format!("+{toolchain}"))
89 .args(["--print", "sysroot"])
90 .output()?;
91 bytes_to_pathbuf(out.stdout)
92}
93
94pub fn get_rust_lib_path(sysroot: &Path) -> PathBuf {
96 if cfg!(windows) { sysroot.join("bin") } else { sysroot.join("lib") }
97}
98
99pub fn prepend_path_to_env_var(var_name: &str, new_path: PathBuf) -> Result<OsString> {
101 let mut paths = match env::var(var_name) {
102 Ok(paths) => env::split_paths(&paths).collect(),
103 Err(env::VarError::NotPresent) => vec![],
104 Err(e) => Err(e)?,
105 };
106 paths.insert(0, new_path);
107 env::join_paths(paths).map_err(anyhow::Error::from)
108}
109
110fn bytes_to_pathbuf(input: Vec<u8>) -> Result<PathBuf> {
111 Ok(PathBuf::from(String::from_utf8(input)?.trim()))
112}
113
114pub fn get_version() -> &'static str {
115 concat!(env!("GIT_SHA"), " (", env!("GIT_DATE"), ")")
116}