use std::fs;
use std::path::Path;
fn main() {
let in_crate = Path::new("rules/detect");
let workspace = Path::new("../../rules/detect");
let rules_dir = if in_crate.is_dir() {
in_crate
} else {
workspace
};
if !rules_dir.is_dir() {
println!(
"cargo::warning=rules/detect not found at {}, embedded rules will be empty",
rules_dir.display()
);
fs::write(
Path::new(&std::env::var("OUT_DIR").unwrap()).join("embedded_detect_rules.toml"),
"# No rules found at build time.\n",
)
.expect("failed to write empty embedded rules");
return;
}
let mut entries: Vec<_> = fs::read_dir(rules_dir)
.expect("failed to read rules/detect")
.filter_map(std::result::Result::ok)
.filter(|e| {
e.path()
.extension()
.is_some_and(|ext| ext.eq_ignore_ascii_case("toml"))
})
.map(|e| e.path())
.collect();
entries.sort();
let mut merged = String::with_capacity(1024 * 1024);
merged.push_str("# Auto-generated by build.rs — do not edit.\n");
merged.push_str(&format!("# {} rule files merged.\n\n", entries.len()));
for entry in &entries {
let content = fs::read_to_string(entry)
.unwrap_or_else(|e| panic!("failed to read {}: {e}", entry.display()));
merged.push_str(&format!(
"# ── {} ──\n",
entry.file_name().unwrap().to_string_lossy()
));
merged.push_str(&content);
merged.push('\n');
}
let out_dir = std::env::var("OUT_DIR").unwrap();
let out_path = Path::new(&out_dir).join("embedded_detect_rules.toml");
fs::write(&out_path, &merged)
.unwrap_or_else(|e| panic!("failed to write {}: {e}", out_path.display()));
println!("cargo::rerun-if-changed={}", rules_dir.display());
for entry in &entries {
println!("cargo::rerun-if-changed={}", entry.display());
}
}