use std::fs; use std::path::{Path, PathBuf}; fn main() -> Result<(), Box> { let manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR")?); let out_dir = PathBuf::from(std::env::var("OUT_DIR")?); fs::create_dir_all(&out_dir)?; let email_dir = manifest_dir.join("proto/email"); let email_protos = proto_files(&email_dir)?; for proto in &email_protos { println!("cargo:rerun-if-changed={}", proto.display()); } tonic_prost_build::configure() .build_client(true) .build_server(false) .out_dir(&out_dir) .compile_protos(&email_protos, &[email_dir])?; let git_dir = manifest_dir.join("proto/git"); let git_protos = proto_files(&git_dir)?; for proto in &git_protos { println!("cargo:rerun-if-changed={}", proto.display()); } tonic_prost_build::configure() .build_client(true) .build_server(false) .type_attribute( ".", "#[derive(serde::Serialize, serde::Deserialize, utoipa::ToSchema)]", ) .extern_path(".google.protobuf.Timestamp", "crate::pb::Timestamp") .out_dir(&out_dir) .compile_protos(&git_protos, &[git_dir])?; let this_dir = manifest_dir.join("proto/this"); let this_protos = proto_files(&this_dir)?; for proto in &this_protos { println!("cargo:rerun-if-changed={}", proto.display()); } tonic_prost_build::configure() .build_client(false) .build_server(true) .out_dir(&out_dir) .compile_protos(&this_protos, &[this_dir])?; let im_dir = manifest_dir.join("proto/this/im"); let im_protos = proto_files(&im_dir)?; for proto in &im_protos { println!("cargo:rerun-if-changed={}", proto.display()); } tonic_prost_build::configure() .build_client(false) .build_server(true) .out_dir(&out_dir) .compile_protos(&im_protos, &[im_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(); if files.is_empty() { return Err(format!("no .proto files found in {}", proto_dir.display()).into()); } Ok(files) }