Skip to main content

xtask/
flags.rs

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    // Use RA's own sources for PGO training
10    RustAnalyzer,
11    // Download a Rust crate from `https://github.com/{0}` and use it for PGO training.
12    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    /// Run custom build command.
30    cmd xtask {
31
32        /// Install rust-analyzer server or editor plugin.
33        cmd install {
34            /// Install only VS Code plugin.
35            optional --client
36            /// One of `code`, `code-exploration`, `code-insiders`, `codium`, or `code-oss`.
37            optional --code-bin name: String
38
39            /// Install only the language server.
40            optional --server
41            /// Use mimalloc allocator for server.
42            optional --mimalloc
43            /// Use jemalloc allocator for server.
44            optional --jemalloc
45            // Enable memory profiling support.
46            //
47            // **Warning:** This will produce a slower build of rust-analyzer, use only for profiling.
48            optional --enable-profiling
49
50            /// Install the proc-macro server.
51            optional --proc-macro-server
52
53            /// build in release with debug info set to 2.
54            optional --dev-rel
55
56            /// Make `never!()`, `always!()` etc. panic instead of just logging an error.
57            optional --force-always-assert
58
59            /// Apply PGO optimizations
60            optional --pgo pgo: PgoTrainingCrate
61        }
62
63        cmd fuzz-tests {}
64
65        cmd release {
66            optional --dry-run
67        }
68
69        cmd dist {
70            /// Use mimalloc allocator for server
71            optional --mimalloc
72            /// Use jemalloc allocator for server
73            optional --jemalloc
74            // Enable memory profiling support.
75            //
76            // **Warning:** This will produce a slower build of rust-analyzer, use only for profiling.
77            optional --enable-profiling
78            optional --client-patch-version version: String
79            /// Apply PGO optimizations
80            optional --pgo pgo: PgoTrainingCrate
81        }
82        /// Read a changelog AsciiDoc file and update the GitHub Releases entry in Markdown.
83        cmd publish-release-notes {
84            /// Only run conversion and show the result.
85            optional --dry-run
86            /// Target changelog file.
87            required changelog: String
88        }
89        cmd metrics {
90            optional measurement_type: MeasurementType
91        }
92        /// Builds a benchmark version of rust-analyzer and puts it into `./target`.
93        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// generated start
107// The following code is generated by `xflags` macro.
108// Run `env UPDATE_XFLAGS=1 cargo build` to regenerate.
109#[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// generated end
202
203#[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            // Profiling requires debug information.
321            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}