use std::{ env, fs, io::Write, path::{Path, PathBuf}, }; const IGNORE_DIRS: &[&str] = &[]; const IGNORE_FILES: &[&str] = &["main.lua"]; fn main() { let crate_root = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); let lua_src = crate_root.join("lua_src"); let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); let out_file = out_dir.join("bundled_modules.rs"); println!("cargo:rerun-if-changed=lua_src"); let mut entries: Vec<(String, String)> = Vec::new(); collect(&lua_src, &lua_src, &mut entries); // Files are sorted alphabetically here to make output deterministic entries.sort_by(|a, b| a.0.cmp(&b.0)); let mut out = match fs::File::create(&out_file) { Ok(f) => f, Err(e) => { eprintln!( "ERROR: could not write to '{}': {e}", out_file.display() ); std::process::exit(1); } }; writeln!(out, "// AUTO-GENERATED by build.rs").unwrap(); writeln!(out, "pub const BUNDLED_MODULES: &[(&str, &str)] = &[").unwrap(); for (module_name, rel_path) in &entries { writeln!( out, r#" ("{module_name}", include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/lua_src/{rel_path}"))),"# ).unwrap(); } writeln!(out, "];").unwrap(); eprintln!("INFORMATION: Bundled {} Lua module(s)", entries.len()); for (name, path) in &entries { eprintln!(" {name:30} ← lua_src/{path}"); } } fn collect(root: &Path, dir: &Path, out: &mut Vec<(String, String)>) { let entries = match fs::read_dir(dir) { Ok(e) => e, Err(e) => { eprintln!("ERROR: could not read '{}': {e}", dir.display()); return; } }; for entry in entries.flatten() { let path = entry.path(); let file_name = path.file_name().unwrap().to_string_lossy(); if path.is_dir() { if IGNORE_DIRS.contains(&file_name.as_ref()) { eprintln!("INFORMATION: skipping directory lua_src/{file_name}/"); continue; } collect(root, &path, out); continue; } if path.extension().and_then(|e| e.to_str()) != Some("lua") { continue; } let rel = path.strip_prefix(root).unwrap(); let rel_str = rel.to_string_lossy(); if IGNORE_FILES.contains(&rel_str.as_ref()) { eprintln!("INFORMATION: skipping file 'lua_src/{rel_str}'"); continue; } let module_name = rel .with_extension("") .components() .map(|c| c.as_os_str().to_string_lossy()) .collect::>() .join("."); out.push((module_name, rel_str.replace('\\', "/"))); } }