diff options
Diffstat (limited to 'build.rs')
| -rw-r--r-- | build.rs | 128 |
1 files changed, 117 insertions, 11 deletions
diff --git a/build.rs b/build.rs index ce74854..a6c5756 100644 --- a/build.rs +++ b/build.rs @@ -1,8 +1,31 @@ +use std::collections::BTreeSet; use std::env; -use std::fs; -use std::path::Path; +use std::fs::{ self, File }; +use std::io::Write; +use std::path::{ Path, PathBuf }; use std::process::Command; +struct Error(String); +impl std::fmt::Display for Error { + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) + -> std::result::Result<(), std::fmt::Error> + { + fmt.write_str(&self.0) + } +} +impl From<std::io::Error> for Error { + fn from(e: std::io::Error) -> Self { + Error(format!("System I/O error: {}", e)) + } +} +impl From<std::path::StripPrefixError> for Error { + fn from(e: std::path::StripPrefixError) -> Self { + Error(format!("Can't strip path prefix: {}", e)) + } +} +type Result<T> = std::result::Result<T, Error>; + + fn main() { match process_all() { Err(error) => println!("cargo-error={}", error), @@ -11,18 +34,25 @@ fn main() { } -fn process_all() -> std::io::Result<()> { - process_shaders()?; - process_textures()?; - process_models()?; +fn process_all() -> Result<()> { + let mut asset_paths: BTreeSet<PathBuf> = BTreeSet::new(); + + process_shaders(&mut asset_paths)?; + process_textures(&mut asset_paths)?; + process_models(&mut asset_paths)?; + + generate_asset_module(asset_paths)?; Ok(()) } -fn process_shaders() -> std::io::Result<()> { +fn process_shaders(asset_paths: &mut BTreeSet<PathBuf>) -> Result<()> +{ let out_dir = env::var_os("OUT_DIR").unwrap(); + fs::create_dir_all(Path::new(&out_dir).join("shaders/"))?; + for input in fs::read_dir("shaders")? { let input_path = input?.path(); if !input_path.is_file() { @@ -38,14 +68,14 @@ fn process_shaders() -> std::io::Result<()> { let output_path = Path::new(&out_dir) - .join(format!("{}.spv", + .join(format!("shaders/{}.spv", input_path.file_name().unwrap().to_str().unwrap())); let result = Command::new("glslang") .arg("-V") .arg(&input_path) .arg("-o") - .arg(output_path) + .arg(&output_path) .output()?; if !result.status.success() { println!("cargo::error=Failed to compile shader {}; details follow.", @@ -56,13 +86,15 @@ fn process_shaders() -> std::io::Result<()> { } println!("cargo::rerun-if-changed={}", input_path.display()); + + asset_paths.insert(output_path.to_path_buf()); } Ok(()) } -fn process_textures() -> std::io::Result<()> { +fn process_textures(asset_paths: &mut BTreeSet<PathBuf>) -> Result<()> { for input in fs::read_dir("textures")? { let input_path = input?.path(); if !input_path.is_file() { @@ -76,14 +108,26 @@ fn process_textures() -> std::io::Result<()> { continue; } + if let Some(Some(extension)) = input_path.extension() + .map(|a| a.to_str()) + { + if extension != "png" { + continue; + } + } else { + continue; + } + println!("cargo::rerun-if-changed={}", input_path.display()); + + asset_paths.insert(input_path.to_path_buf()); } Ok(()) } -fn process_models() -> std::io::Result<()> { +fn process_models(asset_paths: &mut BTreeSet<PathBuf>) -> Result<()> { for input in fs::read_dir("models")? { let input_path = input?.path(); if !input_path.is_file() { @@ -97,9 +141,71 @@ fn process_models() -> std::io::Result<()> { continue; } + if let Some(Some(extension)) = input_path.extension() + .map(|a| a.to_str()) + { + if extension != "obj" { + continue; + } + } else { + continue; + } + println!("cargo::rerun-if-changed={}", input_path.display()); + + asset_paths.insert(input_path.to_path_buf()); } Ok(()) } + +fn generate_asset_module(asset_paths: BTreeSet<PathBuf>) -> Result<()> { + let out_dir = env::var_os("OUT_DIR") + .ok_or(Error("Don't have $OUT_DIR.".to_string()))?; + let output_path = Path::new(&out_dir).join("assets.rs"); + let mut file = File::create(output_path)?; + + let source_dir = env::current_dir()?; + + println!("cargo::warning=assets {:?}", asset_paths); + writeln!(file, "#[deny(unsafe_code)]")?; + writeln!(file, "pub fn asset(name: &str) -> crate::error::Result<&[u8]> {{"); + writeln!(file, " match name {{"); + + for asset_path in asset_paths { + let name = if asset_path.starts_with(&out_dir) { + asset_path.strip_prefix(&out_dir)? + } else { + &asset_path + }.to_str() + .ok_or(Error("Can't stringify path - weird filesystem?".to_string()))?; + + let include_path = if asset_path.is_absolute() { + asset_path.to_path_buf() + } else { + Path::new(&source_dir).join(&asset_path).to_path_buf() + }; + let mut include_path = include_path.to_path_buf(); + include_path = include_path.strip_prefix(&source_dir)?.to_path_buf(); + for _ in Path::new(&out_dir).strip_prefix(&source_dir)?.components() { + include_path = Path::new("../").join(include_path).to_path_buf(); + } + let include_path = include_path + .to_str() + .ok_or(Error("Can't stringify path - weird filesystem?" + .to_string()))?; + + writeln!(file, " \"{}\" => Ok(include_bytes!(\"{}\")),", + name.escape_default(), + include_path.escape_default()); + } + + writeln!(file, " _ => Err(crate::error::Error {{"); + writeln!(file, " message: format!(\"No such asset {{:?}}\", name)"); + writeln!(file, " }})"); + writeln!(file, " }}"); + writeln!(file, "}}"); + + Ok(()) +} |