os_xtask_utils/
qemu.rs

1use super::ext;
2use once_cell::sync::Lazy;
3use std::{
4    collections::HashSet,
5    ffi::{OsStr, OsString},
6    path::{Path, PathBuf},
7    process::Command,
8    sync::Mutex,
9};
10
11ext!(def; Qemu);
12
13static SEARCH_DIRS: Lazy<Mutex<HashSet<PathBuf>>> = Lazy::new(|| {
14    Mutex::new(if cfg!(target_os = "windows") {
15        HashSet::from_iter([PathBuf::from(r"C:\Program Files\qemu")])
16    } else {
17        HashSet::new()
18    })
19});
20
21impl Qemu {
22    #[inline]
23    pub fn search_at(path: impl AsRef<Path>) {
24        SEARCH_DIRS
25            .lock()
26            .unwrap()
27            .insert(path.as_ref().to_path_buf());
28    }
29
30    #[inline]
31    fn find(name: impl AsRef<OsStr>) -> Self {
32        Self(Command::new(Self::find_qemu(OsString::from_iter([
33            OsStr::new("qemu-"),
34            name.as_ref(),
35        ]))))
36    }
37
38    #[inline]
39    pub fn system(arch: impl AsRef<OsStr>) -> Self {
40        Self::find(OsString::from_iter([OsStr::new("system-"), arch.as_ref()]))
41    }
42
43    #[inline]
44    pub fn img() -> Self {
45        Self::find("img")
46    }
47
48    fn find_qemu(mut name: OsString) -> OsString {
49        #[cfg(target_os = "windows")]
50        name.push(OsStr::new(".exe"));
51        SEARCH_DIRS
52            .lock()
53            .unwrap()
54            .iter()
55            .map(|dir| dir.join(&name))
56            .find(|path| path.is_file())
57            .map_or(name, |p| p.into_os_string())
58    }
59}