use std::path::{Path, PathBuf};
use std::{env, fs};
use anyhow::Context;
use miden_node_proto_build::{
block_producer_api_descriptor,
rpc_api_descriptor,
store_block_producer_api_descriptor,
store_ntx_builder_api_descriptor,
store_rpc_api_descriptor,
store_shared_api_descriptor,
};
use tonic_build::FileDescriptorSet;
fn main() -> anyhow::Result<()> {
println!("cargo::rerun-if-changed=../../proto/proto");
println!("cargo::rerun-if-env-changed=BUILD_PROTO");
if env::var("BUILD_PROTO").unwrap_or("0".to_string()) == "0" {
return Ok(());
}
let crate_root: PathBuf =
env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR should be set").into();
let dst_dir = crate_root.join("src").join("generated");
fs::remove_dir_all(&dst_dir).context("removing existing files")?;
fs::create_dir(&dst_dir).context("creating destination folder")?;
generate_bindings(rpc_api_descriptor(), &dst_dir)?;
generate_bindings(store_rpc_api_descriptor(), &dst_dir)?;
generate_bindings(store_ntx_builder_api_descriptor(), &dst_dir)?;
generate_bindings(store_block_producer_api_descriptor(), &dst_dir)?;
generate_bindings(store_shared_api_descriptor(), &dst_dir)?;
generate_bindings(block_producer_api_descriptor(), &dst_dir)?;
generate_mod_rs(&dst_dir).context("generating mod.rs")?;
Ok(())
}
fn generate_bindings(file_descriptors: FileDescriptorSet, dst_dir: &Path) -> anyhow::Result<()> {
let mut prost_config = prost_build::Config::new();
prost_config.skip_debug(["AccountId", "Digest"]);
tonic_build::configure()
.out_dir(dst_dir)
.compile_fds_with_config(prost_config, file_descriptors)
.context("compiling protobufs")?;
Ok(())
}
fn generate_mod_rs(directory: impl AsRef<Path>) -> std::io::Result<()> {
let mod_filepath = directory.as_ref().join("mod.rs");
let mut submodules = Vec::new();
for entry in fs::read_dir(directory)? {
let entry = entry?;
let path = entry.path();
if path.is_file() {
let file_stem = path
.file_stem()
.and_then(|f| f.to_str())
.expect("Could not get file name")
.to_owned();
submodules.push(file_stem);
}
}
submodules.sort();
let contents = submodules.iter().map(|f| format!("pub mod {f};\n"));
let contents = std::iter::once(
"#![allow(clippy::pedantic, reason = \"generated by build.rs and tonic\")]\n".to_string(),
)
.chain(std::iter::once(
"#![allow(clippy::large_enum_variant, reason = \"generated by build.rs and tonic\")]\n\n"
.to_string(),
))
.chain(contents)
.collect::<String>();
fs::write(mod_filepath, contents)
}