use std::path::{Path, PathBuf}; use std::process; fn get_home() -> PathBuf { dirs::home_dir() .unwrap_or(PathBuf::from("/")) } #[cfg(target_os = "macos")] fn get_home_search() -> PathBuf { let mut path = get_home(); path.push("/Library/Frameworks/AtomicRuntime.framework"); path } #[cfg(target_os = "linux")] fn get_home_search() -> PathBuf { let mut path = get_home(); path.push("/.local/share/atomic-runtime"); path } #[cfg(target_os = "windows")] fn get_home_search() -> PathBuf { let mut path = get_home(); path.push("\\AppData\\Local\\Atomic Runtime"); path } #[cfg(target_os = "macos")] fn get_search_paths() -> [PathBuf; 5] { [ PathBuf::from("/Library/Frameworks/AtomicRuntime.framework"), PathBuf::from("/System/Library/Frameworks/AtomicRuntime.framework"), PathBuf::from("/usr/local/lib/atomic-runtime"), PathBuf::from("/opt/atomic-runtime"), get_home_search() ] } #[cfg(target_os = "linux")] fn get_search_paths() -> [PathBuf; 8] { [ PathBuf::from("/usr/local/lib/atomic-runtime"), PathBuf::from("/usr/local/lib64/atomic-runtime"), PathBuf::from("/usr/lib/atomic-runtime"), PathBuf::from("/usr/lib64/atomic-runtime"), PathBuf::from("/lib/atomic-runtime"), PathBuf::from("/lib64/atomic-runtime"), PathBuf::from("/opt/atomic-runtime"), get_home_search() ] } #[cfg(target_os = "windows")] fn get_search_paths() -> [PathBuf; 29] { [ PathBuf::from("C:\\Program Files\\Common Files\\Equestria.dev\\AtomicRuntime"), PathBuf::from("C:\\Program Files\\Common Files\\Equestria.dev\\Atomic Runtime"), PathBuf::from("C:\\Program Files (x86)\\Common Files\\Equestria.dev\\AtomicRuntime"), PathBuf::from("C:\\Program Files (x86)\\Common Files\\Equestria.dev\\Atomic Runtime"), PathBuf::from("C:\\Program Files (Arm)\\Common Files\\Equestria.dev\\AtomicRuntime"), PathBuf::from("C:\\Program Files (Arm)\\Common Files\\Equestria.dev\\Atomic Runtime"), PathBuf::from("C:\\Program Files\\Common Files\\AtomicRuntime"), PathBuf::from("C:\\Program Files\\Common Files\\Atomic Runtime"), PathBuf::from("C:\\Program Files (x86)\\Common Files\\AtomicRuntime"), PathBuf::from("C:\\Program Files (x86)\\Common Files\\Atomic Runtime"), PathBuf::from("C:\\Program Files (Arm)\\Common Files\\AtomicRuntime"), PathBuf::from("C:\\Program Files (Arm)\\Common Files\\Atomic Runtime"), PathBuf::from("C:\\Windows\\AtomicRuntime"), PathBuf::from("C:\\Windows\\Atomic Runtime"), PathBuf::from("C:\\Program Files\\Equestria.dev\\AtomicRuntime"), PathBuf::from("C:\\Program Files\\Equestria.dev\\Atomic Runtime"), PathBuf::from("C:\\Program Files (x86)\\Equestria.dev\\AtomicRuntime"), PathBuf::from("C:\\Program Files (x86)\\Equestria.dev\\Atomic Runtime"), PathBuf::from("C:\\Program Files (Arm)\\Equestria.dev\\AtomicRuntime"), PathBuf::from("C:\\Program Files (Arm)\\Equestria.dev\\Atomic Runtime"), PathBuf::from("C:\\Program Files\\AtomicRuntime"), PathBuf::from("C:\\Program Files\\Atomic Runtime"), PathBuf::from("C:\\Program Files (x86)\\AtomicRuntime"), PathBuf::from("C:\\Program Files (x86)\\Atomic Runtime"), PathBuf::from("C:\\Program Files (Arm)\\AtomicRuntime"), PathBuf::from("C:\\Program Files (Arm)\\Atomic Runtime"), PathBuf::from("C:\\ProgramData\\AtomicRuntime"), PathBuf::from("C:\\ProgramData\\Atomic Runtime"), get_home_search() ] } fn show_system_info() { println!("atomic-launcher: Starting atomic-launcher on {} ({})", std::env::consts::OS, std::env::consts::ARCH); } // TODO: Rename these to "Atomic" #[cfg(target_os = "macos")] const BINARY_PATH: &str = "Contents/MacOS/Electron"; #[cfg(target_os = "linux")] const BINARY_PATH: &str = "electron"; #[cfg(target_os = "windows")] const BINARY_PATH: &str = "electron.exe"; #[cfg(target_os = "macos")] const APP_DATA_PATH: &str = "../Resources/app"; #[cfg(any(target_os = "linux", target_os = "windows"))] const APP_DATA_PATH: &str = "./resources/app"; fn main() { show_system_info(); println!("atomic-launcher: Compiled against rustc {}", rustc_version_runtime::version()); let exec_path = std::env::current_exe().ok(); let work_dir = exec_path.as_ref().and_then(|p| p.parent()) .unwrap_or(Path::new("/")); println!("atomic-launcher: Current directory: {}", work_dir .to_str() .unwrap_or("/")); let mut found_app = false; let mut app_path = PathBuf::from(work_dir); app_path.push(APP_DATA_PATH); if app_path.exists() { found_app = true; } else { println!("atomic-launcher: Warning: Could not find Electron-compatible app. Looked in {}. The default atomic-runtime application will be opened instead.", app_path .to_str() .unwrap_or("/")); } let runtime_search_paths = get_search_paths(); println!("atomic-launcher: Looking for atomic-runtime in: {}", runtime_search_paths .iter() .map(|i| i .to_str() .unwrap_or("/")) .collect::>() .join(", ") .as_str()); let mut valid_path: Option = None; for path in runtime_search_paths { let path_str = path.to_str().unwrap_or("/"); if path.as_path().exists() && Path::new(&format!("{}/{}", path_str, BINARY_PATH)).exists() { valid_path = Some(path); break; } } if let Some(path) = valid_path { println!("atomic-launcher: Found atomic-runtime at {}", Path::new(&format!("{}/{}", path .to_str() .unwrap_or(""), BINARY_PATH)) .to_str() .unwrap_or("")); let mut cmd = process::Command::new(Path::new(&format!("{}/{}", path .to_str() .unwrap_or(""), BINARY_PATH))); println!("atomic-launcher: Executing: {:?}", cmd); if found_app { cmd.arg(app_path); } if let Ok(mut app) = cmd.spawn() { process::exit(app.wait() .unwrap_or_default() .code() .unwrap_or(255)); } else { eprintln!("atomic-launcher: Application failed to start."); process::exit(3); } } else { eprintln!("atomic-launcher: Could not find a valid atomic-runtime path. Aborting."); process::exit(2); } }