浏览代码

feat(cli): make tauri/cli fully support projects with non-standard structure (#11258)

* feat(cli): add support for providing custom app/src paths to tauri's CLI via optional env vars

* fix tests

* rename env vars (app vs src is confusing)

* add change file

---------

Co-authored-by: Lucas Nogueira <lucas@tauri.app>
Vincent Esche 9 月之前
父节点
当前提交
e4c9268b19
共有 2 个文件被更改,包括 44 次插入25 次删除
  1. 7 0
      .changes/support-custom-repo-structure.md
  2. 37 25
      crates/tauri-cli/src/helpers/app_paths.rs

+ 7 - 0
.changes/support-custom-repo-structure.md

@@ -0,0 +1,7 @@
+---
+"@tauri-apps/cli": patch:enhance
+"tauri-cli": patch:enhance
+---
+
+Support custom project directory structure where the Tauri app folder is not a subfolder of the frontend project.
+The frontend and Tauri app project paths can be set with the `TAURI_FRONTEND_PATH` and the `TAURI_APP_PATH` environment variables respectively.

+ 37 - 25
crates/tauri-cli/src/helpers/app_paths.rs

@@ -18,6 +18,11 @@ use tauri_utils::{
 };
 
 const TAURI_GITIGNORE: &[u8] = include_bytes!("../../tauri.gitignore");
+// path to the Tauri app (Rust crate) directory, usually <cwd>/src-tauri
+const ENV_TAURI_APP_PATH: &str = "TAURI_APP_PATH";
+// path to the frontend app directory
+const ENV_TAURI_FRONTEND_PATH: &str = "TAURI_FRONTEND_PATH";
+
 static APP_DIR: OnceLock<PathBuf> = OnceLock::new();
 static TAURI_DIR: OnceLock<PathBuf> = OnceLock::new();
 
@@ -68,29 +73,33 @@ fn lookup<F: Fn(&PathBuf) -> bool>(dir: &Path, checker: F) -> Option<PathBuf> {
   None
 }
 
-pub fn resolve_tauri_dir() -> Option<PathBuf> {
-  let Ok(cwd) = current_dir() else {
-    return None;
-  };
+fn env_tauri_app_path() -> Option<PathBuf> {
+  std::env::var(ENV_TAURI_APP_PATH)
+    .map(PathBuf::from)
+    .ok()?
+    .canonicalize()
+    .ok()
+}
 
-  if cwd.join(ConfigFormat::Json.into_file_name()).exists()
-    || cwd.join(ConfigFormat::Json5.into_file_name()).exists()
-    || cwd.join(ConfigFormat::Toml.into_file_name()).exists()
-  {
-    return Some(cwd);
-  }
+fn env_tauri_frontend_path() -> Option<PathBuf> {
+  std::env::var(ENV_TAURI_FRONTEND_PATH)
+    .map(PathBuf::from)
+    .ok()?
+    .canonicalize()
+    .ok()
+}
+
+pub fn resolve_tauri_dir() -> Option<PathBuf> {
+  let src_dir = env_tauri_frontend_path().or_else(|| current_dir().ok())?;
 
-  let src_tauri = cwd.join("src-tauri");
-  if src_tauri.join(ConfigFormat::Json.into_file_name()).exists()
-    || src_tauri
-      .join(ConfigFormat::Json5.into_file_name())
-      .exists()
-    || src_tauri.join(ConfigFormat::Toml.into_file_name()).exists()
+  if src_dir.join(ConfigFormat::Json.into_file_name()).exists()
+    || src_dir.join(ConfigFormat::Json5.into_file_name()).exists()
+    || src_dir.join(ConfigFormat::Toml.into_file_name()).exists()
   {
-    return Some(src_tauri);
+    return Some(src_dir);
   }
 
-  lookup(&cwd, |path| {
+  lookup(&src_dir, |path| {
     folder_has_configuration_file(Target::Linux, path) || is_configuration_file(Target::Linux, path)
   })
   .map(|p| {
@@ -103,13 +112,15 @@ pub fn resolve_tauri_dir() -> Option<PathBuf> {
 }
 
 pub fn resolve() {
-  TAURI_DIR.set(resolve_tauri_dir().unwrap_or_else(||
-    panic!("Couldn't recognize the current folder as a Tauri project. It must contain a `{}`, `{}` or `{}` file in any subfolder.",
+  TAURI_DIR.set(resolve_tauri_dir().unwrap_or_else(|| {
+    let env_var_name = env_tauri_frontend_path().is_some().then(|| format!("`{ENV_TAURI_FRONTEND_PATH}`"));
+    panic!("Couldn't recognize the {} folder as a Tauri project. It must contain a `{}`, `{}` or `{}` file in any subfolder.",
+      env_var_name.as_deref().unwrap_or("current"),
       ConfigFormat::Json.into_file_name(),
       ConfigFormat::Json5.into_file_name(),
       ConfigFormat::Toml.into_file_name()
     )
-  )).expect("tauri dir already resolved");
+  })).expect("tauri dir already resolved");
   APP_DIR
     .set(resolve_app_dir().unwrap_or_else(|| tauri_dir().parent().unwrap().to_path_buf()))
     .expect("app dir already resolved");
@@ -122,12 +133,13 @@ pub fn tauri_dir() -> &'static PathBuf {
 }
 
 pub fn resolve_app_dir() -> Option<PathBuf> {
-  let cwd = current_dir().expect("failed to read cwd");
-  if cwd.join("package.json").exists() {
-    return Some(cwd);
+  let app_dir = env_tauri_app_path().unwrap_or_else(|| current_dir().expect("failed to read cwd"));
+
+  if app_dir.join("package.json").exists() {
+    return Some(app_dir);
   }
 
-  lookup(&cwd, |path| {
+  lookup(&app_dir, |path| {
     if let Some(file_name) = path.file_name() {
       file_name == OsStr::new("package.json")
     } else {