From 2c6f70cc574a63230d97a648faafddd9eb62f95b Mon Sep 17 00:00:00 2001 From: WillLillis Date: Mon, 6 Jan 2025 22:36:16 -0500 Subject: [PATCH] feat(xtask): add `--watch` option for `build-wasm` and `check-wasm-exports` xtask commands --- Cargo.lock | Bin 68944 -> 71986 bytes xtask/Cargo.toml | 2 + xtask/src/build_wasm.rs | 30 +++++++++++--- xtask/src/check_wasm_exports.rs | 24 +++++++++-- xtask/src/main.rs | 68 +++++++++++++++++++++++++++++++- 5 files changed, 114 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3dbc7a216f0af3a37fee1223020a01af8fa5e7b0..3ca5cf0ec3792f59131d24aeb08dac4cafbe558b 100644 GIT binary patch delta 1530 zcmZXUOK6-`6vr78^LEiT4~ZsDqtb=WaNm!DnN$=6H)#=cQ7QLvjtrU1w4J0S8!?Jq z7y{~DRK7rmsaiO>n0_w(v6kI5{@Xo6wy1U=`?)TmQ`ThUr?tL_P z^XA~rt?{8EE2}a|x5mF5pk)#mRTZ$L4yKg zpe7Q9o)WG#HEF;0aBF2^zf>rtyI&nkbIs+7^1%|}t@nVzMIQ}tXVH@=lyKHtZ6heo zL?GPrpcDsVtw5oi^uW`-lhf&wUq{mWTTirJIC*Vwwh5P@zE)~(G#AD$!Nq2^Q7=AI zTo7fNcI#&<3P3x;q7#vEsw4?Ifa8=4>y5D<7z!Dq=ebqFS!56lH4;_cf{~^D!c@BU z)^Hj*KGXVT@%liIQfvF!8&gB|##$9O(#Kc)62?fCiB>C1BJm~&%A)crWEP4rtx-e` zATlx;Nt96{5F>?UoJko%I=(%3w3xY<*}~If#f56`-+vWP4ENXXxyh^Fj22E;AR{Nt z%Z$b&a&LtS5Ft3Gjq^bTBr&@k>CM zV20XAB@f;SFFcVhe~ip&$ey9qUJ)rhb0iDk?Eok*vxcmPwQ0?#z3*pQ`jyGynUxFc zunvb@p=DA|_hy%uv=AC;aMWur6_>_1MlzDD51fgp2u5qDVBBeCe4v3uh+IOXLPrwX zz6^B_NEy*sciB!s`te&=foK)WvZ6DZWuqks8ITBK3E|QOu8d_my97RPVXOfiC?hBt z2*XVW(AVQ5LtR7CKgGveFP{7D!M^zvu8$0?RvYQnIaguEC?mK>LkN1ufamZBL?)ci zG1AtHAfn7sHWVCM$U!EVaMmIu@#)CxZ8JtEYK_-A&R=%TYI;{srVqE~T0gD6UFe^B zuJKgiST`1jpr*|qUaADic|M3+O)OgPBq1_pMT`i;l#-TbhUl_U5{c$EN}r=bf(kNY zA?eif(O6OKm)17ULo>Z` z_ObNA*8Ehj7{NEz>j5s7aJ^PbzcaUJV?ZNiHiI$4r1gwTj>dwu5xK;mc&>RSX+}wv z%C^aTlc3TNs7pJWGpa4WRE>w!^ysyf9u(BsbJ^8aVm0m0KQeLf-POMb3a%oJjCmv^ zPzHp$oG&nrqRx{X@&JHQ2+Xx*U@#$H037lqkaLU*Jk@D;diwsPot~I&y>ou){#A0j z`PtFIHuv=D*+*OH%8jAED0@!t)K54d7!`jkG&mM U{C|u8!Mpi|`25a5;my&10e-aGh5!Hn delta 107 zcmV-x0F?i-vINkY1hB>nlgtaclNh8_vziTfEwlSOnFOAw{bdvxr?22eWl% z<^{81Y^eyd33i16vy^u$0kb1~Km)UBf3Fgg(#jgMIFhRdv+0;?K(kue8v(O>+A9LH NtlY3Nw}B4 Result<()> { fs::create_dir_all("target/scratch").unwrap(); - let exported_functions = concat!( - include_str!("../../lib/src/wasm/stdlib-symbols.txt"), - include_str!("../../lib/binding_web/exports.txt") + let exported_functions = format!( + "{}{}", + fs::read_to_string("lib/src/wasm/stdlib-symbols.txt")?, + fs::read_to_string("lib/binding_web/exports.txt")? ) .replace('"', "") .lines() @@ -159,9 +168,20 @@ pub fn run_wasm(args: &BuildWasm) -> Result<()> { "-o", "target/scratch/tree-sitter.js", ]); + let command = command.args(&emscripten_flags); + if args.watch { + watch_wasm!(|| build_wasm(command)); + } else { + build_wasm(command)?; + } + + Ok(()) +} + +fn build_wasm(cmd: &mut Command) -> Result<()> { bail_on_err( - &command.args(emscripten_flags).spawn()?.wait_with_output()?, + &cmd.spawn()?.wait_with_output()?, "Failed to compile the Tree-sitter WASM library", )?; diff --git a/xtask/src/check_wasm_exports.rs b/xtask/src/check_wasm_exports.rs index 3d0cab407..4bc9e9fbc 100644 --- a/xtask/src/check_wasm_exports.rs +++ b/xtask/src/check_wasm_exports.rs @@ -1,12 +1,19 @@ use std::{ collections::HashSet, io::BufRead, + path::PathBuf, process::{Command, Stdio}, + time::Duration, }; use anyhow::{anyhow, Result}; +use notify::{ + event::{AccessKind, AccessMode}, + EventKind, RecursiveMode, +}; +use notify_debouncer_full::new_debouncer; -use crate::{bail_on_err, build_wasm::run_wasm, BuildWasm}; +use crate::{bail_on_err, build_wasm::run_wasm, watch_wasm, BuildWasm, CheckWasmExports}; const EXCLUDES: [&str; 28] = [ // Unneeded because the JS side has its own way of implementing it @@ -44,15 +51,26 @@ const EXCLUDES: [&str; 28] = [ "ts_query_cursor_timeout_micros", ]; -pub fn run() -> Result<()> { +pub fn run(args: &CheckWasmExports) -> Result<()> { + if args.watch { + watch_wasm!(check_wasm_exports); + } else { + check_wasm_exports()?; + } + + Ok(()) +} + +fn check_wasm_exports() -> Result<()> { // Build the wasm module with debug symbols for wasm-objdump run_wasm(&BuildWasm { debug: true, verbose: false, docker: false, + watch: false, })?; - let mut wasm_exports = include_str!("../../lib/binding_web/exports.txt") + let mut wasm_exports = std::fs::read_to_string("lib/binding_web/exports.txt")? .lines() .map(|s| s.replace("_wasm", "").replace("byte", "index")) // remove leading and trailing quotes, trailing comma diff --git a/xtask/src/main.rs b/xtask/src/main.rs index a1333d65f..9d8069dfb 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -30,7 +30,7 @@ enum Commands { /// Bumps the version of the workspace. BumpVersion(BumpVersion), /// Checks that WASM exports are synced. - CheckWasmExports, + CheckWasmExports(CheckWasmExports), /// Runs `cargo clippy`. Clippy(Clippy), /// Fetches emscripten. @@ -82,6 +82,9 @@ struct BuildWasm { /// Run emscripten with verbose output. #[arg(long, short)] verbose: bool, + /// Rebuild when relevant files are changed. + #[arg(long, short)] + watch: bool, } #[derive(Args)] @@ -91,6 +94,13 @@ struct BumpVersion { version: Option, } +#[derive(Args)] +struct CheckWasmExports { + /// Recheck when relevant files are changed. + #[arg(long, short)] + watch: bool, +} + #[derive(Args)] struct Clippy { /// Automatically apply lint suggestions (`clippy --fix`). @@ -207,7 +217,7 @@ fn run() -> Result<()> { 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::CheckWasmExports => check_wasm_exports::run()?, + Commands::CheckWasmExports(check_options) => check_wasm_exports::run(&check_options)?, Commands::Clippy(clippy_options) => clippy::run(&clippy_options)?, Commands::FetchEmscripten => fetch::run_emscripten()?, Commands::FetchFixtures => fetch::run_fixtures()?, @@ -289,3 +299,57 @@ pub fn create_commit(repo: &Repository, msg: &str, paths: &[&str]) -> Result { + if let Err(e) = $watch_fn() { + eprintln!("{e}"); + } + + let watch_files = [ + "binding.c", + "binding.js", + "exports.txt", + "imports.js", + "prefix.js", + "suffix.js", + ] + .iter() + .map(PathBuf::from) + .collect::>(); + let (tx, rx) = std::sync::mpsc::channel(); + let mut debouncer = new_debouncer(Duration::from_secs(1), None, tx)?; + debouncer.watch("lib/binding_web", RecursiveMode::NonRecursive)?; + + for result in rx { + match result { + Ok(events) => { + for event in events { + if event.kind == EventKind::Access(AccessKind::Close(AccessMode::Write)) + && event + .paths + .iter() + .filter_map(|p| p.file_name()) + .any(|p| watch_files.contains(&PathBuf::from(p))) + { + if let Err(e) = $watch_fn() { + eprintln!("{e}"); + } + } + } + } + Err(errors) => { + return Err(anyhow!( + "{}", + errors + .into_iter() + .map(|e| e.to_string()) + .collect::>() + .join("\n") + )); + } + } + } + }; +}