Skip to content

Commit 28fb036

Browse files
samwillisamrbashirlucasfernog
authored
fix(core): Incorrect resource_dir when app run from new style target/PLATFORM+ARCH/(debug|release) dir (#8852)
* Fix resource_dir when app run from new target/someting/(debug|release) dir * Update core/tauri-utils/src/platform.rs Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com> * change file, update logic, add tests * lint * fix tests --------- Co-authored-by: Amr Bashir <amr.bashir2015@gmail.com> Co-authored-by: Lucas Nogueira <lucas@tauri.app>
1 parent ed33b85 commit 28fb036

4 files changed

Lines changed: 105 additions & 9 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"tauri-utils": patch:enhance
3+
---
4+
5+
Enhance resource directory resolution on development.

‎core/tauri-config-schema/schema.json‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1095,7 +1095,14 @@
10951095
]
10961096
},
10971097
"windows": {
1098-
"description": "List of windows that uses this capability. Can be a glob pattern.",
1098+
"description": "List of windows that uses this capability. Can be a glob pattern.\n\nOn multiwebview windows, prefer [`Self::webviews`] for a fine grained access control.",
1099+
"type": "array",
1100+
"items": {
1101+
"type": "string"
1102+
}
1103+
},
1104+
"webviews": {
1105+
"description": "List of webviews that uses this capability. Can be a glob pattern.\n\nThis is only required when using on multiwebview contexts, by default all child webviews of a window that matches [`Self::windows`] are linked.",
10991106
"type": "array",
11001107
"items": {
11011108
"type": "string"

‎core/tauri-utils/src/platform.rs‎

Lines changed: 84 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
77
use std::{
88
fmt::Display,
9-
path::{PathBuf, MAIN_SEPARATOR},
9+
path::{Path, PathBuf, MAIN_SEPARATOR},
1010
};
1111

1212
use serde::{Deserialize, Serialize};
@@ -221,6 +221,28 @@ pub fn target_triple() -> crate::Result<String> {
221221
Ok(format!("{arch}-{os}"))
222222
}
223223

224+
#[cfg(not(test))]
225+
fn is_cargo_output_directory(path: &Path) -> bool {
226+
path.join(".cargo-lock").exists()
227+
}
228+
229+
#[cfg(test)]
230+
const CARGO_OUTPUT_DIRECTORIES: &[&str] = &["debug", "release", "custom-profile"];
231+
232+
#[cfg(test)]
233+
fn is_cargo_output_directory(path: &Path) -> bool {
234+
let last_component = path
235+
.components()
236+
.last()
237+
.unwrap()
238+
.as_os_str()
239+
.to_str()
240+
.unwrap();
241+
CARGO_OUTPUT_DIRECTORIES
242+
.iter()
243+
.any(|dirname| &last_component == dirname)
244+
}
245+
224246
/// Computes the resource directory of the current environment.
225247
///
226248
/// On Windows, it's the path to the executable.
@@ -233,17 +255,32 @@ pub fn target_triple() -> crate::Result<String> {
233255
/// `${exe_dir}/../lib/${exe_name}`.
234256
///
235257
/// On MacOS, it's `${exe_dir}../Resources` (inside .app).
236-
#[allow(unused_variables)]
237258
pub fn resource_dir(package_info: &PackageInfo, env: &Env) -> crate::Result<PathBuf> {
238259
let exe = current_exe()?;
239-
let exe_dir = exe.parent().expect("failed to get exe directory");
260+
resource_dir_from(exe, package_info, env)
261+
}
262+
263+
#[allow(unused_variables)]
264+
fn resource_dir_from<P: AsRef<Path>>(
265+
exe: P,
266+
package_info: &PackageInfo,
267+
env: &Env,
268+
) -> crate::Result<PathBuf> {
269+
let exe_dir = exe.as_ref().parent().expect("failed to get exe directory");
240270
let curr_dir = exe_dir.display().to_string();
241271

242-
if curr_dir.ends_with(format!("{MAIN_SEPARATOR}target{MAIN_SEPARATOR}debug").as_str())
243-
|| curr_dir.ends_with(format!("{MAIN_SEPARATOR}target{MAIN_SEPARATOR}release").as_str())
244-
|| cfg!(target_os = "windows")
272+
let parts: Vec<&str> = curr_dir.split(MAIN_SEPARATOR).collect();
273+
let len = parts.len();
274+
275+
// Check if running from the Cargo output directory, which means it's an executable in a development machine
276+
// We check if the binary is inside a `target` folder which can be either `target/$profile` or `target/$triple/$profile`
277+
// and see if there's a .cargo-lock file along the executable
278+
// This ensures the check is safer so it doesn't affect apps in production
279+
// Windows also includes the resources in the executable folder so we check that too
280+
if cfg!(target_os = "windows")
281+
|| ((len >= 2 && parts[len - 2] == "target") || (len >= 3 && parts[len - 3] == "target"))
282+
&& is_cargo_output_directory(exe_dir)
245283
{
246-
// running from the out dir or windows
247284
return Ok(exe_dir.to_path_buf());
248285
}
249286

@@ -306,3 +343,43 @@ mod build {
306343
}
307344
}
308345
}
346+
347+
#[cfg(test)]
348+
mod tests {
349+
use std::path::PathBuf;
350+
351+
use crate::{Env, PackageInfo};
352+
353+
#[test]
354+
fn resolve_resource_dir() {
355+
let package_info = PackageInfo {
356+
name: "MyApp".into(),
357+
version: "1.0.0".parse().unwrap(),
358+
authors: "",
359+
description: "",
360+
crate_name: "",
361+
};
362+
let env = Env::default();
363+
364+
let path = PathBuf::from("/path/to/target/aarch64-apple-darwin/debug/app");
365+
let resource_dir = super::resource_dir_from(&path, &package_info, &env).unwrap();
366+
assert_eq!(resource_dir, path.parent().unwrap());
367+
368+
let path = PathBuf::from("/path/to/target/custom-profile/app");
369+
let resource_dir = super::resource_dir_from(&path, &package_info, &env).unwrap();
370+
assert_eq!(resource_dir, path.parent().unwrap());
371+
372+
let path = PathBuf::from("/path/to/target/release/app");
373+
let resource_dir = super::resource_dir_from(&path, &package_info, &env).unwrap();
374+
assert_eq!(resource_dir, path.parent().unwrap());
375+
376+
let path = PathBuf::from("/path/to/target/unknown-profile/app");
377+
let resource_dir = super::resource_dir_from(&path, &package_info, &env);
378+
#[cfg(target_os = "macos")]
379+
assert!(resource_dir.is_err());
380+
#[cfg(target_os = "linux")]
381+
assert_eq!(resource_dir.unwrap(), PathBuf::from("/usr/lib/my-app"));
382+
#[cfg(windows)]
383+
assert_eq!(resource_dir.unwrap(), path.parent().unwrap());
384+
}
385+
}

‎tooling/cli/schema.json‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1095,7 +1095,14 @@
10951095
]
10961096
},
10971097
"windows": {
1098-
"description": "List of windows that uses this capability. Can be a glob pattern.",
1098+
"description": "List of windows that uses this capability. Can be a glob pattern.\n\nOn multiwebview windows, prefer [`Self::webviews`] for a fine grained access control.",
1099+
"type": "array",
1100+
"items": {
1101+
"type": "string"
1102+
}
1103+
},
1104+
"webviews": {
1105+
"description": "List of webviews that uses this capability. Can be a glob pattern.\n\nThis is only required when using on multiwebview contexts, by default all child webviews of a window that matches [`Self::windows`] are linked.",
10991106
"type": "array",
11001107
"items": {
11011108
"type": "string"

0 commit comments

Comments
 (0)