use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
fn source_digest() -> u64 {
fn walk(dir: &std::path::Path, files: &mut Vec<std::path::PathBuf>) {
let Ok(entries) = std::fs::read_dir(dir) else {
return;
};
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
walk(&path, files);
} else if path.extension().is_some_and(|ext| ext == "rs") {
files.push(path);
}
}
}
let mut files = Vec::new();
walk(std::path::Path::new("src"), &mut files);
files.sort();
let mut hasher = DefaultHasher::new();
for file in &files {
file.to_string_lossy().hash(&mut hasher);
if let Ok(bytes) = std::fs::read(file) {
bytes.hash(&mut hasher);
}
}
hasher.finish()
}
fn main() {
println!("cargo:rerun-if-changed=src");
println!(
"cargo:rustc-env=LANG_CHECK_BUILD_ID={:016x}",
source_digest()
);
let (proto, include) = if std::path::Path::new("proto/checker.proto").exists() {
("proto/checker.proto", "proto")
} else {
("../proto/checker.proto", "../proto")
};
println!("cargo:rerun-if-changed={proto}");
prost_build::Config::new()
.type_attribute(".", "#[derive(serde::Serialize, serde::Deserialize)]")
.compile_protos(&[proto], &[include])
.unwrap();
for name in ["forester", "tinylang", "org", "typst"] {
let dir = format!("tree-sitter-{name}/src");
let parser = format!("{dir}/parser.c");
let scanner = format!("{dir}/scanner.c");
println!("cargo:rerun-if-changed={parser}");
println!("cargo:rerun-if-changed={scanner}");
cc::Build::new()
.include(&dir)
.file(&parser)
.file(&scanner)
.warnings(false)
.compile(&format!("tree_sitter_{name}"));
}
{
let dir = "tree-sitter-bibtex/src";
let parser = format!("{dir}/parser.c");
println!("cargo:rerun-if-changed={parser}");
cc::Build::new()
.include(dir)
.file(&parser)
.warnings(false)
.compile("tree_sitter_bibtex");
}
}