use std::path::PathBuf; /// Resolve the project root at runtime. /// /// Dev layout: /src-tauri/target/debug/ → walk up 4 levels /// Packaged: use TAURI_RESOURCE_DIR env var set by the Tauri runtime, /// falling back to a sibling `resources/` directory next to the exe. pub fn project_root() -> PathBuf { // Tauri sets this env var when running packaged; prefer it. if let Ok(res) = std::env::var("TAURI_RESOURCE_DIR") { return PathBuf::from(res); } let exe = std::env::current_exe().expect("Failed to get executable path"); // Dev: exe is at /src-tauri/target/debug/, walk up 4 levels. if let Some(root) = exe .parent() // debug/ .and_then(|p| p.parent()) // target/ .and_then(|p| p.parent()) // src-tauri/ .and_then(|p| p.parent()) // project root { if root.join("backend").exists() { return root.to_path_buf(); } } // Packaged fallback: resources/ lives next to the exe. exe.parent() .map(|p| p.join("resources")) .unwrap_or_else(|| PathBuf::from("resources")) } /// Absolute path to the bundled Python interpreter. /// Tries .venv312 first (new), falls back to .venv (legacy). pub fn python_exe() -> PathBuf { let root = project_root(); // Packaged layout: resources/python/bin/python3 let bundled = root.join("python").join("bin").join("python3"); if bundled.exists() { return bundled; } // Dev: prefer .venv312 (Python 3.12), fall back to .venv let venv312 = root.join(".venv312").join("bin").join("python3.12"); if venv312.exists() { return venv312; } root.join(".venv").join("bin").join("python3") } /// Absolute path to a script in the backend directory. pub fn backend_script(name: &str) -> PathBuf { project_root().join("backend").join(name) } /// Absolute path to a script at the project root. pub fn root_script(name: &str) -> PathBuf { project_root().join(name) }