databuild/databuild/prost_generator.rs

92 lines
3.1 KiB
Rust

use std::env;
use std::fs;
use std::path::Path;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = env::args().collect();
if args.len() != 4 {
eprintln!("Usage: {} <proto_file> <descriptor_file> <output_file>", args[0]);
std::process::exit(1);
}
let proto_file = &args[1];
let _descriptor_file = &args[2]; // For future use if needed
let output_file = &args[3];
// Generate Rust code using proper prost-build
generate_prost_code(proto_file, output_file)?;
Ok(())
}
fn generate_prost_code(proto_file: &str, output_file: &str) -> Result<(), Box<dyn std::error::Error>> {
// Create a temporary directory for prost-build output
let temp_dir = tempfile::tempdir()?;
let temp_path = temp_dir.path();
// Configure prost-build
let mut config = prost_build::Config::new();
// Set output directory
config.out_dir(temp_path);
// Configure derive traits - prost::Message provides Debug automatically
config.type_attribute(".", "#[derive(serde::Serialize, serde::Deserialize, schemars::JsonSchema)]");
// Try to find protoc in the environment (Bazel should provide this)
if let Ok(protoc_path) = env::var("PROTOC") {
config.protoc_executable(&protoc_path);
}
// Get the directory containing the proto file for include path
let proto_path = Path::new(proto_file);
let include_dir = proto_path.parent().unwrap_or(Path::new("."));
// Try to compile the protos
match config.compile_protos(&[proto_file], &[include_dir]) {
Ok(_) => {
// Find and read the generated files
let generated_content = find_and_read_generated_files(temp_path)?;
fs::write(output_file, generated_content)?;
}
Err(e) => {
eprintln!("prost-build failed: {}", e);
eprintln!("Available environment variables:");
for (key, value) in env::vars() {
if key.contains("PROTOC") || key.contains("PATH") {
eprintln!(" {}: {}", key, value);
}
}
// This error should be surfaced to help debug the protoc issue
return Err(format!("prost-build compilation failed: {}. This indicates protoc is not available in the Bazel sandbox. Consider passing protoc path via environment or simplifying the proto dependencies.", e).into());
}
}
Ok(())
}
fn find_and_read_generated_files(dir: &Path) -> Result<String, Box<dyn std::error::Error>> {
let mut content = String::from("// Generated by prost-build\n\n");
let mut found_files = false;
for entry in fs::read_dir(dir)? {
let entry = entry?;
let path = entry.path();
if path.extension().and_then(|s| s.to_str()) == Some("rs") {
let file_content = fs::read_to_string(&path)?;
content.push_str(&file_content);
content.push('\n');
found_files = true;
}
}
if !found_files {
return Err("No generated Rust files found from prost-build".into());
}
Ok(content)
}