aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-15 12:22:51 -0600
committerSulfurNitride <SulfurNitride@users.noreply.github.com>2026-02-15 12:22:51 -0600
commitbd25ca97297d766bc24fb09e0f95d1bf7d2baf73 (patch)
tree85054cfa12c07026c5945ceee5d804fddb6ab35f
parent6410929e17d642618f284d5c97d457f1ac653e6e (diff)
Fix RPATH, absolute instance paths, Proton symlink matching, umu-run logging, pybind11 warning
- Set $ORIGIN-relative RPATH on binaries so they find libs without LD_LIBRARY_PATH (fixes #12) - Check QDir::isAbsolutePath before concatenating instance paths to prevent doubling of custom portable paths - Canonicalize paths when matching Proton installations to handle symlinks in /usr/share/steam/compatibilitytools.d/ (fixes #8) - Add diagnostic logging for umu-run resolution showing preference, bundled/system paths, and final selection (helps diagnose #8) - Warn at CMake time if pybind11 >= 2.14 is detected (documents #9) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
-rwxr-xr-xdocker/build-inner.sh6
-rw-r--r--libs/nak_ffi/src/lib.rs42
-rw-r--r--libs/plugin_python/CMakeLists.txt3
-rw-r--r--src/src/instancemanager.cpp3
-rw-r--r--src/src/protonlauncher.cpp3
5 files changed, 37 insertions, 20 deletions
diff --git a/docker/build-inner.sh b/docker/build-inner.sh
index 962898b..7c83796 100755
--- a/docker/build-inner.sh
+++ b/docker/build-inner.sh
@@ -210,6 +210,12 @@ for tool in wrestool icotool lootcli; do
[ -f "${OUT_DIR}/${tool}" ] && strip --strip-unneeded "${OUT_DIR}/${tool}" 2>/dev/null || true
done
+# ── Fix RPATH so binaries find libs without LD_LIBRARY_PATH ──
+echo "Patching RPATH..."
+patchelf --set-rpath '$ORIGIN/lib' "${OUT_DIR}/ModOrganizer-core"
+[ -f "${OUT_DIR}/lootcli" ] && patchelf --set-rpath '$ORIGIN/lib' "${OUT_DIR}/lootcli"
+find "${OUT_DIR}/plugins" -name "*.so" -exec patchelf --set-rpath '$ORIGIN/../lib' {} \; 2>/dev/null || true
+
# ── Validate embedded Python runtime ──
cat > /tmp/mo2_embed_py_check.c <<'C'
#include <Python.h>
diff --git a/libs/nak_ffi/src/lib.rs b/libs/nak_ffi/src/lib.rs
index dbd4cdb..fe18cf3 100644
--- a/libs/nak_ffi/src/lib.rs
+++ b/libs/nak_ffi/src/lib.rs
@@ -7,7 +7,7 @@
//! - `NakKnownGame` pointers are static data and must NOT be freed
use std::ffi::{c_char, c_float, c_int, CStr, CString};
-use std::path::Path;
+use std::path::{Path, PathBuf};
use std::ptr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, LazyLock, Mutex};
@@ -39,6 +39,20 @@ fn error_to_cstring(e: Box<dyn std::error::Error>) -> *mut c_char {
to_cstring(&e.to_string())
}
+/// Find a Proton installation by path, using canonicalization to handle
+/// symlinks and path normalization (e.g. system Protons in
+/// /usr/share/steam/compatibilitytools.d/).
+fn find_proton_by_path(proton_path_str: &str) -> Option<nak_rust::steam::SteamProton> {
+ let target = std::fs::canonicalize(proton_path_str)
+ .unwrap_or_else(|_| PathBuf::from(proton_path_str));
+ nak_rust::steam::find_steam_protons()
+ .into_iter()
+ .find(|p| {
+ std::fs::canonicalize(&p.path)
+ .unwrap_or_else(|_| p.path.clone()) == target
+ })
+}
+
// ============================================================================
// Tier 1: Game Detection
// ============================================================================
@@ -365,13 +379,9 @@ pub unsafe extern "C" fn nak_install_all_dependencies(
let _proton_name = unsafe { from_cstr(proton_name) };
let proton_path_str = unsafe { from_cstr(proton_path) };
- // Find the matching SteamProton by path
- let protons = nak_rust::steam::find_steam_protons();
- let proton = match protons
- .iter()
- .find(|p| p.path.to_string_lossy() == proton_path_str)
- {
- Some(p) => p.clone(),
+ // Find the matching SteamProton by path (canonicalized for symlink support)
+ let proton = match find_proton_by_path(proton_path_str) {
+ Some(p) => p,
None => {
return to_cstring(&format!(
"Proton not found at path: {}",
@@ -454,12 +464,8 @@ pub unsafe extern "C" fn nak_apply_wine_registry_settings(
let _proton_name = unsafe { from_cstr(proton_name) };
let proton_path_str = unsafe { from_cstr(proton_path) };
- let protons = nak_rust::steam::find_steam_protons();
- let proton = match protons
- .iter()
- .find(|p| p.path.to_string_lossy() == proton_path_str)
- {
- Some(p) => p.clone(),
+ let proton = match find_proton_by_path(proton_path_str) {
+ Some(p) => p,
None => {
return to_cstring(&format!(
"Proton not found at path: {}",
@@ -507,12 +513,8 @@ pub unsafe extern "C" fn nak_apply_registry_for_game_path(
let game = unsafe { from_cstr(game_name) };
let install = unsafe { from_cstr(install_path) };
- let protons = nak_rust::steam::find_steam_protons();
- let proton = match protons
- .iter()
- .find(|p| p.path.to_string_lossy() == proton_path_str)
- {
- Some(p) => p.clone(),
+ let proton = match find_proton_by_path(proton_path_str) {
+ Some(p) => p,
None => {
return to_cstring(&format!(
"Proton not found at path: {}",
diff --git a/libs/plugin_python/CMakeLists.txt b/libs/plugin_python/CMakeLists.txt
index 411a82e..6d33f5b 100644
--- a/libs/plugin_python/CMakeLists.txt
+++ b/libs/plugin_python/CMakeLists.txt
@@ -7,6 +7,9 @@ set(MO2_QT_VERSION_MAJOR 6)
find_package(Python COMPONENTS Interpreter Development REQUIRED)
find_package(pybind11 CONFIG REQUIRED)
+if(pybind11_VERSION VERSION_GREATER_EQUAL "2.14")
+ message(WARNING "pybind11 ${pybind11_VERSION} detected. Versions >= 2.14 may cause build errors with MO2's Python plugin. Use 2.13.x or build with the container (./build-native.sh).")
+endif()
get_filename_component(Python_HOME ${Python_EXECUTABLE} PATH)
set(Python_DLL_DIR "${Python_HOME}")
diff --git a/src/src/instancemanager.cpp b/src/src/instancemanager.cpp
index 3aa4db5..6620e3c 100644
--- a/src/src/instancemanager.cpp
+++ b/src/src/instancemanager.cpp
@@ -621,6 +621,9 @@ void InstanceManager::setCurrentInstance(const QString& name)
QString InstanceManager::instancePath(const QString& instanceName) const
{
+ if (QDir::isAbsolutePath(instanceName)) {
+ return QDir::fromNativeSeparators(instanceName);
+ }
return QDir::fromNativeSeparators(globalInstancesRootPath() + "/" + instanceName);
}
diff --git a/src/src/protonlauncher.cpp b/src/src/protonlauncher.cpp
index 233732f..6a1aecd 100644
--- a/src/src/protonlauncher.cpp
+++ b/src/src/protonlauncher.cpp
@@ -397,6 +397,9 @@ bool ProtonLauncher::launchWithUmu(qint64& pid) const
umuRun = system;
}
}
+
+ MOBase::log::info("umu-run: preferSystem={}, bundled='{}' (exists={}), system='{}', selected='{}'",
+ m_preferSystemUmu, bundled, QFileInfo::exists(bundled), system, umuRun);
}
if (umuRun.isEmpty()) {