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            /// Use cargo-zigbuild
80            optional --zig
81            /// Apply PGO optimizations
82            optional --pgo pgo: PgoTrainingCrate
83        }
84        /// Read a changelog AsciiDoc file and update the GitHub Releases entry in Markdown.
85        cmd publish-release-notes {
86            /// Only run conversion and show the result.
87            optional --dry-run
88            /// Target changelog file.
89            required changelog: String
90        }
91        cmd metrics {
92            optional measurement_type: MeasurementType
93        }
94        /// Builds a benchmark version of rust-analyzer and puts it into `./target`.
95        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// generated start
109// The following code is generated by `xflags` macro.
110// Run `env UPDATE_XFLAGS=1 cargo build` to regenerate.
111#[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// generated end
205
206#[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            // Profiling requires debug information.
324            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}