1#![allow(unreachable_pub)]
2
3use std::{fmt, str::FromStr};
4
5use crate::install::{ClientOpt, ProcMacroServerOpt, ServerOpt};
6
7#[derive(Debug, Clone)]
8pub enum PgoTrainingCrate {
9 RustAnalyzer,
11 GitHub(String),
13}
14
15impl FromStr for PgoTrainingCrate {
16 type Err = String;
17
18 fn from_str(s: &str) -> Result<Self, Self::Err> {
19 match s {
20 "rust-analyzer" => Ok(Self::RustAnalyzer),
21 url => Ok(Self::GitHub(url.to_owned())),
22 }
23 }
24}
25
26xflags::xflags! {
27 src "./src/flags.rs"
28
29 cmd xtask {
31
32 cmd install {
34 optional --client
36 optional --code-bin name: String
38
39 optional --server
41 optional --mimalloc
43 optional --jemalloc
45 optional --enable-profiling
49
50 optional --proc-macro-server
52
53 optional --dev-rel
55
56 optional --force-always-assert
58
59 optional --pgo pgo: PgoTrainingCrate
61 }
62
63 cmd fuzz-tests {}
64
65 cmd release {
66 optional --dry-run
67 }
68
69 cmd dist {
70 optional --mimalloc
72 optional --jemalloc
74 optional --enable-profiling
78 optional --client-patch-version version: String
79 optional --zig
81 optional --pgo pgo: PgoTrainingCrate
83 }
84 cmd publish-release-notes {
86 optional --dry-run
88 required changelog: String
90 }
91 cmd metrics {
92 optional measurement_type: MeasurementType
93 }
94 cmd bb {
96 required suffix: String
97 }
98
99 cmd codegen {
100 optional codegen_type: CodegenType
101 optional --check
102 }
103
104 cmd tidy {}
105 }
106}
107
108#[derive(Debug)]
112pub struct Xtask {
113 pub subcommand: XtaskCmd,
114}
115
116#[derive(Debug)]
117pub enum XtaskCmd {
118 Install(Install),
119 FuzzTests(FuzzTests),
120 Release(Release),
121 Dist(Dist),
122 PublishReleaseNotes(PublishReleaseNotes),
123 Metrics(Metrics),
124 Bb(Bb),
125 Codegen(Codegen),
126 Tidy(Tidy),
127}
128
129#[derive(Debug)]
130pub struct Install {
131 pub client: bool,
132 pub code_bin: Option<String>,
133 pub server: bool,
134 pub mimalloc: bool,
135 pub jemalloc: bool,
136 pub enable_profiling: bool,
137 pub proc_macro_server: bool,
138 pub dev_rel: bool,
139 pub force_always_assert: bool,
140 pub pgo: Option<PgoTrainingCrate>,
141}
142
143#[derive(Debug)]
144pub struct FuzzTests;
145
146#[derive(Debug)]
147pub struct Release {
148 pub dry_run: bool,
149}
150
151#[derive(Debug)]
152pub struct Dist {
153 pub mimalloc: bool,
154 pub jemalloc: bool,
155 pub enable_profiling: bool,
156 pub client_patch_version: Option<String>,
157 pub zig: bool,
158 pub pgo: Option<PgoTrainingCrate>,
159}
160
161#[derive(Debug)]
162pub struct PublishReleaseNotes {
163 pub changelog: String,
164
165 pub dry_run: bool,
166}
167
168#[derive(Debug)]
169pub struct Metrics {
170 pub measurement_type: Option<MeasurementType>,
171}
172
173#[derive(Debug)]
174pub struct Bb {
175 pub suffix: String,
176}
177
178#[derive(Debug)]
179pub struct Codegen {
180 pub codegen_type: Option<CodegenType>,
181
182 pub check: bool,
183}
184
185#[derive(Debug)]
186pub struct Tidy;
187
188impl Xtask {
189 #[allow(dead_code)]
190 pub fn from_env_or_exit() -> Self {
191 Self::from_env_or_exit_()
192 }
193
194 #[allow(dead_code)]
195 pub fn from_env() -> xflags::Result<Self> {
196 Self::from_env_()
197 }
198
199 #[allow(dead_code)]
200 pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
201 Self::from_vec_(args)
202 }
203}
204#[derive(Debug, Default)]
207pub enum CodegenType {
208 #[default]
209 All,
210 Grammar,
211 AssistsDocTests,
212 DiagnosticsDocs,
213 LintDefinitions,
214 ParserTests,
215 FeatureDocs,
216}
217
218impl fmt::Display for CodegenType {
219 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
220 match self {
221 Self::All => write!(f, "all"),
222 Self::Grammar => write!(f, "grammar"),
223 Self::AssistsDocTests => write!(f, "assists-doc-tests"),
224 Self::DiagnosticsDocs => write!(f, "diagnostics-docs"),
225 Self::LintDefinitions => write!(f, "lint-definitions"),
226 Self::ParserTests => write!(f, "parser-tests"),
227 Self::FeatureDocs => write!(f, "feature-docs"),
228 }
229 }
230}
231
232impl FromStr for CodegenType {
233 type Err = String;
234 fn from_str(s: &str) -> Result<Self, Self::Err> {
235 match s {
236 "all" => Ok(Self::All),
237 "grammar" => Ok(Self::Grammar),
238 "assists-doc-tests" => Ok(Self::AssistsDocTests),
239 "diagnostics-docs" => Ok(Self::DiagnosticsDocs),
240 "lint-definitions" => Ok(Self::LintDefinitions),
241 "parser-tests" => Ok(Self::ParserTests),
242 "feature-docs" => Ok(Self::FeatureDocs),
243 _ => Err("Invalid option".to_owned()),
244 }
245 }
246}
247
248#[derive(Debug)]
249pub enum MeasurementType {
250 Build,
251 RustcTests,
252 AnalyzeSelf,
253 AnalyzeRipgrep,
254 AnalyzeWebRender,
255 AnalyzeDiesel,
256 AnalyzeHyper,
257}
258
259impl FromStr for MeasurementType {
260 type Err = String;
261 fn from_str(s: &str) -> Result<Self, Self::Err> {
262 match s {
263 "build" => Ok(Self::Build),
264 "rustc_tests" => Ok(Self::RustcTests),
265 "self" => Ok(Self::AnalyzeSelf),
266 "ripgrep-13.0.0" => Ok(Self::AnalyzeRipgrep),
267 "webrender-2022" => Ok(Self::AnalyzeWebRender),
268 "diesel-1.4.8" => Ok(Self::AnalyzeDiesel),
269 "hyper-0.14.18" => Ok(Self::AnalyzeHyper),
270 _ => Err("Invalid option".to_owned()),
271 }
272 }
273}
274impl AsRef<str> for MeasurementType {
275 fn as_ref(&self) -> &str {
276 match self {
277 Self::Build => "build",
278 Self::RustcTests => "rustc_tests",
279 Self::AnalyzeSelf => "self",
280 Self::AnalyzeRipgrep => "ripgrep-13.0.0",
281 Self::AnalyzeWebRender => "webrender-2022",
282 Self::AnalyzeDiesel => "diesel-1.4.8",
283 Self::AnalyzeHyper => "hyper-0.14.18",
284 }
285 }
286}
287
288#[derive(Clone, Copy, Debug)]
289pub(crate) enum Malloc {
290 System,
291 Mimalloc,
292 Jemalloc,
293 Dhat,
294}
295
296impl Malloc {
297 pub(crate) fn to_features(self) -> &'static [&'static str] {
298 match self {
299 Malloc::System => &[][..],
300 Malloc::Mimalloc => &["--features", "mimalloc"],
301 Malloc::Jemalloc => &["--features", "jemalloc"],
302 Malloc::Dhat => &["--features", "dhat"],
303 }
304 }
305}
306
307impl Install {
308 pub(crate) fn server(&self) -> Option<ServerOpt> {
309 if (self.client || self.proc_macro_server) && !self.server {
310 return None;
311 }
312 let malloc = if self.mimalloc {
313 Malloc::Mimalloc
314 } else if self.jemalloc {
315 Malloc::Jemalloc
316 } else if self.enable_profiling {
317 Malloc::Dhat
318 } else {
319 Malloc::System
320 };
321 Some(ServerOpt {
322 malloc,
323 dev_rel: self.dev_rel || self.enable_profiling,
325 pgo: self.pgo.clone(),
326 force_always_assert: self.force_always_assert,
327 })
328 }
329 pub(crate) fn proc_macro_server(&self) -> Option<ProcMacroServerOpt> {
330 if !self.proc_macro_server {
331 return None;
332 }
333 Some(ProcMacroServerOpt { dev_rel: self.dev_rel })
334 }
335 pub(crate) fn client(&self) -> Option<ClientOpt> {
336 if (self.server || self.proc_macro_server) && !self.client {
337 return None;
338 }
339 Some(ClientOpt { code_bin: self.code_bin.clone() })
340 }
341}
342
343impl Dist {
344 pub(crate) fn allocator(&self) -> Malloc {
345 if self.mimalloc {
346 Malloc::Mimalloc
347 } else if self.jemalloc {
348 Malloc::Jemalloc
349 } else if self.enable_profiling {
350 Malloc::Dhat
351 } else {
352 Malloc::System
353 }
354 }
355}