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 --pgo pgo: PgoTrainingCrate
81 }
82 cmd publish-release-notes {
84 optional --dry-run
86 required changelog: String
88 }
89 cmd metrics {
90 optional measurement_type: MeasurementType
91 }
92 cmd bb {
94 required suffix: String
95 }
96
97 cmd codegen {
98 optional codegen_type: CodegenType
99 optional --check
100 }
101
102 cmd tidy {}
103 }
104}
105
106#[derive(Debug)]
110pub struct Xtask {
111 pub subcommand: XtaskCmd,
112}
113
114#[derive(Debug)]
115pub enum XtaskCmd {
116 Install(Install),
117 FuzzTests(FuzzTests),
118 Release(Release),
119 Dist(Dist),
120 PublishReleaseNotes(PublishReleaseNotes),
121 Metrics(Metrics),
122 Bb(Bb),
123 Codegen(Codegen),
124 Tidy(Tidy),
125}
126
127#[derive(Debug)]
128pub struct Install {
129 pub client: bool,
130 pub code_bin: Option<String>,
131 pub server: bool,
132 pub mimalloc: bool,
133 pub jemalloc: bool,
134 pub enable_profiling: bool,
135 pub proc_macro_server: bool,
136 pub dev_rel: bool,
137 pub force_always_assert: bool,
138 pub pgo: Option<PgoTrainingCrate>,
139}
140
141#[derive(Debug)]
142pub struct FuzzTests;
143
144#[derive(Debug)]
145pub struct Release {
146 pub dry_run: bool,
147}
148
149#[derive(Debug)]
150pub struct Dist {
151 pub mimalloc: bool,
152 pub jemalloc: bool,
153 pub enable_profiling: bool,
154 pub client_patch_version: Option<String>,
155 pub pgo: Option<PgoTrainingCrate>,
156}
157
158#[derive(Debug)]
159pub struct PublishReleaseNotes {
160 pub changelog: String,
161
162 pub dry_run: bool,
163}
164
165#[derive(Debug)]
166pub struct Metrics {
167 pub measurement_type: Option<MeasurementType>,
168}
169
170#[derive(Debug)]
171pub struct Bb {
172 pub suffix: String,
173}
174
175#[derive(Debug)]
176pub struct Codegen {
177 pub codegen_type: Option<CodegenType>,
178
179 pub check: bool,
180}
181
182#[derive(Debug)]
183pub struct Tidy;
184
185impl Xtask {
186 #[allow(dead_code)]
187 pub fn from_env_or_exit() -> Self {
188 Self::from_env_or_exit_()
189 }
190
191 #[allow(dead_code)]
192 pub fn from_env() -> xflags::Result<Self> {
193 Self::from_env_()
194 }
195
196 #[allow(dead_code)]
197 pub fn from_vec(args: Vec<std::ffi::OsString>) -> xflags::Result<Self> {
198 Self::from_vec_(args)
199 }
200}
201#[derive(Debug, Default)]
204pub enum CodegenType {
205 #[default]
206 All,
207 Grammar,
208 AssistsDocTests,
209 DiagnosticsDocs,
210 LintDefinitions,
211 ParserTests,
212 FeatureDocs,
213}
214
215impl fmt::Display for CodegenType {
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217 match self {
218 Self::All => write!(f, "all"),
219 Self::Grammar => write!(f, "grammar"),
220 Self::AssistsDocTests => write!(f, "assists-doc-tests"),
221 Self::DiagnosticsDocs => write!(f, "diagnostics-docs"),
222 Self::LintDefinitions => write!(f, "lint-definitions"),
223 Self::ParserTests => write!(f, "parser-tests"),
224 Self::FeatureDocs => write!(f, "feature-docs"),
225 }
226 }
227}
228
229impl FromStr for CodegenType {
230 type Err = String;
231 fn from_str(s: &str) -> Result<Self, Self::Err> {
232 match s {
233 "all" => Ok(Self::All),
234 "grammar" => Ok(Self::Grammar),
235 "assists-doc-tests" => Ok(Self::AssistsDocTests),
236 "diagnostics-docs" => Ok(Self::DiagnosticsDocs),
237 "lint-definitions" => Ok(Self::LintDefinitions),
238 "parser-tests" => Ok(Self::ParserTests),
239 "feature-docs" => Ok(Self::FeatureDocs),
240 _ => Err("Invalid option".to_owned()),
241 }
242 }
243}
244
245#[derive(Debug)]
246pub enum MeasurementType {
247 Build,
248 RustcTests,
249 AnalyzeSelf,
250 AnalyzeRipgrep,
251 AnalyzeWebRender,
252 AnalyzeDiesel,
253 AnalyzeHyper,
254}
255
256impl FromStr for MeasurementType {
257 type Err = String;
258 fn from_str(s: &str) -> Result<Self, Self::Err> {
259 match s {
260 "build" => Ok(Self::Build),
261 "rustc_tests" => Ok(Self::RustcTests),
262 "self" => Ok(Self::AnalyzeSelf),
263 "ripgrep-13.0.0" => Ok(Self::AnalyzeRipgrep),
264 "webrender-2022" => Ok(Self::AnalyzeWebRender),
265 "diesel-1.4.8" => Ok(Self::AnalyzeDiesel),
266 "hyper-0.14.18" => Ok(Self::AnalyzeHyper),
267 _ => Err("Invalid option".to_owned()),
268 }
269 }
270}
271impl AsRef<str> for MeasurementType {
272 fn as_ref(&self) -> &str {
273 match self {
274 Self::Build => "build",
275 Self::RustcTests => "rustc_tests",
276 Self::AnalyzeSelf => "self",
277 Self::AnalyzeRipgrep => "ripgrep-13.0.0",
278 Self::AnalyzeWebRender => "webrender-2022",
279 Self::AnalyzeDiesel => "diesel-1.4.8",
280 Self::AnalyzeHyper => "hyper-0.14.18",
281 }
282 }
283}
284
285#[derive(Clone, Copy, Debug)]
286pub(crate) enum Malloc {
287 System,
288 Mimalloc,
289 Jemalloc,
290 Dhat,
291}
292
293impl Malloc {
294 pub(crate) fn to_features(self) -> &'static [&'static str] {
295 match self {
296 Malloc::System => &[][..],
297 Malloc::Mimalloc => &["--features", "mimalloc"],
298 Malloc::Jemalloc => &["--features", "jemalloc"],
299 Malloc::Dhat => &["--features", "dhat"],
300 }
301 }
302}
303
304impl Install {
305 pub(crate) fn server(&self) -> Option<ServerOpt> {
306 if (self.client || self.proc_macro_server) && !self.server {
307 return None;
308 }
309 let malloc = if self.mimalloc {
310 Malloc::Mimalloc
311 } else if self.jemalloc {
312 Malloc::Jemalloc
313 } else if self.enable_profiling {
314 Malloc::Dhat
315 } else {
316 Malloc::System
317 };
318 Some(ServerOpt {
319 malloc,
320 dev_rel: self.dev_rel || self.enable_profiling,
322 pgo: self.pgo.clone(),
323 force_always_assert: self.force_always_assert,
324 })
325 }
326 pub(crate) fn proc_macro_server(&self) -> Option<ProcMacroServerOpt> {
327 if !self.proc_macro_server {
328 return None;
329 }
330 Some(ProcMacroServerOpt { dev_rel: self.dev_rel })
331 }
332 pub(crate) fn client(&self) -> Option<ClientOpt> {
333 if (self.server || self.proc_macro_server) && !self.client {
334 return None;
335 }
336 Some(ClientOpt { code_bin: self.code_bin.clone() })
337 }
338}
339
340impl Dist {
341 pub(crate) fn allocator(&self) -> Malloc {
342 if self.mimalloc {
343 Malloc::Mimalloc
344 } else if self.jemalloc {
345 Malloc::Jemalloc
346 } else if self.enable_profiling {
347 Malloc::Dhat
348 } else {
349 Malloc::System
350 }
351 }
352}