use std::fs; use std::path::{Path, PathBuf}; fn main() -> Result<(), Box> { let manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR")?); let proto_dir = manifest_dir.join("proto"); let out_dir = PathBuf::from(std::env::var("OUT_DIR")?); fs::create_dir_all(&out_dir)?; clean_generated_files(&out_dir)?; let protos = proto_files(&proto_dir)?; for proto in &protos { println!("cargo:rerun-if-changed={}", proto.display()); } println!("cargo:rerun-if-changed={}", proto_dir.display()); println!("cargo:rerun-if-changed=build.rs"); tonic_prost_build::configure() .build_client(true) .build_server(true) .emit_rerun_if_changed(false) .out_dir(&out_dir) .compile_protos(&protos, &[proto_dir])?; Ok(()) } fn proto_files(proto_dir: &Path) -> Result, Box> { let mut files = fs::read_dir(proto_dir)? .map(|entry| entry.map(|entry| entry.path())) .collect::, _>>()?; files.retain(|path| path.extension().is_some_and(|ext| ext == "proto")); files.sort(); Ok(files) } fn clean_generated_files(out_dir: &Path) -> Result<(), Box> { for entry in fs::read_dir(out_dir)? { let path = entry?.path(); let is_generated_rs = path.extension().is_some_and(|ext| ext == "rs") && path.file_name().is_some_and(|name| name != "mod.rs"); if is_generated_rs { fs::remove_file(path)?; } } Ok(()) }