use std::path::PathBuf;
fn main() {
#[cfg(feature = "transport")]
transport::stage();
#[cfg(feature = "hooks")]
hooks::stage();
let proto_dir = PathBuf::from("proto");
let common_dir = PathBuf::from("../../../proto");
let common_refs_proto = common_dir.join("mkit/common/v1/refs.proto");
let files = [
proto_dir.join("mkit/rpc/v1/common.proto"),
proto_dir.join("mkit/rpc/v1/signer/signer.proto"),
proto_dir.join("mkit/rpc/v1/ssh/ssh.proto"),
proto_dir.join("mkit/rpc/v1/verify/verify.proto"),
common_refs_proto.clone(),
];
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=generated");
for f in &files {
println!("cargo:rerun-if-changed={}", f.display());
}
println!("cargo:rerun-if-env-changed=PROTOC");
println!("cargo:rerun-if-env-changed=MKIT_RPC_CODEGEN");
let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").expect("OUT_DIR"));
let marker = out_dir.join(".mkit-rpc-codegen");
if std::env::var_os("MKIT_RPC_CODEGEN").is_some() {
buffa_build::Config::new()
.files(&files)
.includes(&[&proto_dir, &common_dir])
.include_file("_includes.rs")
.generate_arbitrary(true)
.compile()
.expect("buffa codegen");
std::fs::write(&marker, b"").expect("write codegen marker");
return;
}
let _ = std::fs::remove_file(&marker);
let vendored = PathBuf::from("generated");
let mut staged = 0usize;
for entry in std::fs::read_dir(&vendored).expect("read generated/") {
let entry = entry.expect("read generated/ entry");
let path = entry.path();
if path.extension().is_some_and(|e| e == "rs") {
std::fs::copy(&path, out_dir.join(entry.file_name())).expect("stage generated module");
staged += 1;
}
}
assert!(
staged > 0,
"generated/ contains no .rs modules — run scripts/regen-rpc-proto.sh"
);
}
#[cfg(feature = "hooks")]
mod hooks {
use std::path::{Path, PathBuf};
const MARKER: &str = ".mkit-rpc-hooks-codegen";
pub(crate) fn stage() {
let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").expect("OUT_DIR")).join("hooks");
std::fs::create_dir_all(&out_dir).expect("create hooks OUT_DIR");
println!("cargo:rerun-if-changed=generated/hooks");
println!("cargo:rerun-if-env-changed=PROTOC");
println!("cargo:rerun-if-env-changed=MKIT_HOOKS_CODEGEN");
let marker = out_dir.join(MARKER);
if std::env::var_os("MKIT_HOOKS_CODEGEN").is_some() {
let root = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../../../proto")
.canonicalize()
.expect("canonical proto root not found: expected proto/ at repo root");
let hooks = root.join("mkit/server/hooks/v1/hooks.proto");
println!("cargo:rerun-if-changed={}", hooks.display());
buffa_build::Config::new()
.files(&[hooks.to_str().expect("proto path is valid UTF-8")])
.includes(&[root.to_str().expect("proto root is valid UTF-8")])
.out_dir(&out_dir)
.generate_views(false)
.generate_json(true)
.message_attribute(".mkit.server.hooks.v1.AdmitRequest", "#[doc = \"WARNING: Contains payment credentials. Never log or Debug-print this message or its credential_headers. Build with ..Default::default() for additive evolution.\"]")
.include_file("_hooks.rs")
.compile()
.expect("buffa codegen failed for the canonical hooks proto");
std::fs::write(&marker, b"").expect("write codegen marker");
return;
}
let _ = std::fs::remove_file(&marker);
let mut staged = 0usize;
for entry in std::fs::read_dir(Path::new("generated/hooks")).expect("read generated/hooks/")
{
let path = entry.expect("read generated/hooks/ entry").path();
if path.extension().is_some_and(|e| e == "rs") {
let name = path.file_name().expect("file name");
std::fs::copy(&path, out_dir.join(name)).expect("stage generated module");
staged += 1;
}
}
assert!(
staged > 0,
"generated/hooks/ contains no .rs modules: run scripts/regen-hooks-proto.sh"
);
}
}
#[cfg(feature = "transport")]
mod transport {
use std::path::{Path, PathBuf};
const MARKER: &str = ".mkit-rpc-transport-codegen";
pub(crate) fn stage() {
let out_dir = PathBuf::from(std::env::var_os("OUT_DIR").expect("OUT_DIR"));
println!("cargo:rerun-if-changed=generated/transport");
println!("cargo:rerun-if-env-changed=PROTOC");
println!("cargo:rerun-if-env-changed=MKIT_TRANSPORT_CODEGEN");
let marker = out_dir.join(MARKER);
if std::env::var_os("MKIT_TRANSPORT_CODEGEN").is_some() {
let root = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../../../proto")
.canonicalize()
.expect("canonical proto root not found: expected proto/ at repo root");
let transport = root.join("mkit/transport/v1/transport.proto");
let health = root.join("grpc/health/v1/health.proto");
println!("cargo:rerun-if-changed={}", transport.display());
println!("cargo:rerun-if-changed={}", health.display());
connectrpc_build::Config::new()
.files(&[
transport.to_str().expect("proto path is valid UTF-8"),
health.to_str().expect("proto path is valid UTF-8"),
])
.includes(&[root.to_str().expect("proto root is valid UTF-8")])
.include_file("_connectrpc.rs")
.compile()
.expect("connectrpc-build codegen failed for the canonical protos");
std::fs::write(&marker, b"").expect("write codegen marker");
return;
}
let _ = std::fs::remove_file(&marker);
let mut staged = 0usize;
for entry in
std::fs::read_dir(Path::new("generated/transport")).expect("read generated/transport/")
{
let path = entry.expect("read generated/transport/ entry").path();
if path.extension().is_some_and(|e| e == "rs") {
let name = path.file_name().expect("file name");
std::fs::copy(&path, out_dir.join(name)).expect("stage generated module");
staged += 1;
}
}
assert!(
staged > 0,
"generated/transport/ contains no .rs modules: run scripts/regen-transport-proto.sh"
);
}
}