diff --git a/src/depcheck.rs b/src/depcheck.rs index d98c24e..925e834 100644 --- a/src/depcheck.rs +++ b/src/depcheck.rs @@ -1,4 +1,6 @@ -use std::{env, fmt::Display, path::Path}; +use std::{collections::HashMap, env, fmt::Display, path::Path}; + +use crate::linux_distro::LinuxDistro; #[derive(Debug, Clone, PartialEq, Eq)] pub enum DepType { @@ -12,6 +14,7 @@ pub struct Dependency { pub name: String, pub dep_type: DepType, pub filename: String, + pub packages: HashMap, } impl Ord for Dependency { @@ -94,6 +97,8 @@ pub fn check_dependencies(deps: Vec) -> Vec { #[cfg(test)] mod tests { + use std::collections::HashMap; + use super::{check_dependency, DepType, Dependency}; #[test] @@ -102,6 +107,7 @@ mod tests { name: "libc".into(), dep_type: DepType::SharedObject, filename: "libc.so".into(), + packages: HashMap::new(), }; assert!(check_dependency(libc_dep)); @@ -113,6 +119,7 @@ mod tests { name: "ls".into(), dep_type: DepType::Executable, filename: ("ls".into()), + packages: HashMap::new(), }; assert!(check_dependency(libc_dep)); @@ -124,6 +131,7 @@ mod tests { name: "fakedep".into(), dep_type: DepType::SharedObject, filename: "fakedep.so".into(), + packages: HashMap::new(), }; assert!(!check_dependency(fake_dep)); diff --git a/src/dependencies/adb_dep.rs b/src/dependencies/adb_dep.rs index cb15a46..2c32b33 100644 --- a/src/dependencies/adb_dep.rs +++ b/src/dependencies/adb_dep.rs @@ -1,9 +1,18 @@ -use crate::depcheck::{DepType, Dependency}; +use crate::{ + depcheck::{DepType, Dependency}, + linux_distro::LinuxDistro, +}; +use std::collections::HashMap; pub fn adb_dep() -> Dependency { Dependency { name: "adb".into(), dep_type: DepType::Executable, filename: "adb".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "android-tools".into()), + (LinuxDistro::Fedora, "android-tools".into()), + (LinuxDistro::Debian, "adb".into()), + ]), } } diff --git a/src/dependencies/basalt_deps.rs b/src/dependencies/basalt_deps.rs index 678392d..5274e7b 100644 --- a/src/dependencies/basalt_deps.rs +++ b/src/dependencies/basalt_deps.rs @@ -1,4 +1,9 @@ -use crate::depcheck::{check_dependencies, DepType, Dependency, DependencyCheckResult}; +use crate::{ + depcheck::{check_dependencies, DepType, Dependency, DependencyCheckResult}, + dependencies::common::dep_eigen, + linux_distro::LinuxDistro, +}; +use std::collections::HashMap; fn basalt_deps() -> Vec { vec![ @@ -7,67 +12,111 @@ fn basalt_deps() -> Vec { dep_type: DepType::SharedObject, // just one of the many shared objects boost provides filename: "libboost_system.so".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "boost".into()), + (LinuxDistro::Debian, "libboost-all-dev".into()), + ]), }, Dependency { name: "boost-dev".into(), dep_type: DepType::Include, // just one of the many headers boost provides filename: "boost/filesystem.hpp".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "boost".into()), + (LinuxDistro::Debian, "libboost-all-dev".into()), + ]), }, Dependency { name: "bzip2".into(), dep_type: DepType::SharedObject, filename: "libbz2.so".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "bzip2".into()), + (LinuxDistro::Debian, "libbz2-dev".into()), + ]), }, Dependency { name: "bzip2-dev".into(), dep_type: DepType::Include, filename: "bzlib.h".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "bzip2".into()), + (LinuxDistro::Debian, "libbz2-dev".into()), + ]), }, - Dependency { - name: "eigen".into(), - dep_type: DepType::Include, - filename: "eigen3/Eigen/src/Core/EigenBase.h".into(), - }, + dep_eigen(), Dependency { name: "fmt".into(), dep_type: DepType::SharedObject, filename: "libfmt.so".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "fmt".into()), + (LinuxDistro::Debian, "libfmt-dev".into()), + ]), }, Dependency { name: "fmt-dev".into(), dep_type: DepType::Include, filename: "fmt/core.h".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "fmt".into()), + (LinuxDistro::Debian, "libfmt-dev".into()), + ]), }, Dependency { name: "glew".into(), dep_type: DepType::SharedObject, filename: "libGLEW.so".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "glew".into()), + (LinuxDistro::Debian, "libglew-dev".into()), + ]), }, Dependency { name: "glew-dev".into(), dep_type: DepType::Include, filename: "GL/glew.h".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "glew".into()), + (LinuxDistro::Debian, "libglew-dev".into()), + ]), }, Dependency { name: "gtest".into(), dep_type: DepType::Include, filename: "gtest/gtest.h".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "gtest".into()), + (LinuxDistro::Debian, "libgtest-dev".into()), + ]), }, Dependency { name: "opencv".into(), dep_type: DepType::Include, filename: "opencv4/opencv2/core/hal/hal.hpp".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "opencv".into()), + (LinuxDistro::Debian, "libopencv-dev".into()), + ]), }, Dependency { name: "python3".into(), dep_type: DepType::Executable, filename: "python3".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "python".into()), + (LinuxDistro::Debian, "python3".into()), + ]), }, Dependency { name: "bc".into(), dep_type: DepType::Executable, filename: "bc".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "bc".into()), + (LinuxDistro::Debian, "bc".into()), + ]), }, ] } diff --git a/src/dependencies/common.rs b/src/dependencies/common.rs new file mode 100644 index 0000000..4e4d517 --- /dev/null +++ b/src/dependencies/common.rs @@ -0,0 +1,67 @@ +use crate::{ + depcheck::{DepType, Dependency}, + linux_distro::LinuxDistro, +}; +use std::collections::HashMap; + +pub fn dep_eigen() -> Dependency { + Dependency { + name: "eigen".into(), + dep_type: DepType::Include, + filename: "eigen3/Eigen/src/Core/EigenBase.h".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "eigen".into()), + (LinuxDistro::Debian, "libeigen3-dev".into()), + ]), + } +} + +pub fn dep_cmake() -> Dependency { + Dependency { + name: "cmake".into(), + dep_type: DepType::Executable, + filename: "cmake".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "cmake".into()), + (LinuxDistro::Debian, "cmake".into()), + ]), + } +} + +pub fn dep_git() -> Dependency { + Dependency { + name: "git".into(), + dep_type: DepType::Executable, + filename: "git".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "git".into()), + (LinuxDistro::Debian, "git".into()), + (LinuxDistro::Fedora, "git".into()), + ]), + } +} + +pub fn dep_ninja() -> Dependency { + Dependency { + name: "ninja".into(), + dep_type: DepType::Executable, + filename: "ninja".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "ninja".into()), + (LinuxDistro::Debian, "ninja-build".into()), + ]), + } +} + +pub fn dep_glslang_validator() -> Dependency { + Dependency { + name: "glslang".into(), + dep_type: DepType::Executable, + filename: "glslangValidator".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "glslang".into()), + (LinuxDistro::Debian, "glslang-tools".into()), + (LinuxDistro::Fedora, "glslang-devel".into()), + ]), + } +} diff --git a/src/dependencies/libsurvive_deps.rs b/src/dependencies/libsurvive_deps.rs index b209ee0..8d16803 100644 --- a/src/dependencies/libsurvive_deps.rs +++ b/src/dependencies/libsurvive_deps.rs @@ -1,28 +1,10 @@ -use crate::depcheck::{check_dependencies, DepType, Dependency, DependencyCheckResult}; +use crate::{ + depcheck::{check_dependencies, Dependency, DependencyCheckResult}, + dependencies::common::{dep_cmake, dep_eigen, dep_git, dep_ninja}, +}; fn libsurvive_deps() -> Vec { - vec![ - Dependency { - name: "eigen".into(), - dep_type: DepType::Include, - filename: "eigen3/Eigen/src/Core/EigenBase.h".into(), - }, - Dependency { - name: "cmake".into(), - dep_type: DepType::Executable, - filename: "cmake".into(), - }, - Dependency { - name: "git".into(), - dep_type: DepType::Executable, - filename: "git".into(), - }, - Dependency { - name: "ninja".into(), - dep_type: DepType::Executable, - filename: "ninja".into(), - }, - ] + vec![dep_eigen(), dep_cmake(), dep_git(), dep_ninja()] } pub fn check_libsurvive_deps() -> Vec { diff --git a/src/dependencies/mercury_deps.rs b/src/dependencies/mercury_deps.rs index b788e9c..674f87d 100644 --- a/src/dependencies/mercury_deps.rs +++ b/src/dependencies/mercury_deps.rs @@ -1,4 +1,8 @@ -use crate::depcheck::{check_dependencies, DepType, Dependency, DependencyCheckResult}; +use crate::{ + depcheck::{check_dependencies, DepType, Dependency, DependencyCheckResult}, + linux_distro::LinuxDistro, +}; +use std::collections::HashMap; fn mercury_deps() -> Vec { vec![ @@ -6,21 +10,28 @@ fn mercury_deps() -> Vec { name: "opencv".into(), dep_type: DepType::SharedObject, filename: "libopencv_core.so".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "opencv".into()), + (LinuxDistro::Debian, "libopencv-dev".into()), + ]), }, Dependency { name: "opencv-dev".into(), dep_type: DepType::Include, filename: "opencv4/opencv2/core/base.hpp".into(), - }, - Dependency { - name: "opencv-dev".into(), - dep_type: DepType::Include, - filename: "opencv4/opencv2/core/base.hpp".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "opencv".into()), + (LinuxDistro::Debian, "libopencv-dev".into()), + ]), }, Dependency { name: "git-lfs".into(), dep_type: DepType::Executable, filename: "git-lfs".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "git-lfs".into()), + (LinuxDistro::Debian, "git-lfs".into()), + ]), }, ] } diff --git a/src/dependencies/mod.rs b/src/dependencies/mod.rs index 9203bf9..37f4ba4 100644 --- a/src/dependencies/mod.rs +++ b/src/dependencies/mod.rs @@ -1,5 +1,6 @@ pub mod adb_dep; pub mod basalt_deps; +pub mod common; pub mod libsurvive_deps; pub mod mercury_deps; pub mod monado_deps; diff --git a/src/dependencies/monado_deps.rs b/src/dependencies/monado_deps.rs index d4465d2..7bfbc1d 100644 --- a/src/dependencies/monado_deps.rs +++ b/src/dependencies/monado_deps.rs @@ -1,4 +1,9 @@ -use crate::depcheck::{check_dependencies, DepType, Dependency, DependencyCheckResult}; +use crate::{ + depcheck::{check_dependencies, DepType, Dependency, DependencyCheckResult}, + dependencies::common::{dep_cmake, dep_eigen, dep_git, dep_glslang_validator, dep_ninja}, + linux_distro::LinuxDistro, +}; +use std::collections::HashMap; fn monado_deps() -> Vec { vec![ @@ -6,74 +11,66 @@ fn monado_deps() -> Vec { name: "libdrm".into(), dep_type: DepType::SharedObject, filename: "libdrm.so".into(), - }, - Dependency { - name: "libgl".into(), - dep_type: DepType::SharedObject, - filename: "libdrm.so".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "libdrm".into()), + (LinuxDistro::Debian, "libdrm-dev".into()), + (LinuxDistro::Fedora, "libdrm".into()), + ]), }, Dependency { name: "openxr".into(), dep_type: DepType::SharedObject, filename: "libopenxr_loader.so".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "openxr".into()), + (LinuxDistro::Debian, "libopenxr-dev".into()), + (LinuxDistro::Fedora, "openxr-devel".into()), + ]), }, Dependency { name: "vulkan-icd-loader".into(), dep_type: DepType::SharedObject, filename: "libvulkan.so".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "vulkan-icd-loader".into()), + (LinuxDistro::Debian, "libvulkan-dev".into()), + (LinuxDistro::Fedora, "vulkan-loader-devel".into()), + ]), + }, + Dependency { + name: "vulkan-headers".into(), + dep_type: DepType::Include, + filename: "vulkan/vulkan.h".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "vulkan-headers".into()), + (LinuxDistro::Debian, "libvulkan-dev".into()), + (LinuxDistro::Fedora, "vulkan-devel".into()), + ]), }, Dependency { name: "wayland".into(), dep_type: DepType::SharedObject, filename: "libwayland-client.so".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "wayland".into()), + (LinuxDistro::Debian, "libwayland-dev".into()), + ]), }, - Dependency { - name: "cmake".into(), - dep_type: DepType::Executable, - filename: "cmake".into(), - }, - Dependency { - name: "eigen".into(), - dep_type: DepType::Include, - filename: "eigen3/Eigen/src/Core/EigenBase.h".into(), - }, - Dependency { - name: "git".into(), - dep_type: DepType::Executable, - filename: "git".into(), - }, - Dependency { - name: "ninja".into(), - dep_type: DepType::Executable, - filename: "ninja".into(), - }, - Dependency { - name: "shaderc".into(), - dep_type: DepType::Executable, - filename: "glslc".into(), - }, - // duplicate executable, because of different packaging conventions - // in different distros + dep_cmake(), + dep_eigen(), + dep_git(), + dep_ninja(), Dependency { name: "glslc".into(), dep_type: DepType::Executable, filename: "glslc".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "shaderc".into()), + (LinuxDistro::Debian, "glslc".into()), + (LinuxDistro::Fedora, "glslc".into()), + ]), }, - Dependency { - name: "glslang-devel".into(), - dep_type: DepType::Executable, - filename: "glslangValidator".into(), - }, - Dependency { - name: "vulkan-headers".into(), - dep_type: DepType::Include, - filename: "vulkan/vulkan.h".into(), - }, - Dependency { - name: "vulkan-headers".into(), - dep_type: DepType::Include, - filename: "vulkan/vulkan.h".into(), - }, + dep_glslang_validator(), ] } diff --git a/src/dependencies/pkexec_dep.rs b/src/dependencies/pkexec_dep.rs index f227e69..f3110d9 100644 --- a/src/dependencies/pkexec_dep.rs +++ b/src/dependencies/pkexec_dep.rs @@ -1,9 +1,18 @@ -use crate::depcheck::{DepType, Dependency}; +use crate::{ + depcheck::{DepType, Dependency}, + linux_distro::LinuxDistro, +}; +use std::collections::HashMap; pub fn pkexec_dep() -> Dependency { Dependency { name: "pkexec".into(), dep_type: DepType::Executable, filename: "pkexec".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "polkit".into()), + (LinuxDistro::Debian, "pkexec".into()), + (LinuxDistro::Fedora, "polkit".into()), + ]), } } diff --git a/src/dependencies/wivrn_deps.rs b/src/dependencies/wivrn_deps.rs index d161b35..2a10e9c 100644 --- a/src/dependencies/wivrn_deps.rs +++ b/src/dependencies/wivrn_deps.rs @@ -1,4 +1,9 @@ -use crate::depcheck::{check_dependencies, DepType, Dependency, DependencyCheckResult}; +use crate::{ + depcheck::{check_dependencies, DepType, Dependency, DependencyCheckResult}, + dependencies::common::{dep_eigen, dep_glslang_validator}, + linux_distro::LinuxDistro, +}; +use std::collections::HashMap; fn wivrn_deps() -> Vec { // TODO: populate! @@ -7,26 +12,30 @@ fn wivrn_deps() -> Vec { name: "x264-dev".into(), dep_type: DepType::Include, filename: "x264.h".into(), + packages: HashMap::from([ + (LinuxDistro::Arch, "x264".into()), + (LinuxDistro::Debian, "libx264-dev".into()), + (LinuxDistro::Fedora, "x264-devel".into()), + ]), }, Dependency { name: "avahi-client-dev".into(), dep_type: DepType::Include, filename: "avahi-client/client.h".into(), + packages: HashMap::from([]), // TODO }, Dependency { name: "libpulse-dev".into(), dep_type: DepType::Include, filename: "pulse/context.h".into(), + packages: HashMap::from([]), // TODO }, - Dependency { - name: "eigen".into(), - dep_type: DepType::Include, - filename: "eigen3/Eigen/src/Core/EigenBase.h".into(), - }, + dep_eigen(), Dependency { name: "nlohmann-json".into(), dep_type: DepType::Include, filename: "nlohmann/json.hpp".into(), + packages: HashMap::from([]), // TODO }, // Dependency { // name: "libavcodec-dev".into(), @@ -43,35 +52,36 @@ fn wivrn_deps() -> Vec { // dep_type: DepType::Include, // filename: "libswscale/swscale.h".into(), // }, - Dependency { - name: "glslang".into(), - dep_type: DepType::Executable, - filename: "glslangValidator".into(), - }, + dep_glslang_validator(), Dependency { name: "libudev".into(), dep_type: DepType::Include, filename: "libudev.h".into(), + packages: HashMap::from([]), // TODO }, Dependency { name: "gstreamer".into(), dep_type: DepType::SharedObject, filename: "libgstreamer-1.0.so".into(), + packages: HashMap::from([]), // TODO }, Dependency { name: "gst-plugins-base-libs".into(), dep_type: DepType::SharedObject, filename: "pkgconfig/gstreamer-app-1.0.pc".into(), + packages: HashMap::from([]), // TODO }, Dependency { name: "systemd-dev".into(), dep_type: DepType::Include, filename: "systemd/sd-daemon.h".into(), + packages: HashMap::from([]), // TODO }, Dependency { name: "libva-dev".into(), dep_type: DepType::Include, filename: "va/va.h".into(), + packages: HashMap::from([]), // TODO }, ] } diff --git a/src/file_utils.rs b/src/file_utils.rs index 1e83f8f..f79cca5 100644 --- a/src/file_utils.rs +++ b/src/file_utils.rs @@ -25,7 +25,7 @@ pub fn get_writer(path_s: &String) -> BufWriter { BufWriter::new(file) } -pub fn get_reader(path_s: &String) -> Option> { +pub fn get_reader(path_s: &str) -> Option> { let path = Path::new(&path_s); if !(path.is_file() || path.is_symlink()) { return None; diff --git a/src/linux_distro.rs b/src/linux_distro.rs new file mode 100644 index 0000000..8ef709b --- /dev/null +++ b/src/linux_distro.rs @@ -0,0 +1,42 @@ +use std::io::Read; + +use crate::file_utils::get_reader; + +#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] +pub enum LinuxDistro { + Alpine, + Arch, + Debian, + Fedora, +} + +pub fn get_distro() -> Option { + if let Some(mut reader) = get_reader("/etc/issue") { + let mut buf = String::default(); + if reader.read_to_string(&mut buf).is_ok() { + buf = buf.trim().to_lowercase(); + if buf.contains("arch linux") + || buf.contains("manjaro") + || buf.contains("steamos") + || buf.contains("steam os") + { + return Some(LinuxDistro::Arch); + } + if buf.contains("debian") + || buf.contains("ubuntu") + || buf.contains("mint") + || buf.contains("elementary") + { + return Some(LinuxDistro::Debian); + } + if buf.contains("fedora") || buf.contains("nobara") { + return Some(LinuxDistro::Fedora); + } + if buf.contains("alpine") || buf.contains("postmarket") { + return Some(LinuxDistro::Alpine); + } + } + } + + None +} diff --git a/src/main.rs b/src/main.rs index 38852bc..df1f634 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,6 +28,7 @@ pub mod file_builders; pub mod file_utils; pub mod func_runner; pub mod gpu_profile; +pub mod linux_distro; pub mod log_level; pub mod log_parser; pub mod monado_utils; diff --git a/src/ui/app.rs b/src/ui/app.rs index 1345fc8..4edb138 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -33,6 +33,7 @@ use crate::file_builders::openvrpaths_vrpath::{ set_current_openvrpaths_to_profile, set_current_openvrpaths_to_steam, }; use crate::file_utils::setcap_cap_sys_nice_eip; +use crate::linux_distro::get_distro; use crate::log_parser::MonadoLog; use crate::paths::get_ipc_file_path; use crate::profile::{Profile, XRServiceType}; @@ -454,12 +455,22 @@ impl SimpleComponent for App { if !missing_deps.is_empty() { missing_deps.sort_unstable(); missing_deps.dedup(); // dedup only works if sorted, hence the above + let distro = get_distro(); alert( "Missing dependencies:", Some( missing_deps .iter() - .map(|dep| dep.name.clone()) + .map(|dep| { + if let Some(d) = distro { + return dep + .packages + .get(&d) + .unwrap_or_else(|| &dep.name) + .clone(); + } + dep.name.clone() + }) .collect::>() .join(", ") .as_str(),