use std::env::current_exe; use std::path::{Path, PathBuf}; use std::process::{Command, exit}; use dirs::home_dir; use rustc_version_runtime::version; fn get_home() -> String { let home_buf = home_dir() .unwrap_or(PathBuf::from("/")); let os_string = home_buf .into_os_string(); os_string .to_string_lossy() .to_string() } #[cfg(target_os = "macos")] fn get_home_search() -> PathBuf { PathBuf::from(format!("{}/Library/Frameworks/AtomicRuntime.framework", get_home())) } #[cfg(target_os = "linux")] fn get_home_search() -> PathBuf { PathBuf::from(format!("{}/.local/share/atomic-runtime", get_home())) } #[cfg(target_os = "windows")] fn get_home_search() -> PathBuf { PathBuf::from(format!("{}\\AppData\\Local\\Atomic Runtime", get_home())) } #[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() ] } #[cfg(target_os = "macos")] const PLATFORM: &str = "macOS/Darwin"; #[cfg(target_os = "linux")] const PLATFORM: &str = "Linux"; #[cfg(target_os = "windows")] const PLATFORM: &str = "Windows"; #[cfg(target_arch = "aarch64")] const ARCH: &str = "ARM64"; #[cfg(target_arch = "x86_64")] const ARCH: &str = "x86_64"; fn show_system_info() { println!("atomic-launcher: Starting atomic-launcher on {} ({})", PLATFORM, 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 {}", version()); let my_path_buf = current_exe() .unwrap_or(PathBuf::from("/")); let my_path = my_path_buf .parent() .unwrap_or(Path::new("/")) .to_str() .unwrap_or("/"); println!("atomic-launcher: Current directory: {}", my_path); let mut found_app = false; let app_path_unparsed = &format!("{}/{}", my_path, APP_DATA_PATH); let app_path = Path::new(app_path_unparsed); 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 = 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() { exit(app.wait() .unwrap_or_default() .code() .unwrap_or(255)); } else { eprintln!("atomic-launcher: Application failed to start."); exit(3); } } else { eprintln!("atomic-launcher: Could not find a valid atomic-runtime path. Aborting."); exit(2); } }