flux_bin/
utils.rs

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 use flux_sysroot::{FLUX_SYSROOT, flux_sysroot_dir};
19
20pub const EXIT_ERR: i32 = -1;
21
22const FLUX_DRIVER: &str = "FLUX_DRIVER";
23
24#[derive(Deserialize)]
25pub struct ToolchainToml {
26    toolchain: ToolchainSpec,
27}
28
29#[derive(Deserialize)]
30pub struct ToolchainSpec {
31    channel: String,
32}
33
34pub fn get_flux_driver_path(sysroot: &Path) -> Result<PathBuf> {
35    let path = if let Some(path) = env::var_os(FLUX_DRIVER) {
36        PathBuf::from(path)
37    } else {
38        let mut path = sysroot.join("flux-driver");
39        if cfg!(target_os = "windows") {
40            path.set_extension("exe");
41        }
42        path
43    };
44    if !path.is_file() {
45        return Err(anyhow!("path to flux-driver {:?} does not exist or is not a file", path));
46    }
47    Ok(path)
48}
49
50pub fn get_rust_toolchain() -> Result<String> {
51    let toolchain_str = include_str!("../../../rust-toolchain.toml");
52    let toolchain_file: ToolchainToml = toml::from_str(toolchain_str)?;
53    Ok(toolchain_file.toolchain.channel)
54}
55
56pub fn get_binary_path(toolchain: &str, bin: &str) -> anyhow::Result<PathBuf> {
57    let output = Command::new("rustup")
58        .args(["which", "--toolchain", toolchain, bin])
59        .output()
60        .map_err(|e| anyhow!("failed to run `rustup which`: {e}"))?;
61
62    if !output.status.success() {
63        return Err(anyhow!("`rustup which` failed: {}", String::from_utf8_lossy(&output.stderr)));
64    }
65
66    Ok(PathBuf::from(
67        String::from_utf8(output.stdout)
68            .map_err(|e| anyhow!("invalid utf8 from `rustup which` output: {e}"))?
69            .trim()
70            .to_string(),
71    ))
72}
73
74pub fn get_rust_sysroot(toolchain: &str) -> Result<PathBuf> {
75    let out = Command::new("rustc")
76        .arg(format!("+{toolchain}"))
77        .args(["--print", "sysroot"])
78        .output()?;
79    bytes_to_pathbuf(out.stdout)
80}
81
82/// Path from where to load the rustc-driver library from
83pub fn get_rust_lib_path(sysroot: &Path) -> PathBuf {
84    if cfg!(windows) { sysroot.join("bin") } else { sysroot.join("lib") }
85}
86
87/// Prepends the path so that it's the first checked.
88pub fn prepend_path_to_env_var(var_name: &str, new_path: PathBuf) -> Result<OsString> {
89    let mut paths = match env::var(var_name) {
90        Ok(paths) => env::split_paths(&paths).collect(),
91        Err(env::VarError::NotPresent) => vec![],
92        Err(e) => Err(e)?,
93    };
94    paths.insert(0, new_path);
95    env::join_paths(paths).map_err(anyhow::Error::from)
96}
97
98fn bytes_to_pathbuf(input: Vec<u8>) -> Result<PathBuf> {
99    Ok(PathBuf::from(String::from_utf8(input)?.trim()))
100}
101
102pub fn get_version() -> &'static str {
103    concat!(env!("GIT_SHA"), " (", env!("GIT_DATE"), ")")
104}
105
106pub fn get_version_full() -> &'static str {
107    concat!(env!("GIT_SHA_FULL"), " (", env!("GIT_DATE"), ")")
108}
109
110pub fn print_version_and_exit(program_name: &str, verbose: bool) -> ! {
111    if verbose {
112        println!("{} {}", program_name, get_version_full());
113    } else {
114        println!("{} {}", program_name, get_version());
115    }
116    std::process::exit(0)
117}