use std::{env, fs, path::Path};
use walkdir::WalkDir;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let manifest_dir_str = env::var("CARGO_MANIFEST_DIR")?;
let manifest_dir = Path::new(&manifest_dir_str);
let proto_dir = manifest_dir.join("src/proto");
fs::create_dir_all(&proto_dir)?;
let messages_file = proto_dir.join("evnode.v1.messages.rs");
let services_file = proto_dir.join("evnode.v1.services.rs");
let force_regen = env::var("EV_TYPES_FORCE_PROTO_GEN").is_ok();
if !force_regen && messages_file.exists() && services_file.exists() {
println!("cargo:warning=Using pre-generated proto files. Set EV_TYPES_FORCE_PROTO_GEN=1 to regenerate.");
return Ok(());
}
let proto_root = match manifest_dir.join("../../../proto").canonicalize() {
Ok(path) => path,
Err(e) => {
if messages_file.exists() && services_file.exists() {
println!("cargo:warning=Proto source files not found at ../../../proto, using pre-generated files");
return Ok(());
}
return Err(format!(
"Proto files not found and no pre-generated files available: {e}"
)
.into());
}
};
let proto_files: Vec<_> = WalkDir::new(&proto_root)
.into_iter()
.filter_map(|e| {
let p = e.ok()?.into_path();
(p.extension()?.to_str()? == "proto").then_some(p)
})
.collect();
let mut prost_config = prost_build::Config::new();
prost_config.out_dir(&proto_dir);
prost_config.compile_protos(&proto_files, &[proto_root.as_path()])?;
let generated_file = proto_dir.join("evnode.v1.rs");
let messages_file = proto_dir.join("evnode.v1.messages.rs");
if generated_file.exists() {
fs::rename(&generated_file, &messages_file)?;
}
tonic_build::configure()
.build_server(true)
.build_client(true)
.out_dir(&proto_dir)
.compile(&proto_files, &[proto_root.as_path()])?;
let generated_file_2 = proto_dir.join("evnode.v1.rs");
let services_file = proto_dir.join("evnode.v1.services.rs");
if generated_file_2.exists() {
fs::rename(&generated_file_2, &services_file)?;
}
println!("cargo:rerun-if-changed={}", proto_root.display());
Ok(())
}