use std::env;
use std::fs;
use std::path::{Path, PathBuf};
fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=skills/canonical");
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR"));
let canonical_root = manifest_dir.join("skills/canonical");
let out_dir = PathBuf::from(env::var("OUT_DIR").expect("OUT_DIR"));
let out_path = out_dir.join("embedded_skills.rs");
let mut relative_paths = Vec::new();
collect_relative_files(&canonical_root, &canonical_root, &mut relative_paths)
.expect("collect canonical skill files");
let mut generated =
String::from("pub(crate) static EMBEDDED_SKILL_FILES: &[EmbeddedSkillFile] = &[\n");
for relative_path in relative_paths {
let source = canonical_root.join(&relative_path);
println!("cargo:rerun-if-changed={}", source.display());
let relative_label = relative_path.to_string_lossy().replace('\\', "/");
let skill = relative_path
.components()
.next()
.and_then(|component| component.as_os_str().to_str())
.expect("skill directory");
let source_label = source.to_string_lossy().replace('\\', "/");
generated.push_str(&format!(
" EmbeddedSkillFile {{ skill: {skill:?}, relative_path: {relative_label:?}, contents: include_str!({source_label:?}) }},\n",
));
}
generated.push_str("];\n");
fs::write(out_path, generated).expect("write embedded skill manifest");
}
fn collect_relative_files(
root: &Path,
dir: &Path,
files: &mut Vec<PathBuf>,
) -> std::io::Result<()> {
let mut entries: Vec<_> = fs::read_dir(dir)?.collect::<std::result::Result<Vec<_>, _>>()?;
entries.sort_by_key(|entry| entry.file_name());
for entry in entries {
let path = entry.path();
let file_type = entry.file_type()?;
if file_type.is_dir() {
collect_relative_files(root, &path, files)?;
continue;
}
if file_type.is_file() {
let relative = path.strip_prefix(root).expect("relative canonical path");
files.push(relative.to_path_buf());
}
}
Ok(())
}