Переглянути джерело

fix(codegen): write output file when contents change (#4889)

Brian Li 3 роки тому
батько
коміт
f957cbb56c

+ 6 - 0
.changes/write-only-changed.md

@@ -0,0 +1,6 @@
+---
+"tauri-codegen": patch
+"tauri-build": patch
+---
+
+Only rewrite temporary icon files when the content change, avoid needless rebuilds.

+ 4 - 0
core/tauri-build/src/lib.rs

@@ -293,6 +293,10 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
     )?;
   }
 
+  for icon in &config.tauri.bundle.icon {
+    println!("cargo:rerun-if-changed={}", icon);
+  }
+
   #[allow(unused_mut, clippy::redundant_clone)]
   let mut resources = config.tauri.bundle.resources.clone().unwrap_or_default();
   #[cfg(windows)]

+ 20 - 36
core/tauri-codegen/src/context.rs

@@ -415,9 +415,6 @@ fn ico_icon<P: AsRef<Path>>(
   out_dir: &Path,
   path: P,
 ) -> Result<TokenStream, EmbeddedAssetsError> {
-  use std::fs::File;
-  use std::io::Write;
-
   let path = path.as_ref();
   let bytes = std::fs::read(&path)
     .unwrap_or_else(|e| panic!("failed to read icon {}: {}", path.display(), e))
@@ -434,18 +431,11 @@ fn ico_icon<P: AsRef<Path>>(
   let height = entry.height();
 
   let out_path = out_dir.join(path.file_name().unwrap());
-  let mut out_file = File::create(&out_path).map_err(|error| EmbeddedAssetsError::AssetWrite {
-    path: out_path.clone(),
+  write_if_changed(&out_path, &rgba).map_err(|error| EmbeddedAssetsError::AssetWrite {
+    path: path.to_owned(),
     error,
   })?;
 
-  out_file
-    .write_all(&rgba)
-    .map_err(|error| EmbeddedAssetsError::AssetWrite {
-      path: path.to_owned(),
-      error,
-    })?;
-
   let out_path = out_path.display().to_string();
 
   let icon = quote!(Some(#root::Icon::Rgba { rgba: include_bytes!(#out_path).to_vec(), width: #width, height: #height }));
@@ -454,27 +444,17 @@ fn ico_icon<P: AsRef<Path>>(
 
 #[cfg(target_os = "macos")]
 fn raw_icon<P: AsRef<Path>>(out_dir: &Path, path: P) -> Result<TokenStream, EmbeddedAssetsError> {
-  use std::fs::File;
-  use std::io::Write;
-
   let path = path.as_ref();
   let bytes = std::fs::read(&path)
     .unwrap_or_else(|e| panic!("failed to read icon {}: {}", path.display(), e))
     .to_vec();
 
   let out_path = out_dir.join(path.file_name().unwrap());
-  let mut out_file = File::create(&out_path).map_err(|error| EmbeddedAssetsError::AssetWrite {
-    path: out_path.clone(),
+  write_if_changed(&out_path, &bytes).map_err(|error| EmbeddedAssetsError::AssetWrite {
+    path: path.to_owned(),
     error,
   })?;
 
-  out_file
-    .write_all(&bytes)
-    .map_err(|error| EmbeddedAssetsError::AssetWrite {
-      path: path.to_owned(),
-      error,
-    })?;
-
   let out_path = out_path.display().to_string();
 
   let icon = quote!(Some(include_bytes!(#out_path).to_vec()));
@@ -486,9 +466,6 @@ fn png_icon<P: AsRef<Path>>(
   out_dir: &Path,
   path: P,
 ) -> Result<TokenStream, EmbeddedAssetsError> {
-  use std::fs::File;
-  use std::io::Write;
-
   let path = path.as_ref();
   let bytes = std::fs::read(&path)
     .unwrap_or_else(|e| panic!("failed to read icon {}: {}", path.display(), e))
@@ -505,24 +482,31 @@ fn png_icon<P: AsRef<Path>>(
   let height = reader.info().height;
 
   let out_path = out_dir.join(path.file_name().unwrap());
-  let mut out_file = File::create(&out_path).map_err(|error| EmbeddedAssetsError::AssetWrite {
-    path: out_path.clone(),
+  write_if_changed(&out_path, &buffer).map_err(|error| EmbeddedAssetsError::AssetWrite {
+    path: path.to_owned(),
     error,
   })?;
 
-  out_file
-    .write_all(&buffer)
-    .map_err(|error| EmbeddedAssetsError::AssetWrite {
-      path: path.to_owned(),
-      error,
-    })?;
-
   let out_path = out_path.display().to_string();
 
   let icon = quote!(Some(#root::Icon::Rgba { rgba: include_bytes!(#out_path).to_vec(), width: #width, height: #height }));
   Ok(icon)
 }
 
+fn write_if_changed(out_path: &Path, data: &[u8]) -> std::io::Result<()> {
+  use std::fs::File;
+  use std::io::Write;
+
+  if let Ok(curr) = std::fs::read(&out_path) {
+    if curr == data {
+      return Ok(());
+    }
+  }
+
+  let mut out_file = File::create(&out_path)?;
+  out_file.write_all(data)
+}
+
 #[cfg(any(windows, target_os = "macos", target_os = "linux"))]
 fn find_icon<F: Fn(&&String) -> bool>(
   config: &Config,