Эх сурвалжийг харах

fix(cli): parse cargo`--target-dir` flag (#10233)

* fix(cli): parse cargo`--target-dir` flag

closes #10190

* clippy
Amr Bashir 1 жил өмнө
parent
commit
212001c1df

+ 6 - 0
.changes/cli-target-dir-cargo-cli-flag.md

@@ -0,0 +1,6 @@
+---
+"tauri-cli": "patch:bug"
+"@tauri-apps/cli": "patch:bug"
+---
+
+Fix cli failing to rename application when using cargo `--target-dir` flag with `tauri build` or `tauri dev`

+ 134 - 27
tooling/cli/src/interface/rust.rs

@@ -706,7 +706,7 @@ impl AppSettings for RustAppSettings {
       .expect("Cargo manifest must have the `package.name` field");
 
     let out_dir = self
-      .out_dir(options.target.clone(), get_profile_dir(options).to_string())
+      .out_dir(options)
       .with_context(|| "failed to get project out directory")?;
 
     let binary_extension: String = if self.target_triple.contains("windows") {
@@ -961,13 +961,15 @@ impl RustAppSettings {
     &self.cargo_package_settings
   }
 
-  pub fn out_dir(&self, target: Option<String>, profile: String) -> crate::Result<PathBuf> {
-    get_target_dir(
-      target
-        .as_deref()
-        .or_else(|| self.cargo_config.build().target()),
-      profile,
-    )
+  fn target<'a>(&'a self, options: &'a Options) -> Option<&'a str> {
+    options
+      .target
+      .as_deref()
+      .or_else(|| self.cargo_config.build().target())
+  }
+
+  pub fn out_dir(&self, options: &Options) -> crate::Result<PathBuf> {
+    get_target_dir(self.target(options), options)
   }
 }
 
@@ -995,20 +997,39 @@ pub fn get_cargo_metadata() -> crate::Result<CargoMetadata> {
 
 /// This function determines the 'target' directory and suffixes it with the profile
 /// to determine where the compiled binary will be located.
-fn get_target_dir(target: Option<&str>, profile: String) -> crate::Result<PathBuf> {
-  let mut path = get_cargo_metadata()
-    .with_context(|| "failed to get cargo metadata")?
-    .target_directory;
+fn get_target_dir(triple: Option<&str>, options: &Options) -> crate::Result<PathBuf> {
+  let mut path = if let Some(target) = get_cargo_option(&options.args, "--target-dir") {
+    std::env::current_dir()?.join(target)
+  } else {
+    let mut path = get_cargo_metadata()
+      .with_context(|| "failed to get cargo metadata")?
+      .target_directory;
 
-  if let Some(triple) = target {
-    path.push(triple);
-  }
+    if let Some(triple) = triple {
+      path.push(triple);
+    }
 
-  path.push(profile);
+    path
+  };
+
+  path.push(get_profile_dir(options));
 
   Ok(path)
 }
 
+#[inline]
+fn get_cargo_option<'a>(args: &'a [String], option: &'a str) -> Option<&'a str> {
+  args
+    .iter()
+    .position(|a| a.starts_with(option))
+    .and_then(|i| {
+      args[i]
+        .split_once('=')
+        .map(|(_, p)| Some(p))
+        .unwrap_or_else(|| args.get(i + 1).map(|s| s.as_str()))
+    })
+}
+
 /// Executes `cargo metadata` to get the workspace directory.
 pub fn get_workspace_dir() -> crate::Result<PathBuf> {
   Ok(
@@ -1019,17 +1040,11 @@ pub fn get_workspace_dir() -> crate::Result<PathBuf> {
 }
 
 pub fn get_profile(options: &Options) -> &str {
-  options
-    .args
-    .iter()
-    .position(|a| a.starts_with("--profile"))
-    .and_then(|i| {
-      options.args[i]
-        .split_once('=')
-        .map(|(_, p)| Some(p))
-        .unwrap_or_else(|| options.args.get(i + 1).map(|s| s.as_str()))
-    })
-    .unwrap_or(if options.debug { "dev" } else { "release" })
+  get_cargo_option(&options.args, "--profile").unwrap_or(if options.debug {
+    "dev"
+  } else {
+    "release"
+  })
 }
 
 pub fn get_profile_dir(options: &Options) -> &str {
@@ -1258,6 +1273,25 @@ fn tauri_config_to_bundle_settings(
 mod tests {
   use super::*;
 
+  #[test]
+  fn parse_cargo_option() {
+    let args = vec![
+      "build".into(),
+      "--".into(),
+      "--profile".into(),
+      "holla".into(),
+      "--features".into(),
+      "a".into(),
+      "b".into(),
+      "--target-dir".into(),
+      "path/to/dir".into(),
+    ];
+
+    assert_eq!(get_cargo_option(&args, "--profile"), Some("holla"));
+    assert_eq!(get_cargo_option(&args, "--target-dir"), Some("path/to/dir"));
+    assert_eq!(get_cargo_option(&args, "--non-existent"), None);
+  }
+
   #[test]
   fn parse_profile_from_opts() {
     let options = Options {
@@ -1318,4 +1352,77 @@ mod tests {
     };
     assert_eq!(get_profile(&options), "release");
   }
+
+  #[test]
+  fn parse_target_dir_from_opts() {
+    let current_dir = std::env::current_dir().unwrap();
+
+    let options = Options {
+      args: vec![
+        "build".into(),
+        "--".into(),
+        "--target-dir".into(),
+        "path/to/some/dir".into(),
+        "--features".into(),
+        "feat1".into(),
+      ],
+      debug: false,
+      ..Default::default()
+    };
+
+    assert_eq!(
+      get_target_dir(None, &options).unwrap(),
+      current_dir.join("path/to/some/dir/release")
+    );
+    assert_eq!(
+      get_target_dir(Some("x86_64-pc-windows-msvc"), &options).unwrap(),
+      current_dir.join("path/to/some/dir/release")
+    );
+
+    let options = Options {
+      args: vec![
+        "build".into(),
+        "--".into(),
+        "--features".into(),
+        "feat1".into(),
+      ],
+      debug: false,
+      ..Default::default()
+    };
+
+    #[cfg(windows)]
+    assert!(get_target_dir(Some("x86_64-pc-windows-msvc"), &options)
+      .unwrap()
+      .ends_with("x86_64-pc-windows-msvc\\release"));
+    #[cfg(not(windows))]
+    assert!(get_target_dir(Some("x86_64-pc-windows-msvc"), &options)
+      .unwrap()
+      .ends_with("x86_64-pc-windows-msvc/release"));
+
+    #[cfg(windows)]
+    {
+      std::env::set_var("CARGO_TARGET_DIR", "D:\\path\\to\\env\\dir");
+      assert_eq!(
+        get_target_dir(None, &options).unwrap(),
+        PathBuf::from("D:\\path\\to\\env\\dir\\release")
+      );
+      assert_eq!(
+        get_target_dir(Some("x86_64-pc-windows-msvc"), &options).unwrap(),
+        PathBuf::from("D:\\path\\to\\env\\dir\\x86_64-pc-windows-msvc\\release")
+      );
+    }
+
+    #[cfg(not(windows))]
+    {
+      std::env::set_var("CARGO_TARGET_DIR", "/path/to/env/dir");
+      assert_eq!(
+        get_target_dir(None, &options).unwrap(),
+        PathBuf::from("/path/to/env/dir/release")
+      );
+      assert_eq!(
+        get_target_dir(Some("x86_64-pc-windows-msvc"), &options).unwrap(),
+        PathBuf::from("/path/to/env/dir/x86_64-pc-windows-msvc/release")
+      );
+    }
+  }
 }

+ 2 - 2
tooling/cli/src/interface/rust/desktop.rs

@@ -2,7 +2,7 @@
 // SPDX-License-Identifier: Apache-2.0
 // SPDX-License-Identifier: MIT
 
-use super::{get_profile_dir, AppSettings, DevChild, ExitReason, Options, RustAppSettings, Target};
+use super::{AppSettings, DevChild, ExitReason, Options, RustAppSettings, Target};
 use crate::CommandExt;
 use tauri_utils::display_path;
 
@@ -125,7 +125,7 @@ pub fn build(
       options.target.replace(triple.into());
 
       let triple_out_dir = app_settings
-        .out_dir(Some(triple.into()), get_profile_dir(&options).to_string())
+        .out_dir(&options)
         .with_context(|| format!("failed to get {triple} out dir"))?;
 
       build_production_app(options, available_targets, config_features.clone())