feat(xtask): add --watch option for build-wasm and
`check-wasm-exports` xtask commands
This commit is contained in:
parent
207ef9796e
commit
2c6f70cc57
5 changed files with 252 additions and 20 deletions
|
|
@ -1,13 +1,21 @@
|
|||
use std::{
|
||||
collections::HashSet,
|
||||
ffi::{OsStr, OsString},
|
||||
fmt::Write,
|
||||
fs,
|
||||
path::PathBuf,
|
||||
process::Command,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use notify::{
|
||||
event::{AccessKind, AccessMode},
|
||||
EventKind, RecursiveMode,
|
||||
};
|
||||
use notify_debouncer_full::new_debouncer;
|
||||
|
||||
use crate::{bail_on_err, BuildWasm, EMSCRIPTEN_TAG};
|
||||
use crate::{bail_on_err, watch_wasm, BuildWasm, EMSCRIPTEN_TAG};
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum EmccSource {
|
||||
|
|
@ -95,9 +103,10 @@ pub fn run_wasm(args: &BuildWasm) -> 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",
|
||||
)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<Version>,
|
||||
}
|
||||
|
||||
#[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<Oid
|
|||
&[&parent_commit],
|
||||
)?)
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! watch_wasm {
|
||||
($watch_fn:expr) => {
|
||||
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::<HashSet<PathBuf>>();
|
||||
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::<Vec<_>>()
|
||||
.join("\n")
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue