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;