gglib_core/utils/process.rs
1//! Process spawning utilities with consistent cross-platform behaviour.
2//!
3//! On Windows, every child process created with `std::process::Command::new`
4//! inherits a new console window unless `CREATE_NO_WINDOW` is explicitly set.
5//! The `windows_subsystem = "windows"` attribute on the main binary only
6//! suppresses the window for the *main* process — not any child processes.
7//!
8//! Use [`cmd`] and [`async_cmd`] instead of `Command::new` at every call site.
9//! The Windows-specific flag is applied here and nowhere else.
10
11use std::ffi::OsStr;
12
13/// Create a [`std::process::Command`] that will not open a console window on Windows.
14///
15/// Identical to `std::process::Command::new(program)` on macOS and Linux.
16///
17/// # Usage
18///
19/// ```rust,ignore
20/// use gglib_core::utils::process::cmd;
21///
22/// let output = cmd("nvidia-smi").arg("--list-gpus").output()?;
23/// ```
24pub fn cmd(program: impl AsRef<OsStr>) -> std::process::Command {
25 #[allow(unused_mut)]
26 let mut c = std::process::Command::new(program);
27 #[cfg(windows)]
28 {
29 use std::os::windows::process::CommandExt;
30 c.creation_flags(0x08000000); // CREATE_NO_WINDOW
31 }
32 c
33}
34
35/// Create a [`tokio::process::Command`] that will not open a console window on Windows.
36///
37/// Identical to `tokio::process::Command::new(program)` on macOS and Linux.
38///
39/// # Usage
40///
41/// ```rust,ignore
42/// use gglib_core::utils::process::async_cmd;
43///
44/// let child = async_cmd("llama-server").arg("--port").arg("8080").spawn()?;
45/// ```
46pub fn async_cmd(program: impl AsRef<OsStr>) -> tokio::process::Command {
47 #[allow(unused_mut)]
48 let mut c = tokio::process::Command::new(program);
49 #[cfg(windows)]
50 {
51 use std::os::windows::process::CommandExt;
52 c.creation_flags(0x08000000); // CREATE_NO_WINDOW
53 }
54 c
55}