use std::path::PathBuf; fn main() { let output = std::process::Command::new("git") .args(["rev-parse", "HEAD"]) .output() .expect("Failed to execute git"); let rev = String::from_utf8(output.stdout).expect("Failed to parse git output"); println!("cargo:rustc-env=GIT_COMMIT_SHA={rev}"); println!("cargo:rustc-rerun-if-changed=.git/HEAD"); let root = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("protos"); let descriptor_path = root.join("proto_descriptor.bin"); println!("cargo:rerun-if-changed={}", descriptor_path.display()); let descriptor_mtime = std::fs::metadata(&descriptor_path) .map(|m| m.modified().unwrap()) .unwrap_or(std::time::SystemTime::UNIX_EPOCH); let mut run_protoc = false; let proto_files = vec![root.join("report.proto")]; for proto_file in &proto_files { println!("cargo:rerun-if-changed={}", proto_file.display()); let mtime = match std::fs::metadata(proto_file) { Ok(m) => m.modified().unwrap(), Err(e) => panic!("Failed to stat proto file {}: {:?}", proto_file.display(), e), }; if mtime > descriptor_mtime { run_protoc = true; } } let mut config = prost_build::Config::new(); config.file_descriptor_set_path(&descriptor_path); // If our cached descriptor is up-to-date, we don't need to run protoc. // This is helpful so that users don't need to have protoc installed // unless they're updating the protos. if !run_protoc { config.skip_protoc_run(); } config.compile_protos(&proto_files, &[root]).expect("Failed to compile protos"); let descriptor_set = std::fs::read(descriptor_path).expect("Failed to read descriptor set"); pbjson_build::Builder::new() .register_descriptors(&descriptor_set) .expect("Failed to register descriptors") .preserve_proto_field_names() .build(&[".objdiff"]) .expect("Failed to build pbjson"); }