254 lines
7.7 KiB
Rust
254 lines
7.7 KiB
Rust
mod benchmark;
|
|
mod build_wasm;
|
|
mod bump;
|
|
mod clippy;
|
|
mod fetch;
|
|
mod generate;
|
|
mod test;
|
|
mod upgrade_wasmtime;
|
|
|
|
use anstyle::{AnsiColor, Color, Style};
|
|
use anyhow::Result;
|
|
use clap::{crate_authors, Args, Command, FromArgMatches as _, Subcommand};
|
|
use semver::Version;
|
|
|
|
#[derive(Subcommand)]
|
|
#[command(about="Run various tasks", author=crate_authors!("\n"), styles=get_styles())]
|
|
enum Commands {
|
|
/// Runs `cargo benchmark` with some optional environment variables set.
|
|
Benchmark(Benchmark),
|
|
/// Compile the Tree-sitter WASM library. This will create two files in the
|
|
/// `lib/binding_web` directory: `tree-sitter.js` and `tree-sitter.wasm`.
|
|
BuildWasm(BuildWasm),
|
|
/// Compile the Tree-sitter WASM standard library.
|
|
BuildWasmStdlib,
|
|
/// Bumps the version of the workspace.
|
|
BumpVersion(BumpVersion),
|
|
/// Runs `cargo clippy`.
|
|
Clippy(Clippy),
|
|
/// Fetches emscripten.
|
|
FetchEmscripten,
|
|
/// Fetches the fixtures for testing tree-sitter.
|
|
FetchFixtures,
|
|
/// Generate the Rust bindings from the C library.
|
|
GenerateBindings,
|
|
/// Generates the fixtures for testing tree-sitter.
|
|
GenerateFixtures(GenerateFixtures),
|
|
/// Generate the list of exports from Tree-sitter WASM files.
|
|
GenerateWasmExports,
|
|
/// Run the test suite
|
|
Test(Test),
|
|
/// Run the WASM test suite
|
|
TestWasm,
|
|
/// Upgrade the wasmtime dependency.
|
|
UpgradeWasmtime(UpgradeWasmtime),
|
|
}
|
|
|
|
#[derive(Args)]
|
|
struct Benchmark {
|
|
/// The language to run the benchmarks for.
|
|
#[arg(long, short)]
|
|
language: Option<String>,
|
|
/// The example file to run the benchmarks for.
|
|
#[arg(long, short)]
|
|
example_file_name: Option<String>,
|
|
/// The number of times to parse each sample (default is 5).
|
|
#[arg(long, short, default_value = "5")]
|
|
repetition_count: u32,
|
|
/// Whether to run the benchmarks in debug mode.
|
|
#[arg(long, short = 'g')]
|
|
debug: bool,
|
|
}
|
|
|
|
#[derive(Args)]
|
|
struct BuildWasm {
|
|
/// Compile the library more quickly, with fewer optimizations
|
|
/// and more runtime assertions.
|
|
#[arg(long, short = '0')]
|
|
debug: bool,
|
|
/// Run emscripten using docker, even if \`emcc\` is installed.
|
|
/// By default, \`emcc\` will be run directly when available.
|
|
#[arg(long, short)]
|
|
docker: bool,
|
|
/// Run emscripten with verbose output.
|
|
#[arg(long, short)]
|
|
verbose: bool,
|
|
}
|
|
|
|
#[derive(Args)]
|
|
struct BumpVersion {
|
|
/// The version to bump to.
|
|
#[arg(long, short)]
|
|
version: Option<Version>,
|
|
}
|
|
|
|
#[derive(Args)]
|
|
struct Clippy {
|
|
/// Automatically apply lint suggestions (`clippy --fix`).
|
|
#[arg(long, short)]
|
|
fix: bool,
|
|
/// The package to run Clippy against (`cargo -p <PACKAGE> clippy`).
|
|
#[arg(long, short)]
|
|
package: Option<String>,
|
|
}
|
|
|
|
#[derive(Args)]
|
|
struct GenerateFixtures {
|
|
/// Generates the parser to WASM
|
|
#[arg(long, short)]
|
|
wasm: bool,
|
|
/// Run emscripten via docker even if it is installed locally.
|
|
#[arg(long, short, requires = "wasm")]
|
|
docker: bool,
|
|
}
|
|
|
|
#[derive(Args)]
|
|
struct Test {
|
|
/// Compile C code with the Clang address sanitizer.
|
|
#[arg(long, short)]
|
|
address_sanitizer: bool,
|
|
/// Run only the corpus tests for the given language.
|
|
#[arg(long, short)]
|
|
language: Option<String>,
|
|
/// Run only the corpus tests whose name contain the given string.
|
|
#[arg(long, short)]
|
|
example: Option<String>,
|
|
/// Run the given number of iterations of randomized tests (default 10).
|
|
#[arg(long, short)]
|
|
iterations: Option<u32>,
|
|
/// Set the seed used to control random behavior.
|
|
#[arg(long, short)]
|
|
seed: Option<u32>,
|
|
/// Print parsing log to stderr.
|
|
#[arg(long, short)]
|
|
debug: bool,
|
|
/// Generate an SVG graph of parsing logs.
|
|
#[arg(long, short = 'D')]
|
|
debug_graph: bool,
|
|
/// Run the tests with a debugger.
|
|
#[arg(short)]
|
|
g: bool,
|
|
#[arg(trailing_var_arg = true)]
|
|
args: Vec<String>,
|
|
/// Don't capture the output
|
|
#[arg(long)]
|
|
nocapture: bool,
|
|
}
|
|
|
|
#[derive(Args)]
|
|
struct UpgradeWasmtime {
|
|
/// The version to upgrade to.
|
|
#[arg(long, short)]
|
|
version: Version,
|
|
}
|
|
|
|
const BUILD_VERSION: &str = env!("CARGO_PKG_VERSION");
|
|
const BUILD_SHA: Option<&str> = option_env!("BUILD_SHA");
|
|
const EMSCRIPTEN_VERSION: &str = include_str!("../../cli/loader/emscripten-version");
|
|
const EMSCRIPTEN_TAG: &str = concat!(
|
|
"docker.io/emscripten/emsdk:",
|
|
include_str!("../../cli/loader/emscripten-version")
|
|
);
|
|
|
|
fn main() {
|
|
let result = run();
|
|
if let Err(err) = &result {
|
|
// Ignore BrokenPipe errors
|
|
if let Some(error) = err.downcast_ref::<std::io::Error>() {
|
|
if error.kind() == std::io::ErrorKind::BrokenPipe {
|
|
return;
|
|
}
|
|
}
|
|
if !err.to_string().is_empty() {
|
|
eprintln!("{err:?}");
|
|
}
|
|
std::process::exit(1);
|
|
}
|
|
}
|
|
|
|
fn run() -> Result<()> {
|
|
let version = BUILD_SHA.map_or_else(
|
|
|| BUILD_VERSION.to_string(),
|
|
|build_sha| format!("{BUILD_VERSION} ({build_sha})"),
|
|
);
|
|
let version: &'static str = Box::leak(version.into_boxed_str());
|
|
|
|
let cli = Command::new("xtask")
|
|
.help_template(
|
|
"\
|
|
{before-help}{name} {version}
|
|
{author-with-newline}{about-with-newline}
|
|
{usage-heading} {usage}
|
|
|
|
{all-args}{after-help}
|
|
",
|
|
)
|
|
.version(version)
|
|
.subcommand_required(true)
|
|
.arg_required_else_help(true)
|
|
.disable_help_subcommand(true)
|
|
.disable_colored_help(false);
|
|
let command = Commands::from_arg_matches(&Commands::augment_subcommands(cli).get_matches())?;
|
|
|
|
match command {
|
|
Commands::Benchmark(benchmark_options) => benchmark::run(&benchmark_options)?,
|
|
Commands::BuildWasm(build_wasm_options) => build_wasm::run_wasm(&build_wasm_options)?,
|
|
Commands::BuildWasmStdlib => build_wasm::run_wasm_stdlib()?,
|
|
Commands::BumpVersion(bump_options) => bump::run(bump_options)?,
|
|
Commands::Clippy(clippy_options) => clippy::run(&clippy_options)?,
|
|
Commands::FetchEmscripten => fetch::run_emscripten()?,
|
|
Commands::FetchFixtures => fetch::run_fixtures()?,
|
|
Commands::GenerateBindings => generate::run_bindings()?,
|
|
Commands::GenerateFixtures(generate_fixtures_options) => {
|
|
generate::run_fixtures(&generate_fixtures_options)?;
|
|
}
|
|
Commands::GenerateWasmExports => generate::run_wasm_exports()?,
|
|
Commands::Test(test_options) => test::run(&test_options)?,
|
|
Commands::TestWasm => test::run_wasm()?,
|
|
Commands::UpgradeWasmtime(upgrade_wasmtime_options) => {
|
|
upgrade_wasmtime::run(&upgrade_wasmtime_options)?;
|
|
}
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn bail_on_err(output: &std::process::Output, prefix: &str) -> Result<()> {
|
|
if !output.status.success() {
|
|
let stderr = String::from_utf8_lossy(&output.stderr);
|
|
anyhow::bail!("{prefix}:\n{stderr}");
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
#[must_use]
|
|
const fn get_styles() -> clap::builder::Styles {
|
|
clap::builder::Styles::styled()
|
|
.usage(
|
|
Style::new()
|
|
.bold()
|
|
.fg_color(Some(Color::Ansi(AnsiColor::Yellow))),
|
|
)
|
|
.header(
|
|
Style::new()
|
|
.bold()
|
|
.fg_color(Some(Color::Ansi(AnsiColor::Yellow))),
|
|
)
|
|
.literal(Style::new().fg_color(Some(Color::Ansi(AnsiColor::Green))))
|
|
.invalid(
|
|
Style::new()
|
|
.bold()
|
|
.fg_color(Some(Color::Ansi(AnsiColor::Red))),
|
|
)
|
|
.error(
|
|
Style::new()
|
|
.bold()
|
|
.fg_color(Some(Color::Ansi(AnsiColor::Red))),
|
|
)
|
|
.valid(
|
|
Style::new()
|
|
.bold()
|
|
.fg_color(Some(Color::Ansi(AnsiColor::Green))),
|
|
)
|
|
.placeholder(Style::new().fg_color(Some(Color::Ansi(AnsiColor::White))))
|
|
}
|