run_make_support/
macros.rs

1/// Implement common helpers for command wrappers. This assumes that the command wrapper is a struct
2/// containing a `cmd: Command` field. The provided helpers are:
3///
4/// 1. Generic argument acceptors: `arg` and `args` (delegated to [`Command`]). These are intended
5///    to be *fallback* argument acceptors, when specific helpers don't make sense. Prefer to add
6///    new specific helper methods over relying on these generic argument providers.
7/// 2. Environment manipulation methods: `env`, `env_remove` and `env_clear`: these delegate to
8///    methods of the same name on [`Command`].
9/// 3. Output and execution: `run` and `run_fail` are provided. These are higher-level convenience
10///    methods which wait for the command to finish running and assert that the command successfully
11///    ran or failed as expected. They return [`CompletedProcess`], which can be used to assert the
12///    stdout/stderr/exit code of the executed process.
13///
14/// Example usage:
15///
16/// ```ignore (illustrative)
17/// struct CommandWrapper { cmd: Command } // <- required `cmd` field
18///
19/// crate::macros::impl_common_helpers!(CommandWrapper);
20///
21/// impl CommandWrapper {
22///     // ... additional specific helper methods
23/// }
24/// ```
25///
26/// [`Command`]: crate::command::Command
27/// [`CompletedProcess`]: crate::command::CompletedProcess
28macro_rules! impl_common_helpers {
29    ($wrapper: ident) => {
30        impl $wrapper {
31            /// Specify an environment variable.
32            pub fn env<K, V>(&mut self, key: K, value: V) -> &mut Self
33            where
34                K: AsRef<::std::ffi::OsStr>,
35                V: AsRef<::std::ffi::OsStr>,
36            {
37                self.cmd.env(key, value);
38                self
39            }
40
41            /// Remove an environmental variable.
42            pub fn env_remove<K>(&mut self, key: K) -> &mut Self
43            where
44                K: AsRef<::std::ffi::OsStr>,
45            {
46                self.cmd.env_remove(key);
47                self
48            }
49
50            /// Generic command argument provider. Prefer specific helper methods if possible.
51            /// Note that for some executables, arguments might be platform specific. For C/C++
52            /// compilers, arguments might be platform *and* compiler specific.
53            pub fn arg<S>(&mut self, arg: S) -> &mut Self
54            where
55                S: AsRef<::std::ffi::OsStr>,
56            {
57                self.cmd.arg(arg);
58                self
59            }
60
61            /// Generic command arguments provider. Prefer specific helper methods if possible.
62            /// Note that for some executables, arguments might be platform specific. For C/C++
63            /// compilers, arguments might be platform *and* compiler specific.
64            pub fn args<V, S>(&mut self, args: V) -> &mut Self
65            where
66                V: AsRef<[S]>,
67                S: AsRef<::std::ffi::OsStr>,
68            {
69                self.cmd.args(args.as_ref());
70                self
71            }
72
73            /// Configuration for the child process’s standard input (stdin) handle.
74            ///
75            /// See [`std::process::Command::stdin`].
76            pub fn stdin<T: Into<::std::process::Stdio>>(&mut self, cfg: T) -> &mut Self {
77                self.cmd.stdin(cfg);
78                self
79            }
80
81            /// Configuration for the child process’s standard output (stdout) handle.
82            ///
83            /// See [`std::process::Command::stdout`].
84            pub fn stdout<T: Into<::std::process::Stdio>>(&mut self, cfg: T) -> &mut Self {
85                self.cmd.stdout(cfg);
86                self
87            }
88
89            /// Configuration for the child process’s standard error (stderr) handle.
90            ///
91            /// See [`std::process::Command::stderr`].
92            pub fn stderr<T: Into<::std::process::Stdio>>(&mut self, cfg: T) -> &mut Self {
93                self.cmd.stderr(cfg);
94                self
95            }
96
97            /// Inspect what the underlying [`Command`] is up to the
98            /// current construction.
99            pub fn inspect<I>(&mut self, inspector: I) -> &mut Self
100            where
101                I: FnOnce(&::std::process::Command),
102            {
103                self.cmd.inspect(inspector);
104                self
105            }
106
107            /// Set an auxiliary stream passed to the process, besides the stdio streams.
108            #[cfg(unix)]
109            pub fn set_aux_fd<F: Into<std::os::fd::OwnedFd>>(
110                &mut self,
111                new_fd: std::os::fd::RawFd,
112                fd: F,
113            ) -> &mut Self {
114                self.cmd.set_aux_fd(new_fd, fd);
115                self
116            }
117
118            /// Run the constructed command and assert that it is successfully run.
119            #[track_caller]
120            pub fn run(&mut self) -> crate::command::CompletedProcess {
121                self.cmd.run()
122            }
123
124            /// Run the constructed command and assert that it does not successfully run.
125            #[track_caller]
126            pub fn run_fail(&mut self) -> crate::command::CompletedProcess {
127                self.cmd.run_fail()
128            }
129
130            /// Run the command but do not check its exit status.
131            /// Only use if you explicitly don't care about the exit status.
132            /// Prefer to use [`Self::run`] and [`Self::run_fail`]
133            /// whenever possible.
134            #[track_caller]
135            pub fn run_unchecked(&mut self) -> crate::command::CompletedProcess {
136                self.cmd.run_unchecked()
137            }
138
139            /// Set the path where the command will be run.
140            pub fn current_dir<P: AsRef<::std::path::Path>>(&mut self, path: P) -> &mut Self {
141                self.cmd.current_dir(path);
142                self
143            }
144        }
145    };
146}
147
148pub(crate) use impl_common_helpers;