diff --git a/Cargo.toml b/Cargo.toml index 765991ca999dee0092ed40dae962076e5022e313..50721de13fc3f0c286076280154e5c9c1ea336c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "kernel" version = "0.1.0" +build = "build.rs" [lib] name = "kernel" diff --git a/build.rs b/build.rs new file mode 100644 index 0000000000000000000000000000000000000000..53d07ee5737aa0803bb2a6b33525d5c8879bb1f3 --- /dev/null +++ b/build.rs @@ -0,0 +1,111 @@ +use std::env; +use std::fs; +use std::io::{Error, Write}; +use std::path::Path; +use std::collections::HashMap; + + +// View loc folder with subfolders, get listings +// Returns touple (folder_map, file_list) +// folder_map keys are folders, and values are lists of direct childs +// file_list is a vector of all detected files with full path +fn scan_folder(loc: &Path) -> (HashMap<String, Vec<String>>, Vec<String>) { + let mut folders: HashMap<String, Vec<String>> = HashMap::new(); + let mut files: Vec<String> = Vec::new(); + let mut current = Vec::new(); + + if loc.is_dir() { + for entry in fs::read_dir(loc).unwrap() { + let entry = entry.unwrap(); + let path = entry.path(); + let path_str = String::from(path.to_str().unwrap()).replace("\\", "/"); + + current.push(path_str.clone()); + + // if folder then scan recursively + if path.is_dir() { + let (d, mut f) = scan_folder(&path); + for (key, value) in d.into_iter() { + folders.insert(key, value); + } + + files.append(&mut f); + } else { + files.push(path_str); + } + } + + current.sort(); + folders.entry(String::from(loc.to_str().unwrap()).replace("\\", "/")).or_insert(current); + } else { + panic!("{:?} is not a folder!", loc); + } + + (folders, files) +} + +// Write folder/file information to output file +fn fill_from_location(f: &mut fs::File, loc: &Path ) -> Result<(), (Error)> { + let (folders, mut files) = scan_folder(loc); + let mut folder_it:Vec<_> = folders.keys().collect(); + + let loc_str = loc.to_str().unwrap(); + let mut idx = loc_str.len(); + + if !loc_str.ends_with("/") { + idx += 1; + } + + folder_it.sort(); + files.sort(); + for dir in folder_it.iter() { + let strip: String = dir.chars().skip(idx).collect(); + write!(f, " files.insert(b\"{}\", (b\"", strip)?; + + // Write child elements separated with \n + let sub = folders.get(*dir).unwrap(); + let mut first = true; + for child in sub.iter() { + let (_, c) = child.split_at(idx); + if first { + write!(f, "{}", c)?; + first = false; + } else { + write!(f, "\\n{}", c)?; + } + } + write!(f, "\", true));\n")?; + } + + for name in files.iter() { + let (_, strip) = name.split_at(idx); + write!(f, " files.insert(b\"{}\", (include_bytes!(\"{}\"), false));\n", strip, name)?; + } + + Ok(()) +} + +fn main() { + let out_dir = env::var("OUT_DIR").unwrap(); + let dest_path = Path::new(&out_dir).join("gen.rs"); + let mut f = fs::File::create(&dest_path).unwrap(); + let src = env::var("INITFS_FOLDER"); + + // Write header + f.write_all(b" +mod gen { + use collections::BTreeMap; + pub fn gen() -> BTreeMap<&'static [u8], (&'static [u8], bool)> { + let mut files: BTreeMap<&'static [u8], (&'static [u8], bool)> = BTreeMap::new(); +").unwrap(); + + match src { + Ok(v) => fill_from_location(&mut f, Path::new(&v)).unwrap(), + Err(e) => println!("cargo:warning=location not found: {}, please set proper INITFS_FOLDER.", e), + } + + f.write_all(b" files + } +} + ").unwrap(); +} \ No newline at end of file diff --git a/src/scheme/initfs.rs b/src/scheme/initfs.rs index 0bd37905f7f35efab1243ca248991e0e033ef1ab..e3a6a35ef01a72eebbf577e7a8abbe1cdb06ed37 100644 --- a/src/scheme/initfs.rs +++ b/src/scheme/initfs.rs @@ -15,8 +15,7 @@ mod gen { } #[cfg(not(test))] -#[path="../../../build/userspace/initfs.rs"] -mod gen; +include!(concat!(env!("OUT_DIR"), "/gen.rs")); struct Handle { path: &'static [u8],