1use std::ops::{Deref, DerefMut};
2use std::path::PathBuf;
3use std::process::Command;
4
5use clap::{ArgAction, Parser};
6
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10use crate::common::CommonOptions;
11use crate::heading;
12
13#[derive(Clone, Debug, Default, Parser)]
15#[command(
16 display_order = 1,
17 after_help = "Run `cargo help build` for more detailed information."
18)]
19#[group(skip)]
20#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
21pub struct Build {
22 #[command(flatten)]
23 #[cfg_attr(feature = "serde", serde(flatten))]
24 pub common: CommonOptions,
25
26 #[arg(long, value_name = "PATH", help_heading = heading::MANIFEST_OPTIONS)]
28 #[cfg_attr(feature = "serde", serde(default))]
29 pub manifest_path: Option<PathBuf>,
30
31 #[arg(short = 'r', long, help_heading = heading::COMPILATION_OPTIONS)]
33 #[cfg_attr(feature = "serde", serde(default))]
34 pub release: bool,
35
36 #[arg(long)]
38 #[cfg_attr(feature = "serde", serde(default))]
39 pub ignore_rust_version: bool,
40
41 #[arg(long, help_heading = heading::COMPILATION_OPTIONS)]
43 #[cfg_attr(feature = "serde", serde(default))]
44 pub unit_graph: bool,
45
46 #[arg(
48 short = 'p',
49 long = "package",
50 value_name = "SPEC",
51 action = ArgAction::Append,
52 num_args=0..=1,
53 help_heading = heading::PACKAGE_SELECTION,
54 )]
55 #[cfg_attr(feature = "serde", serde(default))]
56 pub packages: Vec<String>,
57
58 #[arg(long, help_heading = heading::PACKAGE_SELECTION)]
60 #[cfg_attr(feature = "serde", serde(default))]
61 pub workspace: bool,
62
63 #[arg(
65 long,
66 value_name = "SPEC",
67 action = ArgAction::Append,
68 help_heading = heading::PACKAGE_SELECTION,
69 )]
70 #[cfg_attr(feature = "serde", serde(default))]
71 pub exclude: Vec<String>,
72
73 #[arg(long, help_heading = heading::PACKAGE_SELECTION)]
75 #[cfg_attr(feature = "serde", serde(default))]
76 pub all: bool,
77
78 #[arg(long, help_heading = heading::TARGET_SELECTION)]
80 #[cfg_attr(feature = "serde", serde(default))]
81 pub lib: bool,
82
83 #[arg(
85 long,
86 value_name = "NAME",
87 action = ArgAction::Append,
88 num_args=0..=1,
89 help_heading = heading::TARGET_SELECTION,
90 )]
91 #[cfg_attr(feature = "serde", serde(default))]
92 pub bin: Vec<String>,
93
94 #[arg(long, help_heading = heading::TARGET_SELECTION)]
96 #[cfg_attr(feature = "serde", serde(default))]
97 pub bins: bool,
98
99 #[arg(
101 long,
102 value_name = "NAME",
103 action = ArgAction::Append,
104 num_args=0..=1,
105 help_heading = heading::TARGET_SELECTION,
106 )]
107 #[cfg_attr(feature = "serde", serde(default))]
108 pub example: Vec<String>,
109
110 #[arg(long, help_heading = heading::TARGET_SELECTION)]
112 #[cfg_attr(feature = "serde", serde(default))]
113 pub examples: bool,
114
115 #[arg(
117 long,
118 value_name = "NAME",
119 action = ArgAction::Append,
120 help_heading = heading::TARGET_SELECTION,
121 )]
122 #[cfg_attr(feature = "serde", serde(default))]
123 pub test: Vec<String>,
124
125 #[arg(long, help_heading = heading::TARGET_SELECTION)]
127 #[cfg_attr(feature = "serde", serde(default))]
128 pub tests: bool,
129
130 #[arg(
132 long,
133 value_name = "NAME",
134 action = ArgAction::Append,
135 help_heading = heading::TARGET_SELECTION,
136 )]
137 #[cfg_attr(feature = "serde", serde(default))]
138 pub bench: Vec<String>,
139
140 #[arg(long, help_heading = heading::TARGET_SELECTION)]
142 #[cfg_attr(feature = "serde", serde(default))]
143 pub benches: bool,
144
145 #[arg(long, help_heading = heading::TARGET_SELECTION)]
147 #[cfg_attr(feature = "serde", serde(default))]
148 pub all_targets: bool,
149
150 #[arg(long, alias = "out-dir", value_name = "PATH", help_heading = heading::COMPILATION_OPTIONS)]
152 #[cfg_attr(feature = "serde", serde(default))]
153 pub artifact_dir: Option<PathBuf>,
154
155 #[arg(long, help_heading = heading::COMPILATION_OPTIONS)]
157 #[cfg_attr(feature = "serde", serde(default))]
158 pub build_plan: bool,
159
160 #[arg(long)]
162 #[cfg_attr(feature = "serde", serde(default))]
163 pub future_incompat_report: bool,
164}
165
166impl Build {
167 pub fn command(&self) -> Command {
169 let mut cmd = CommonOptions::cargo_command();
170 cmd.arg("build");
171
172 self.common.apply(&mut cmd);
173
174 if let Some(path) = self.manifest_path.as_ref() {
175 cmd.arg("--manifest-path").arg(path);
176 }
177 if self.release {
178 cmd.arg("--release");
179 }
180 if self.ignore_rust_version {
181 cmd.arg("--ignore-rust-version");
182 }
183 if self.unit_graph {
184 cmd.arg("--unit-graph");
185 }
186 for pkg in &self.packages {
187 cmd.arg("--package").arg(pkg);
188 }
189 if self.workspace {
190 cmd.arg("--workspace");
191 }
192 for item in &self.exclude {
193 cmd.arg("--exclude").arg(item);
194 }
195 if self.all {
196 cmd.arg("--all");
197 }
198 if self.lib {
199 cmd.arg("--lib");
200 }
201 for bin in &self.bin {
202 cmd.arg("--bin").arg(bin);
203 }
204 if self.bins {
205 cmd.arg("--bins");
206 }
207 for example in &self.example {
208 cmd.arg("--example").arg(example);
209 }
210 if self.examples {
211 cmd.arg("--examples");
212 }
213 for test in &self.test {
214 cmd.arg("--test").arg(test);
215 }
216 if self.tests {
217 cmd.arg("--tests");
218 }
219 for bench in &self.bench {
220 cmd.arg("--bench").arg(bench);
221 }
222 if self.benches {
223 cmd.arg("--benches");
224 }
225 if self.all_targets {
226 cmd.arg("--all-targets");
227 }
228 if let Some(dir) = self.artifact_dir.as_ref() {
229 cmd.arg("--artifact-dir").arg(dir);
230 }
231 if self.build_plan {
232 cmd.arg("--build-plan");
233 }
234 if self.future_incompat_report {
235 cmd.arg("--future-incompat-report");
236 }
237
238 cmd
239 }
240}
241
242impl Deref for Build {
243 type Target = CommonOptions;
244
245 fn deref(&self) -> &Self::Target {
246 &self.common
247 }
248}
249
250impl DerefMut for Build {
251 fn deref_mut(&mut self) -> &mut Self::Target {
252 &mut self.common
253 }
254}
255
256#[cfg(test)]
257mod test {
258 use super::Build;
259 use clap::CommandFactory;
260
261 #[test]
262 fn verify_cli() {
263 <Build as CommandFactory>::command().debug_assert()
264 }
265}