1use std::borrow::Cow; 2use std::env; 3use std::path::{Path, PathBuf}; 4 5#[inline] 6#[must_use] 7pub const fn is_appimage_build() -> bool { 8 match option_env!("JGENESIS_APPIMAGE_BUILD") { 9 Some(var) => !var.is_empty(), 10 None => false, 11 } 12} 13 14/// Fix relative input paths when running from inside an AppImage. 15/// 16/// The AppImage runner changes the current working directory to a subdirectory inside the AppImage 17/// package, which leads to very confusing behavior if a user passes a relative path as input. This 18/// function prefixes relative paths with the working directory that the AppImage was launched from. 19/// 20/// Returns the input path untouched if the input path is absolute or this is not an AppImage build. 21#[inline] 22#[must_use] 23pub fn fix_appimage_relative_path(path: &Path) -> Cow<'_, Path> { 24 if !is_appimage_build() || path.is_absolute() { 25 return path.into(); 26 } 27 28 let Ok(owd) = env::var("OWD") else { return path.into() }; 29 let converted = Path::new(&owd).join(path); 30 31 log::info!( 32 "Converted relative path '{}' to absolute path '{}'", 33 path.display(), 34 converted.display() 35 ); 36 37 converted.into() 38} 39 40/// Directory containing the emulator executable 41/// 42/// Returns `None` if unable to determine 43#[inline] 44#[must_use] 45pub fn determine_emulator_dir() -> Option<PathBuf> { 46 let exe_path: PathBuf = if is_appimage_build() { 47 // When running from inside an AppImage, env::current_exe() returns a path inside the mount's 48 // temp dir. 49 // 50 // APPIMAGE env var should contain the path to the AppImage file: 51 // https://docs.appimage.org/packaging-guide/environment-variables.html 52 env::var("APPIMAGE").ok()?.into() 53 } else { 54 env::current_exe().ok()? 55 }; 56 57 exe_path.parent().map(ToOwned::to_owned) 58}