summaryrefslogtreecommitdiff
path: root/build.rs
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@digital-scurf.org>2021-01-10 11:10:36 +0000
committerDaniel Silverstone <dsilvers@digital-scurf.org>2021-01-10 11:10:36 +0000
commit00ab17722cdb10e02e4e97cf8b098e1cb9e75978 (patch)
treeedee69966fcd4d0a0d27169da3b12d7f9b42d097 /build.rs
parentd373be7f55233e5802840a804bf50f3f9a717252 (diff)
downloadsubplot-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.rs88
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");
+}