From 212001c1dfda1497c870eb91087cfb190f433e57 Mon Sep 17 00:00:00 2001 From: Amr Bashir Date: Wed, 10 Jul 2024 16:01:13 +0300 Subject: [PATCH] fix(cli): parse cargo`--target-dir` flag (#10233) * fix(cli): parse cargo`--target-dir` flag closes #10190 * clippy --- .changes/cli-target-dir-cargo-cli-flag.md | 6 + tooling/cli/src/interface/rust.rs | 161 ++++++++++++++++++---- tooling/cli/src/interface/rust/desktop.rs | 4 +- 3 files changed, 142 insertions(+), 29 deletions(-) create mode 100644 .changes/cli-target-dir-cargo-cli-flag.md diff --git a/.changes/cli-target-dir-cargo-cli-flag.md b/.changes/cli-target-dir-cargo-cli-flag.md new file mode 100644 index 000000000..e36106228 --- /dev/null +++ b/.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` diff --git a/tooling/cli/src/interface/rust.rs b/tooling/cli/src/interface/rust.rs index 330d5ac9f..f7c210131 100644 --- a/tooling/cli/src/interface/rust.rs +++ b/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, profile: String) -> crate::Result { - 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 { + get_target_dir(self.target(options), options) } } @@ -995,20 +997,39 @@ pub fn get_cargo_metadata() -> crate::Result { /// 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 { - 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 { + 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 { Ok( @@ -1019,17 +1040,11 @@ pub fn get_workspace_dir() -> crate::Result { } 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") + ); + } + } } diff --git a/tooling/cli/src/interface/rust/desktop.rs b/tooling/cli/src/interface/rust/desktop.rs index b97adb0d0..4593ad1e8 100644 --- a/tooling/cli/src/interface/rust/desktop.rs +++ b/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())