Skip to main content

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    // 1. We want to be dependency-light
17    // 2. Speed of hash maps doesn't matter, as xtask is dev tooling
18    clippy::disallowed_types
19)]
20
21mod flags;
22
23mod codegen;
24mod dist;
25mod install;
26mod metrics;
27mod pgo;
28mod publish;
29mod release;
30mod tidy;
31mod util;
32
33use anyhow::bail;
34use std::{env, path::PathBuf};
35use xshell::{Shell, cmd};
36
37fn main() -> anyhow::Result<()> {
38    let flags = flags::Xtask::from_env_or_exit();
39
40    let sh = &Shell::new()?;
41    sh.change_dir(project_root());
42
43    match flags.subcommand {
44        flags::XtaskCmd::Install(cmd) => cmd.run(sh),
45        flags::XtaskCmd::FuzzTests(_) => run_fuzzer(sh),
46        flags::XtaskCmd::Release(cmd) => cmd.run(sh),
47        flags::XtaskCmd::Dist(cmd) => cmd.run(sh),
48        flags::XtaskCmd::PublishReleaseNotes(cmd) => cmd.run(sh),
49        flags::XtaskCmd::Metrics(cmd) => cmd.run(sh),
50        flags::XtaskCmd::Codegen(cmd) => cmd.run(sh),
51        flags::XtaskCmd::Bb(cmd) => {
52            {
53                let _d = sh.push_dir("./crates/rust-analyzer");
54                cmd!(sh, "cargo build --release --features jemalloc").run()?;
55            }
56            sh.copy_file(
57                "./target/release/rust-analyzer",
58                format!("./target/rust-analyzer-{}", cmd.suffix),
59            )?;
60            Ok(())
61        }
62        flags::XtaskCmd::Tidy(cmd) => cmd.run(sh),
63    }
64}
65
66/// Returns the path to the root directory of `rust-analyzer` project.
67fn project_root() -> PathBuf {
68    let dir =
69        env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned());
70    PathBuf::from(dir).parent().unwrap().to_owned()
71}
72
73fn run_fuzzer(sh: &Shell) -> anyhow::Result<()> {
74    let _d = sh.push_dir("./crates/syntax");
75    let _e = sh.push_env("RUSTUP_TOOLCHAIN", "nightly");
76    if cmd!(sh, "cargo fuzz --help").read().is_err() {
77        cmd!(sh, "cargo install --locked cargo-fuzz").run()?;
78    };
79
80    // Expecting nightly rustc
81    let out = cmd!(sh, "rustc --version").read()?;
82    if !out.contains("nightly") {
83        bail!("fuzz tests require nightly rustc")
84    }
85
86    cmd!(sh, "cargo fuzz run parser").run()?;
87    Ok(())
88}
89
90fn date_iso(sh: &Shell) -> anyhow::Result<String> {
91    let res = cmd!(sh, "date -u +%Y-%m-%d").read()?;
92    Ok(res)
93}
94
95fn is_release_tag(tag: &str) -> bool {
96    tag.len() >= 10
97        && tag.starts_with(|c: char| c.is_ascii_digit())
98        && tag.as_bytes()[4] == b'-'
99        && tag.as_bytes()[7] == b'-'
100}