Browse Source

refactor: copy resources and sidecars on the Cargo build script (#3357)

Lucas Fernandes Nogueira 3 years ago
parent
commit
5eb72c24de

+ 3 - 2
.changes/config.json

@@ -208,7 +208,8 @@
     },
     "tauri-bundler": {
       "path": "./tooling/bundler",
-      "manager": "rust"
+      "manager": "rust",
+      "dependencies": ["tauri-utils"]
     },
     "tauri-utils": {
       "path": "./core/tauri-utils",
@@ -268,7 +269,7 @@
     "cli.rs": {
       "path": "./tooling/cli.rs",
       "manager": "rust",
-      "dependencies": ["tauri-bundler"],
+      "dependencies": ["tauri-bundler", "tauri-utils"],
       "postversion": "node ../../.scripts/covector/generate-cli-doc.js && node ../../.scripts/covector/generate-config-doc.js && cargo check"
     },
     "create-tauri-app": {

+ 8 - 0
.changes/refactor-resources-sidecar-copying.md

@@ -0,0 +1,8 @@
+---
+"cli.rs": patch
+"tauri-bundler": patch
+"tauri-utils": patch
+"tauri-build": patch
+---
+
+Move the copying of resources and sidecars from `cli.rs` to `tauri-build` so using the Cargo CLI directly processes the files for the application execution in development.

+ 1 - 1
core/tauri-build/Cargo.toml

@@ -20,7 +20,7 @@ rustdoc-args = [ "--cfg", "doc_cfg" ]
 anyhow = "1"
 quote = { version = "1", optional = true }
 tauri-codegen = { version = "1.0.0-beta.4", path = "../tauri-codegen", optional = true }
-tauri-utils = { version = "1.0.0-beta.0", path = "../tauri-utils", features = [ "build" ] }
+tauri-utils = { version = "1.0.0-beta.0", path = "../tauri-utils", features = [ "build", "resources" ] }
 cargo_toml = "0.10"
 serde_json = "1"
 

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

@@ -5,6 +5,7 @@
 #![cfg_attr(doc_cfg, feature(doc_cfg))]
 
 pub use anyhow::Result;
+use tauri_utils::resources::{external_binaries, resource_relpath, ResourcePaths};
 
 use std::path::{Path, PathBuf};
 
@@ -15,6 +16,44 @@ mod codegen;
 #[cfg_attr(doc_cfg, doc(cfg(feature = "codegen")))]
 pub use codegen::context::CodegenContext;
 
+fn copy_file(from: impl AsRef<Path>, to: impl AsRef<Path>) -> Result<()> {
+  let from = from.as_ref();
+  let to = to.as_ref();
+  if !from.exists() {
+    return Err(anyhow::anyhow!("{:?} does not exist", from));
+  }
+  if !from.is_file() {
+    return Err(anyhow::anyhow!("{:?} is not a file", from));
+  }
+  std::fs::copy(from, to)?;
+  Ok(())
+}
+
+fn copy_binaries<'a>(binaries: ResourcePaths<'a>, target_triple: &str, path: &Path) -> Result<()> {
+  for src in binaries {
+    let src = src?;
+    let dest = path.join(
+      src
+        .file_name()
+        .expect("failed to extract external binary filename")
+        .to_string_lossy()
+        .replace(&format!("-{}", target_triple), ""),
+    );
+    copy_file(&src, &dest)?;
+  }
+  Ok(())
+}
+
+/// Copies resources to a path.
+fn copy_resources(resources: ResourcePaths<'_>, path: &Path) -> Result<()> {
+  for src in resources {
+    let src = src?;
+    let dest = path.join(resource_relpath(&src));
+    copy_file(&src, &dest)?;
+  }
+  Ok(())
+}
+
 /// Attributes used on Windows.
 #[allow(dead_code)]
 #[derive(Debug)]
@@ -176,6 +215,28 @@ pub fn try_build(attributes: Attributes) -> Result<()> {
     }
   }
 
