use std::{
env,
ffi::OsString,
fs,
path::{Path, PathBuf},
};
use anyhow::{Result, anyhow};
use serde::Deserialize;
#[cfg(target_os = "windows")]
pub const LIB_PATH: &str = "PATH";
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
pub const LIB_PATH: &str = "LD_LIBRARY_PATH";
#[cfg(target_os = "macos")]
pub const LIB_PATH: &str = "DYLD_FALLBACK_LIBRARY_PATH";
pub const EXIT_ERR: i32 = -1;
pub const FLUX_SYSROOT: &str = "FLUX_SYSROOT";
const FLUX_DRIVER: &str = "FLUX_DRIVER";
pub fn sysroot_dir() -> PathBuf {
env::var_os(FLUX_SYSROOT).map_or_else(default_sysroot_dir, PathBuf::from)
}
#[derive(Deserialize)]
pub struct ToolchainToml {
toolchain: ToolchainSpec,
}
#[derive(Deserialize)]
pub struct ToolchainSpec {
channel: String,
}
fn default_sysroot_dir() -> PathBuf {
home::home_dir()
.expect("Couldn't find home directory")
.join(".flux")
}
pub fn get_flux_driver_path(sysroot: &Path) -> Result<PathBuf> {
let path = if let Some(path) = env::var_os(FLUX_DRIVER) {
PathBuf::from(path)
} else {
let mut path = sysroot.join("flux-driver");
if cfg!(target_os = "windows") {
path.set_extension("exe");
}
path
};
if !path.is_file() {
return Err(anyhow!("path to flux-driver {:?} does not exist or is not a file", path));
}
Ok(path)
}
pub fn get_rust_toolchain() -> Result<String> {
let toolchain_str = include_str!("../../../rust-toolchain");
let toolchain_file: ToolchainToml = toml::from_str(toolchain_str)?;
Ok(toolchain_file.toolchain.channel)
}
pub fn get_rustc_driver_lib_path(rust_toolchain: &str) -> Result<PathBuf> {
let toolchains_path = home::rustup_home()?.join("toolchains");
if toolchains_path.is_dir() {
let entries = fs::read_dir(toolchains_path)?;
for entry in entries {
let toolchain_entry = entry?;
let file_name = toolchain_entry.file_name().into_string().map_err(|name| {
anyhow!("Could not convert Rustup toolchain file name: {:?}", name)
})?;
if file_name.starts_with(rust_toolchain) {
return toolchain_entry
.path()
.join("lib")
.canonicalize()
.map_err(anyhow::Error::from);
}
}
}
Err(anyhow!("Could not read Rustup toolchains folder"))
}
pub fn prepend_path_to_env_var(var_name: &str, new_path: PathBuf) -> Result<OsString> {
let mut paths = match env::var(var_name) {
Ok(paths) => env::split_paths(&paths).collect(),
Err(env::VarError::NotPresent) => vec![],
Err(e) => Err(e)?,
};
paths.insert(0, new_path);
env::join_paths(paths).map_err(anyhow::Error::from)
}