fn copy_prebuilt(out_dir: &str, manifest_dir: &str) {
if let Ok(descriptor_pb) = std::env::var("DESCRIPTOR_PB") {
let knife_pb = std::env::var("KNIFE_PB")
.unwrap_or_else(|_| panic!("DESCRIPTOR_PB is set but KNIFE_PB is not"));
let enum_collision_pb = std::env::var("ENUM_COLLISION_PB")
.unwrap_or_else(|_| panic!("DESCRIPTOR_PB is set but ENUM_COLLISION_PB is not"));
let message_set_pb = std::env::var("MESSAGE_SET_PB")
.unwrap_or_else(|_| panic!("DESCRIPTOR_PB is set but MESSAGE_SET_PB is not"));
for (name, src) in &[
("descriptor.pb", descriptor_pb),
("knife.pb", knife_pb),
("enum_collision.pb", enum_collision_pb),
("message_set.pb", message_set_pb),
] {
let dst = std::path::Path::new(out_dir).join(name);
std::fs::copy(src, &dst)
.unwrap_or_else(|e| panic!("failed to copy {name} from '{src}': {e}"));
}
return;
}
let prebuilt = std::path::Path::new(manifest_dir).join("fixtures/prebuilt");
for name in &[
"descriptor.pb",
"knife.pb",
"enum_collision.pb",
"message_set.pb",
] {
let src = prebuilt.join(name);
let dst = std::path::Path::new(out_dir).join(name);
std::fs::copy(&src, &dst).unwrap_or_else(|e| panic!("failed to copy {name}: {e}"));
}
}
#[cfg(feature = "wkt-db")]
fn build_wkt_graph(out_dir: &str, manifest_dir: &str) {
use std::path::Path;
#[cfg(not(feature = "prebuilt-wkt"))]
use std::process::Command;
let wkt_rkyv_dst = format!("{out_dir}/wkt.rkyv");
let wkt_index_dst = format!("{out_dir}/wkt_index.rkyv");
#[cfg(feature = "prebuilt-wkt")]
{
let prebuilt = Path::new(manifest_dir).join("wkt/prebuilt");
for (name, dst) in &[
("wkt.rkyv", &wkt_rkyv_dst),
("wkt_index.rkyv", &wkt_index_dst),
] {
let src = prebuilt.join(name);
std::fs::copy(&src, dst)
.unwrap_or_else(|e| panic!("failed to copy {name} from wkt/prebuilt/: {e}"));
}
}
#[cfg(not(feature = "prebuilt-wkt"))]
{
if let Ok(prebuilt) = std::env::var("WKT_RKYV") {
std::fs::copy(&prebuilt, &wkt_rkyv_dst)
.unwrap_or_else(|e| panic!("failed to copy WKT_RKYV '{prebuilt}': {e}"));
let prebuilt_index = std::env::var("WKT_INDEX")
.unwrap_or_else(|_| panic!("WKT_RKYV is set but WKT_INDEX is not"));
std::fs::copy(&prebuilt_index, &wkt_index_dst)
.unwrap_or_else(|e| panic!("failed to copy WKT_INDEX '{prebuilt_index}': {e}"));
return;
}
let sources_path = Path::new(manifest_dir).join("wkt/SOURCES");
let sources_text =
std::fs::read_to_string(&sources_path).expect("failed to read wkt/SOURCES");
let proto_files: Vec<&str> = sources_text
.lines()
.map(str::trim)
.filter(|l| !l.is_empty())
.collect();
let wkt_desc_path = format!("{out_dir}/wkt.desc");
let mut cmd = Command::new("protoc");
cmd.arg(format!("--descriptor_set_out={wkt_desc_path}"));
cmd.arg("--include_imports");
for f in &proto_files {
cmd.arg(f);
}
let status = cmd
.status()
.unwrap_or_else(|e| panic!("failed to run protoc: {e}"));
assert!(status.success(), "protoc failed with status {status}");
let schemas_desc = format!("{out_dir}/schemas.desc");
let reproto_bin = std::env::var("REPROTO_BIN").unwrap_or_else(|_| "reproto".to_string());
let status = Command::new(&reproto_bin)
.arg(format!("--build-schema-db={schemas_desc}"))
.arg(format!("-O{out_dir}/reproto-out"))
.arg(format!("-I{out_dir}"))
.arg("wkt.desc")
.status()
.unwrap_or_else(|e| panic!("failed to run reproto '{reproto_bin}': {e}"));
assert!(
status.success(),
"reproto --build-schema-db failed with status {status}"
);
std::fs::copy(format!("{out_dir}/schemas/hopcroft.rkyv"), &wkt_rkyv_dst)
.unwrap_or_else(|e| panic!("failed to copy hopcroft.rkyv: {e}"));
std::fs::copy(format!("{out_dir}/schemas/index.rkyv"), &wkt_index_dst)
.unwrap_or_else(|e| panic!("failed to copy index.rkyv: {e}"));
}
}
fn main() {
let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR not set");
let manifest_dir = std::env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
copy_prebuilt(&out_dir, &manifest_dir);
#[cfg(feature = "wkt-db")]
build_wkt_graph(&out_dir, &manifest_dir);
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=wkt/SOURCES");
println!("cargo:rerun-if-changed=fixtures/schemas/knife.proto");
println!("cargo:rerun-if-changed=fixtures/schemas/enum_collision.proto");
println!("cargo:rerun-if-changed=fixtures/schemas/message_set.proto");
}