use anyhow::{Context, Result};
use std::{env, fs};
use walkdir::WalkDir;
fn generate_builtin_std_library() -> Result<()> {
use std::path::PathBuf;
let manifest_dir = env::var("CARGO_MANIFEST_DIR")
.map(PathBuf::from)
.expect("Manifest dir");
let std_dir = env::var("MICROCAD_STD_DIR")
.map(PathBuf::from)
.unwrap_or_else(|_| manifest_dir.join("../../lib/std"));
let dest_path = env::var("OUT_DIR")
.map(PathBuf::from)
.expect("Output dir")
.join("microcad_std.rs");
let sources = WalkDir::new(&std_dir)
.into_iter()
.filter_map(|e| e.ok())
.filter(|e| e.path().extension().is_some_and(|ext| ext == "µcad"))
.map(|entry| {
let path = entry.path();
let rel_path = path
.strip_prefix(&std_dir)
.expect("Some prefix")
.to_path_buf();
let content = fs::read_to_string(path).expect("Unable to read file");
(rel_path, content)
})
.collect::<Vec<_>>();
assert!(
!sources.is_empty(),
"{std_dir:?} does not contain a µcad std library!"
);
let mut code = String::new();
code.push_str(
"
mod microcad_std {
use std::path::PathBuf;
use std::collections::HashMap;
lazy_static::lazy_static! {
pub static ref FILES: HashMap<PathBuf, String> = {
let mut m = HashMap::new();
",
);
for (path, content) in sources {
let path_str = path.to_string_lossy();
code.push_str(&format!(
" m.insert(PathBuf::from(r#\"{path_str}\"#), r#\"{content}\"#.to_string());\n"
));
}
code.push_str(
"
m
};
}
}
",
);
match rustfmt_wrapper::rustfmt(code) {
Ok(code) =>
{
fs::write(&dest_path, code).context(format!("cannot create file '{dest_path:?}'"))?;
println!(
"cargo:rerun-if-changed={std_dir}",
std_dir = std_dir.display()
);
Ok(())
}
Err(rustfmt_wrapper::Error::Rustfmt(msg)) => {
Err(anyhow::Error::msg(msg.clone())).context(msg)
}
Err(err) => Err(anyhow::Error::new(err)),
}
}
fn main() {
generate_builtin_std_library().expect("No error");
}