xtask/
main.rs

1//! See <https://github.com/matklad/cargo-xtask/>.
2//!
3//! This binary defines various auxiliary build commands, which are not
4//! expressible with just `cargo`. Notably, it provides tests via `cargo test -p xtask`
5//! for code generation and `cargo xtask install` for installation of
6//! rust-analyzer server and client.
7//!
8//! This binary is integrated into the `cargo` command line by using an alias in
9//! `.cargo/config`.
10
11#![warn(rust_2018_idioms, unused_lifetimes)]
12#![allow(
13    clippy::print_stderr,
14    clippy::print_stdout,
15    clippy::disallowed_methods,
16    clippy::disallowed_types
17)]
18
19mod flags;
20
21mod codegen;
22mod dist;
23mod install;
24mod metrics;
25mod pgo;
26mod publish;
27mod release;
28mod tidy;
29mod util;
30
31use anyhow::bail;
32use std::{env, path::PathBuf};
33use xshell::{Shell, cmd};
34
35fn main() -> anyhow::Result<()> {
36    let flags = flags::Xtask::from_env_or_exit();
37
38    let sh = &Shell::new()?;
39    sh.change_dir(project_root());
40
41    match flags.subcommand {
42        flags::XtaskCmd::Install(cmd) => cmd.run(sh),
43        flags::XtaskCmd::FuzzTests(_) => run_fuzzer(sh),
44        flags::XtaskCmd::Release(cmd) => cmd.run(sh),
45        flags::XtaskCmd::Dist(cmd) => cmd.run(sh),
46        flags::XtaskCmd::PublishReleaseNotes(cmd) => cmd.run(sh),
47        flags::XtaskCmd::Metrics(cmd) => cmd.run(sh),
48        flags::XtaskCmd::Codegen(cmd) => cmd.run(sh),
49        flags::XtaskCmd::Bb(cmd) => {
50            {
51                let _d = sh.push_dir("./crates/rust-analyzer");
52                cmd!(sh, "cargo build --release --features jemalloc").run()?;
53            }
54            sh.copy_file(
55                "./target/release/rust-analyzer",
56                format!("./target/rust-analyzer-{}", cmd.suffix),
57            )?;
58            Ok(())
59        }
60        flags::XtaskCmd::Tidy(cmd) => cmd.run(sh),
61    }
62}
63
64/// Returns the path to the root directory of `rust-analyzer` project.
65fn project_root() -> PathBuf {
66    let dir =
67        env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned());
68    PathBuf::from(dir).parent().unwrap().to_owned()
69}
70
71fn run_fuzzer(sh: &Shell) -> anyhow::Result<()> {
72    let _d = sh.push_dir("./crates/syntax");
73    let _e = sh.push_env("RUSTUP_TOOLCHAIN", "nightly");
74    if cmd!(sh, "cargo fuzz --help").read().is_err() {
75        cmd!(sh, "cargo install cargo-fuzz").run()?;
76    };
77
78    // Expecting nightly rustc
79    let out = cmd!(sh, "rustc --version").read()?;
80    if !out.contains("nightly") {
81        bail!("fuzz tests require nightly rustc")
82    }
83
84    cmd!(sh, "cargo fuzz run parser").run()?;
85    Ok(())
86}
87
88fn date_iso(sh: &Shell) -> anyhow::Result<String> {
89    let res = cmd!(sh, "date -u +%Y-%m-%d").read()?;
90    Ok(res)
91}
92
93fn is_release_tag(tag: &str) -> bool {
94    tag.len() == "2020-02-24".len() && tag.starts_with(|c: char| c.is_ascii_digit())
95}