diff options
author | Daniel Silverstone <dsilvers@digital-scurf.org> | 2021-01-10 11:10:36 +0000 |
---|---|---|
committer | Daniel Silverstone <dsilvers@digital-scurf.org> | 2021-01-10 11:10:36 +0000 |
commit | 00ab17722cdb10e02e4e97cf8b098e1cb9e75978 (patch) | |
tree | edee69966fcd4d0a0d27169da3b12d7f9b42d097 /build.rs | |
parent | d373be7f55233e5802840a804bf50f3f9a717252 (diff) | |
download | subplot-00ab17722cdb10e02e4e97cf8b098e1cb9e75978.tar.gz |
resource: Support embedded the resources
We detect the content of the share/ tree at build time and embed files into it.
Symbolic links to files will be followed and the target will be embedded.
Signed-off-by: Daniel Silverstone <dsilvers@digital-scurf.org>
Diffstat (limited to 'build.rs')
-rw-r--r-- | build.rs | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..3843324 --- /dev/null +++ b/build.rs @@ -0,0 +1,88 @@ +// Build script for Subplot, locates and builds the embedded resource set from +// the share directory + +use anyhow::Result; +use std::io::Write; +use std::path::{Component, Path, PathBuf}; +use walkdir::WalkDir; + +fn path_ignore(path: &Path) -> bool { + // We have a number of rules for ignoring any given path. + path.components().any(|component| { + match component { + Component::Prefix(_) => true, + Component::RootDir => true, + Component::CurDir => true, + Component::ParentDir => true, + Component::Normal(part) => { + if let Some(part) = part.to_str() { + // We don't want dot files, tilde files, bak files + // or the python cache. Add other things here if + // there's stuff ending up in the resources tree + // which we don't want. + part.starts_with('.') + || part.ends_with('~') + || part.ends_with(".bak") + || part == "__pycache__" + } else { + // We don't want any non-unicode paths + true + } + } + } + }) +} + +fn gather_share_files() -> Result<Vec<PathBuf>> { + let base_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("share"); + println!("cargo:rerun-if-changed={}", base_path.display()); + let mut ret = Vec::new(); + for entry in WalkDir::new(&base_path) { + let entry = entry?; + let entry_path = entry.path().strip_prefix(&base_path)?; + if entry_path.components().count() == 0 || path_ignore(entry_path) { + continue; + } + // If this path part is a directory, we want to watch it but we don't + // represent directories in the resources tree + if entry.file_type().is_dir() { + println!("cargo:rerun-if-changed={}", entry.path().display()); + continue; + } + // If this is a symlink we need cargo to watch the target of the link + // even though we'll treat it as a basic file when we embed it + if entry.file_type().is_symlink() { + let target = std::fs::read_link(entry.path())?; + println!("cargo:rerun-if-changed={}", target.display()); + } + println!("cargo:rerun-if-changed={}", entry.path().display()); + ret.push(entry_path.into()); + } + + Ok(ret) +} + +fn write_out_resource_file<'a>(paths: impl Iterator<Item = &'a Path>) -> Result<()> { + let mut out_path: PathBuf = std::env::var("OUT_DIR")?.into(); + out_path.push("embedded_files.inc"); + let mut fh = std::fs::File::create(out_path)?; + writeln!(fh, "&[")?; + for entry in paths { + let sharepath = Path::new("/share").join(entry); + writeln!( + fh, + r#"({:?}, include_bytes!(concat!(env!("CARGO_MANIFEST_DIR"), {:?}))),"#, + entry.display(), + sharepath.display() + )?; + } + writeln!(fh, "]")?; + fh.flush()?; + Ok(()) +} + +fn main() { + let paths = gather_share_files().expect("Unable to scan the share tree"); + write_out_resource_file(paths.iter().map(PathBuf::as_path)) + .expect("Unable to write the resource file out"); +} |