+  let target_triple = std::env::var("TARGET").unwrap();
+  let out_dir = std::env::var("OUT_DIR").unwrap();
+  // TODO: far from ideal, but there's no other way to get the target dir, see <https://github.com/rust-lang/cargo/issues/5457>
+  let target_dir = Path::new(&out_dir)
+    .parent()
+    .unwrap()
+    .parent()
+    .unwrap()
+    .parent()
+    .unwrap();
+
+  if let Some(paths) = config.tauri.bundle.external_bin {
+    copy_binaries(
+      ResourcePaths::new(external_binaries(&paths, &target_triple).as_slice(), true),
+      &target_triple,
+      target_dir,
+    )?;
+  }
+  if let Some(paths) = config.tauri.bundle.resources {
+    copy_resources(ResourcePaths::new(paths.as_slice(), true), target_dir)?;
+  }
+
   #[cfg(windows)]
   {
     use anyhow::Context;

+ 3 - 0
core/tauri-utils/Cargo.toml

@@ -31,6 +31,8 @@ serialize-to-javascript = { git = "https://github.com/chippers/serialize-to-java
 ctor = "0.1"
 json5 = { version = "0.4", optional = true }
 json-patch = "0.2"
+glob = { version = "0.3.0", optional = true }
+walkdir = { version = "2", optional = true }
 
 [target."cfg(target_os = \"linux\")".dependencies]
 heck = "0.4"
@@ -42,3 +44,4 @@ schema = ["schemars"]
 isolation = [ "aes-gcm", "ring", "once_cell" ]
 process-relaunch-dangerous-allow-symlink-macos = []
 config-json5 = [ "json5" ]
+resources = [ "glob", "walkdir" ]

+ 23 - 0
core/tauri-utils/src/lib.rs

@@ -9,6 +9,9 @@ pub mod assets;
 pub mod config;
 pub mod html;
 pub mod platform;
+/// Prepare application resources and sidecars.
+#[cfg(feature = "resources")]
+pub mod resources;
 
 /// Application pattern.
 pub mod pattern;
@@ -123,4 +126,24 @@ pub enum Error {
   /// Invalid pattern.
   #[error("invalid pattern `{0}`. Expected either `brownfield` or `isolation`.")]
   InvalidPattern(String),
+  /// Invalid glob pattern.
+  #[cfg(feature = "resources")]
+  #[error("{0}")]
+  GlobPattern(#[from] glob::PatternError),
+  /// Failed to use glob pattern.
+  #[cfg(feature = "resources")]
+  #[error("`{0}`")]
+  Glob(#[from] glob::GlobError),
+  /// Glob pattern did not find any results.
+  #[cfg(feature = "resources")]
+  #[error("path matching {0} not found.")]
+  GlobPathNotFound(String),
+  /// Error walking directory.
+  #[cfg(feature = "resources")]
+  #[error("{0}")]
+  WalkdirError(#[from] walkdir::Error),
+  /// Not allowed to walk dir.
+  #[cfg(feature = "resources")]
+  #[error("could not walk directory `{0}`, try changing `allow_walk` to true on the `ResourcePaths` constructor.")]
+  NotAllowedToWalkDir(std::path::PathBuf),
 }

+ 126 - 0
core/tauri-utils/src/resources.rs

@@ -0,0 +1,126 @@
+// Copyright 2019-2021 Tauri Programme within The Commons Conservancy
+// SPDX-License-Identifier: Apache-2.0
+// SPDX-License-Identifier: MIT
+
+use std::path::{Component, Path, PathBuf};
+
+/// Given a path (absolute or relative) to a resource file, returns the
+/// relative path from the bundle resources directory where that resource
+/// should be stored.
+pub fn resource_relpath(path: &Path) -> PathBuf {
+  let mut dest = PathBuf::new();
+  for component in path.components() {
+    match component {
+      Component::Prefix(_) => {}
+      Component::RootDir => dest.push("_root_"),
+      Component::CurDir => {}
+      Component::ParentDir => dest.push("_up_"),
+      Component::Normal(string) => dest.push(string),
+    }
+  }
+  dest
+}
+
+/// Parses the external binaries to bundle, adding the target triple suffix to each of them.
+pub fn external_binaries(external_binaries: &[String], target_triple: &str) -> Vec<String> {
+  let mut paths = Vec::new();
+  for curr_path in external_binaries {
+    paths.push(format!(
+      "{}-{}{}",
+      curr_path,
+      target_triple,
+      if cfg!(windows) { ".exe" } else { "" }
+    ));
+  }
+  paths
+}
+
+/// A helper to iterate through resources.
+pub struct ResourcePaths<'a> {
+  /// the patterns to iterate.
+  pattern_iter: std::slice::Iter<'a, String>,
+  /// the glob iterator if the path from the current iteration is a glob pattern.
+  glob_iter: Option<glob::Paths>,
+  /// the walkdir iterator if the path from the current iteration is a directory.
+  walk_iter: Option<walkdir::IntoIter>,
+  /// whether the resource paths allows directories or not.
+  allow_walk: bool,
+  /// the pattern of the current iteration.
+  current_pattern: Option<String>,
+  /// whether the current pattern is valid or not.
+  current_pattern_is_valid: bool,
+}
+
+impl<'a> ResourcePaths<'a> {
+  /// Creates a new ResourcePaths from a slice of patterns to iterate
+  pub fn new(patterns: &'a [String], allow_walk: bool) -> ResourcePaths<'a> {
+    ResourcePaths {
+      pattern_iter: patterns.iter(),
+      glob_iter: None,
+      walk_iter: None,
+      allow_walk,
+      current_pattern: None,
+      current_pattern_is_valid: false,
+    }
+  }
+}
+
+impl<'a> Iterator for ResourcePaths<'a> {
+  type Item = crate::Result<PathBuf>;
+
+  fn next(&mut self) -> Option<crate::Result<PathBuf>> {
+    loop {
+      if let Some(ref mut walk_entries) = self.walk_iter {
+        if let Some(entry) = walk_entries.next() {
+          let entry = match entry {
+            Ok(entry) => entry,
+            Err(error) => return Some(Err(crate::Error::from(error))),
+          };
+          let path = entry.path();
+          if path.is_dir() {
+            continue;
+          }
+          self.current_pattern_is_valid = true;
+          return Some(Ok(path.to_path_buf()));
+        }
+      }
+      self.walk_iter = None;
+      if let Some(ref mut glob_paths) = self.glob_iter {
+        if let Some(glob_result) = glob_paths.next() {
+          let path = match glob_result {
+            Ok(path) => path,
+            Err(error) => return Some(Err(error.into())),
+          };
+          if path.is_dir() {
+            if self.allow_walk {
+              let walk = walkdir::WalkDir::new(path);
+              self.walk_iter = Some(walk.into_iter());
+              continue;
+            } else {
+              return Some(Err(crate::Error::NotAllowedToWalkDir(path)));
+            }
+          }
+          self.current_pattern_is_valid = true;
+          return Some(Ok(path));
+        } else if let Some(current_path) = &self.current_pattern {
+          if !self.current_pattern_is_valid {
+            self.glob_iter = None;
+            return Some(Err(crate::Error::GlobPathNotFound(current_path.clone())));
+          }
+        }
+      }
+      self.glob_iter = None;
+      if let Some(pattern) = self.pattern_iter.next() {
+        self.current_pattern = Some(pattern.to_string());
+        self.current_pattern_is_valid = false;
+        let glob = match glob::glob(pattern) {
+          Ok(glob) => glob,
+          Err(error) => return Some(Err(error.into())),
+        };
+        self.glob_iter = Some(glob);
+        continue;
+      }
+      return None;
+    }
+  }
+}

+ 8 - 6
examples/sidecar/src-tauri/Cargo.lock

@@ -2715,6 +2715,7 @@ name = "tauri-utils"
 version = "1.0.0-beta.3"
 dependencies = [
  "ctor",
+ "glob",
  "heck 0.4.0",
  "html5ever",
  "json-patch",
@@ -2728,6 +2729,7 @@ dependencies = [
  "serialize-to-javascript",
  "thiserror",
  "url",
+ "walkdir",
  "zstd",
 ]
 
@@ -3076,9 +3078,9 @@ dependencies = [
 
 [[package]]
 name = "webview2-com"
-version = "0.10.0"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "381febeeb86214fd262941a2b26322c33c38bf8b565b0ddfd4a7a8d4003053a9"
+checksum = "1975ce3573344c099935fe3903f1708dac69efe8539f1efee3ae54d8f9315fbb"
 dependencies = [
  "webview2-com-macros",
  "webview2-com-sys",
@@ -3099,9 +3101,9 @@ dependencies = [
 
 [[package]]
 name = "webview2-com-sys"
-version = "0.10.0"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2e3542bb16fe61e951f87c9146571344f1e773327498efa65704a4cff472662"
+checksum = "9a746838a94b7391f707209a246e3436d81d1e71832126a65a897d3ee5511040"
 dependencies = [
  "regex",
  "serde",
@@ -3240,9 +3242,9 @@ dependencies = [
 
 [[package]]
 name = "wry"
-version = "0.13.0"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f4875fbbfc2c63f6c57c4ef84f678b1b57e3b8795443add7fbd02f3e8017e30"
+checksum = "194b2750d8fe10fef189af5e2ca09e56cb8c5458a365d2b32842b024351f58c9"
 dependencies = [
  "cocoa",
  "core-graphics",

+ 2 - 1
tooling/bundler/Cargo.toml

@@ -22,8 +22,8 @@ exclude = [
 ]
 
 [dependencies]
+tauri-utils = { version = "1.0.0-beta.3", path = "../../core/tauri-utils", features = [ "resources" ] }
 ar = "0.9.0"
-glob = "0.3.0"
 icns = "0.3"
 image = "0.23.14"
 libflate = "1.1"
@@ -48,6 +48,7 @@ bitness = "0.4"
 winreg = "0.10"
 sha2 = "0.10"
 hex = "0.4"
+glob = "0.3"
 
 [target."cfg(target_os = \"macos\")".dependencies]
 time = { version = "0.3", features = ["formatting"] }

+ 3 - 19
tooling/bundler/src/bundle/common.rs

@@ -7,7 +7,7 @@ use std::{
   ffi::OsStr,
   fs::{self, File},
   io::{self, BufWriter, Write},
-  path::{Component, Path, PathBuf},
+  path::Path,
   process::{Command, Stdio},
 };
 use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor};
@@ -133,23 +133,6 @@ pub fn copy_dir(from: &Path, to: &Path) -> crate::Result<()> {
   Ok(())
 }
 
-/// Given a path (absolute or relative) to a resource file, returns the
-/// relative path from the bundle resources directory where that resource
-/// should be stored.
-pub fn resource_relpath(path: &Path) -> PathBuf {
-  let mut dest = PathBuf::new();
-  for component in path.components() {
-    match component {
-      Component::Prefix(_) => {}
-      Component::RootDir => dest.push("_root_"),
-      Component::CurDir => {}
-      Component::ParentDir => dest.push("_up_"),
-      Component::Normal(string) => dest.push(string),
-    }
-  }
-  dest
-}
-
 /// Prints a message to stderr, in the same format that `cargo` uses,
 /// indicating that we are creating a bundle with the given filename.
 pub fn print_bundling(filename: &str) -> crate::Result<()> {
@@ -233,8 +216,9 @@ pub fn execute_with_verbosity(cmd: &mut Command, settings: &Settings) -> crate::
 
 #[cfg(test)]
 mod tests {
-  use super::{create_file, is_retina, resource_relpath};
+  use super::{create_file, is_retina};
   use std::{io::Write, path::PathBuf};
+  use tauri_utils::resources::resource_relpath;
 
   #[test]
   fn create_file_with_parent_dirs() {

+ 1 - 1
tooling/bundler/src/bundle/macos/ios.rs

@@ -45,7 +45,7 @@ pub fn bundle_project(settings: &Settings) -> crate::Result<Vec<PathBuf>> {
 
   for src in settings.resource_files() {
     let src = src?;
-    let dest = bundle_dir.join(common::resource_relpath(&src));
+    let dest = bundle_dir.join(tauri_utils::resources::resource_relpath(&src));
     common::copy_file(&src, &dest)
       .with_context(|| format!("Failed to copy resource file {:?}", src))?;
   }

+ 10 - 124
tooling/bundler/src/bundle/settings.rs

@@ -4,6 +4,7 @@
 
 use super::category::AppCategory;
 use crate::bundle::{common, platform::target_triple};
+use tauri_utils::resources::{external_binaries, ResourcePaths};
 
 use std::{
   collections::HashMap,
@@ -466,7 +467,6 @@ impl SettingsBuilder {
     } else {
       target_triple()?
     };
-    let bundle_settings = parse_external_bin(&target, self.bundle_settings)?;
 
     Ok(Settings {
       package: self.package_settings.expect("package settings is required"),
@@ -476,7 +476,14 @@ impl SettingsBuilder {
         .project_out_directory
         .expect("out directory is required"),
       binaries: self.binaries,
-      bundle_settings,
+      bundle_settings: BundleSettings {
+        external_bin: self
+          .bundle_settings
+          .external_bin
+          .as_ref()
+          .map(|bins| external_binaries(bins, &target)),
+        ..self.bundle_settings
+      },
       target,
     })
   }
@@ -636,7 +643,7 @@ impl Settings {
   pub fn copy_resources(&self, path: &Path) -> crate::Result<()> {
     for src in self.resource_files() {
       let src = src?;
-      let dest = path.join(common::resource_relpath(&src));
+      let dest = path.join(tauri_utils::resources::resource_relpath(&src));
       common::copy_file(&src, &dest)?;
     }
     Ok(())
@@ -717,124 +724,3 @@ impl Settings {
     }
   }
 }
-
-/// Parses the external binaries to bundle, adding the target triple suffix to each of them.
-fn parse_external_bin(
-  target_triple: &str,
-  bundle_settings: BundleSettings,
-) -> crate::Result<BundleSettings> {
-  let mut win_paths = Vec::new();
-  let external_bin = match bundle_settings.external_bin {
-    Some(paths) => {
-      for curr_path in paths.iter() {
-        win_paths.push(format!(
-          "{}-{}{}",
-          curr_path,
-          target_triple,
-          if cfg!(windows) { ".exe" } else { "" }
-        ));
-      }
-      Some(win_paths)
-    }
-    None => Some(vec![]),
-  };
-
-  Ok(BundleSettings {
-    external_bin,
-    ..bundle_settings
-  })
-}
-
-/// A helper to iterate through resources.
-pub struct ResourcePaths<'a> {
-  /// the patterns to iterate.
-  pattern_iter: std::slice::Iter<'a, String>,
-  /// the glob iterator if the path from the current iteration is a glob pattern.
-  glob_iter: Option<glob::Paths>,
-  /// the walkdir iterator if the path from the current iteration is a directory.
-  walk_iter: Option<walkdir::IntoIter>,
-  /// whether the resource paths allows directories or not.
-  allow_walk: bool,
-  /// the pattern of the current iteration.
-  current_pattern: Option<String>,
-  /// whether the current pattern is valid or not.
-  current_pattern_is_valid: bool,
-}
-
-impl<'a> ResourcePaths<'a> {
-  /// Creates a new ResourcePaths from a slice of patterns to iterate
-  fn new(patterns: &'a [String], allow_walk: bool) -> ResourcePaths<'a> {
-    ResourcePaths {
-      pattern_iter: patterns.iter(),
-      glob_iter: None,
-      walk_iter: None,
-      allow_walk,
-      current_pattern: None,
-      current_pattern_is_valid: false,
-    }
-  }
-}
-
-impl<'a> Iterator for ResourcePaths<'a> {
-  type Item = crate::Result<PathBuf>;
-
-  fn next(&mut self) -> Option<crate::Result<PathBuf>> {
-    loop {
-      if let Some(ref mut walk_entries) = self.walk_iter {
-        if let Some(entry) = walk_entries.next() {
-          let entry = match entry {
-            Ok(entry) => entry,
-            Err(error) => return Some(Err(crate::Error::from(error))),
-          };
-          let path = entry.path();
-          if path.is_dir() {
-            continue;
-          }
-          self.current_pattern_is_valid = true;
-          return Some(Ok(path.to_path_buf()));
-        }
-      }
-      self.walk_iter = None;
-      if let Some(ref mut glob_paths) = self.glob_iter {
-        if let Some(glob_result) = glob_paths.next() {
-          let path = match glob_result {
-            Ok(path) => path,
-            Err(error) => return Some(Err(crate::Error::from(error))),
-          };
-          if path.is_dir() {
-            if self.allow_walk {
-              let walk = walkdir::WalkDir::new(path);
-              self.walk_iter = Some(walk.into_iter());
-              continue;
-            } else {
-              let msg = format!("{:?} is a directory", path);
-              return Some(Err(crate::Error::GenericError(msg)));
-            }
-          }
-          self.current_pattern_is_valid = true;
-          return Some(Ok(path));
-        } else if let Some(current_path) = &self.current_pattern {
-          if !self.current_pattern_is_valid {
-            self.glob_iter = None;
-            return Some(Err(crate::Error::GenericError(format!(
-              "Path matching '{}' not found",
-              current_path
-            ))));
-          }
-        }
-      }
-      self.glob_iter = None;
-      if let Some(pattern) = self.pattern_iter.next() {
-        self.current_pattern = Some(pattern.to_string());
-        self.current_pattern_is_valid = false;
-        let glob = match glob::glob(pattern) {
-          Ok(glob) => glob,
-          Err(error) => return Some(Err(crate::Error::from(error))),
-        };
-        self.glob_iter = Some(glob);
-        continue;
-      }
-      return None;
-    }
-  }
-}

+ 11 - 6
tooling/bundler/src/error.rs

@@ -9,15 +9,12 @@ use thiserror::Error as DeriveError;
 #[derive(Debug, DeriveError)]
 #[non_exhaustive]
 pub enum Error {
+  /// Error running tauri_utils API.
+  #[error("{0}")]
+  Resource(#[from] tauri_utils::Error),
   /// Bundler error.
   #[error("{0}")]
   BundlerError(#[from] anyhow::Error),
-  /// Failed to use glob pattern.
-  #[error("`{0}`")]
-  GlobError(#[from] glob::GlobError),
-  /// Invalid glob pattern.
-  #[error("`{0}`")]
-  GlobPatternError(#[from] glob::PatternError),
   /// I/O error.
   #[error("`{0}`")]
   IoError(#[from] io::Error),
@@ -57,6 +54,14 @@ pub enum Error {
   #[cfg(windows)]
   #[error("`{0}`")]
   HttpError(#[from] attohttpc::Error),
+  /// Invalid glob pattern.
+  #[cfg(windows)]
+  #[error("{0}")]
+  GlobPattern(#[from] glob::PatternError),
+  /// Failed to use glob pattern.
+  #[cfg(windows)]
+  #[error("`{0}`")]
+  Glob(#[from] glob::GlobError),
   /// Failed to validate downloaded file hash.
   #[error("hash mismatch of downloaded file")]
   HashError,

+ 3 - 1
tooling/cli.rs/Cargo.lock

@@ -2380,7 +2380,6 @@ dependencies = [
  "attohttpc",
  "bitness",
  "dirs-next",
- "glob",
  "handlebars",
  "heck",
  "hex",
@@ -2394,6 +2393,7 @@ dependencies = [
  "sha2",
  "strsim",
  "tar",
+ "tauri-utils",
  "tempfile",
  "termcolor",
  "thiserror",
@@ -2453,6 +2453,7 @@ version = "1.0.0-beta.3"
 dependencies = [
  "aes-gcm",
  "ctor",
+ "glob",
  "heck",
  "html5ever",
  "json-patch",
@@ -2468,6 +2469,7 @@ dependencies = [
  "serialize-to-javascript",
  "thiserror",
  "url",
+ "walkdir",
 ]
 
 [[package]]

+ 0 - 3
tooling/cli.rs/src/build.rs

@@ -299,9 +299,6 @@ pub fn command(options: Options) -> Result<()> {
     )
     .with_context(|| "failed to build bundler settings")?;
 
-    settings.copy_resources(&out_dir)?;
-    settings.copy_binaries(&out_dir)?;
-
     let bundles = bundle_project(settings).with_context(|| "failed to bundle project")?;
 
     // If updater is active

+ 0 - 22
tooling/cli.rs/src/dev.rs

@@ -74,28 +74,6 @@ pub fn command(options: Options) -> Result<()> {
   };
   let config = get_config(merge_config.as_deref())?;
 
-  let (settings, out_dir) = {
-    let config_guard = config.lock().unwrap();
-    let config_ = config_guard.as_ref().unwrap();
-    let app_settings = crate::interface::rust::AppSettings::new(config_)?;
-    let out_dir = app_settings
-      .get_out_dir(options.target.clone(), true)
-      .with_context(|| "failed to get project out directory")?;
-    let settings = crate::interface::get_bundler_settings(
-      app_settings,
-      options.target.clone(),
-      &Default::default(),
-      config_,
-      &out_dir,
-      false,
-      None,
-    )
-    .with_context(|| "failed to build bundler settings")?;
-    (settings, out_dir)
-  };
-  settings.copy_resources(&out_dir)?;
-  settings.copy_binaries(&out_dir)?;
-
   if let Some(before_dev) = &config
     .lock()
     .unwrap()