mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-21 03:16:54 +02:00
Linux: port the emulator to a working state on Linux (#117)
Linux: port the emulator to a working state
This commit is contained in:
@@ -32,6 +32,9 @@ set_target_properties(launcher PROPERTIES AUTOUIC ON AUTOMOC ON AUTORCC ON)
|
||||
|
||||
if(WIN32 AND NOT KYTY_CLANG_CL)
|
||||
set_target_properties(launcher PROPERTIES LINK_FLAGS "${KYTY_LD_OPTIONS}")
|
||||
elseif(LINUX)
|
||||
# Use the same linker as kyty_emulator.
|
||||
set_target_properties(launcher PROPERTIES LINK_FLAGS "${KYTY_LD_OPTIONS}")
|
||||
endif()
|
||||
|
||||
add_dependencies(launcher KytyGitVersion)
|
||||
@@ -79,6 +82,62 @@ if(WIN32)
|
||||
--no-translations
|
||||
)
|
||||
")
|
||||
elseif(LINUX)
|
||||
# Bundle the Qt runtime and plugins.
|
||||
set_target_properties(launcher PROPERTIES
|
||||
INSTALL_RPATH "$ORIGIN/lib"
|
||||
BUILD_WITH_INSTALL_RPATH FALSE
|
||||
LINK_FLAGS "${KYTY_LD_OPTIONS} -Wl,--disable-new-dtags")
|
||||
|
||||
# Support distribution and official Qt layouts.
|
||||
get_target_property(kyty_qt_core_lib Qt6::Core IMPORTED_LOCATION_RELEASE)
|
||||
if(NOT kyty_qt_core_lib)
|
||||
get_target_property(kyty_qt_core_lib Qt6::Core IMPORTED_LOCATION)
|
||||
endif()
|
||||
get_filename_component(kyty_qt_libdir "${kyty_qt_core_lib}" DIRECTORY)
|
||||
|
||||
set(kyty_qt_plugins_dir "")
|
||||
foreach(kyty_candidate
|
||||
"${kyty_qt_libdir}/qt6/plugins"
|
||||
"${kyty_qt_libdir}/../plugins"
|
||||
"${Qt6_DIR}/../../../plugins")
|
||||
if(IS_DIRECTORY "${kyty_candidate}/platforms")
|
||||
get_filename_component(kyty_qt_plugins_dir "${kyty_candidate}" ABSOLUTE)
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if(kyty_qt_plugins_dir)
|
||||
message(STATUS "Qt plugins for launcher deployment: ${kyty_qt_plugins_dir}")
|
||||
set(kyty_qt_plugin_files "")
|
||||
foreach(kyty_qt_plugin platforms tls imageformats xcbglintegrations wayland-shell-integration)
|
||||
if(IS_DIRECTORY "${kyty_qt_plugins_dir}/${kyty_qt_plugin}")
|
||||
file(GLOB kyty_qt_plugin_group
|
||||
"${kyty_qt_plugins_dir}/${kyty_qt_plugin}/*.so"
|
||||
"${kyty_qt_plugins_dir}/${kyty_qt_plugin}/*.so.*")
|
||||
list(APPEND kyty_qt_plugin_files ${kyty_qt_plugin_group})
|
||||
install(DIRECTORY "${kyty_qt_plugins_dir}/${kyty_qt_plugin}" DESTINATION "plugins")
|
||||
endif()
|
||||
endforeach()
|
||||
install(CODE "
|
||||
set(kyty_plugin_files \"${kyty_qt_plugin_files}\")
|
||||
file(GET_RUNTIME_DEPENDENCIES
|
||||
EXECUTABLES \"${CMAKE_CURRENT_BINARY_DIR}/${launcher_name}\"
|
||||
LIBRARIES \${kyty_plugin_files}
|
||||
RESOLVED_DEPENDENCIES_VAR kyty_resolved
|
||||
POST_INCLUDE_REGEXES \"libQt6\" \"libicu\"
|
||||
POST_EXCLUDE_REGEXES \".*\")
|
||||
foreach(kyty_dep \${kyty_resolved})
|
||||
file(INSTALL DESTINATION \"\${CMAKE_INSTALL_PREFIX}/lib\"
|
||||
TYPE SHARED_LIBRARY FOLLOW_SYMLINK_CHAIN FILES \"\${kyty_dep}\")
|
||||
endforeach()
|
||||
")
|
||||
install(CODE "
|
||||
file(WRITE \"\${CMAKE_INSTALL_PREFIX}/qt.conf\" \"[Paths]\\nPlugins = plugins\\n\")
|
||||
")
|
||||
else()
|
||||
message(WARNING "Qt plugin directory not found; the installed launcher will need a system Qt")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
@@ -45,8 +45,6 @@ constexpr char EMULATOR_EXE[] = "kyty_emulator";
|
||||
#if defined(_WIN32)
|
||||
constexpr char CMD_EXE[] = "cmd.exe";
|
||||
#elif defined(__linux__)
|
||||
constexpr char GNOME[] = "gnome-terminal";
|
||||
constexpr char XTERM[] = "xterm";
|
||||
constexpr char KYTY_BASH_FILE[] = "kyty_run.sh";
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
@@ -265,6 +263,57 @@ static bool CreateBashScript(const QString& interpreter, const QStringList& args
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Find a terminal and its command separator.
|
||||
static bool FindTerminal(QString* program, QStringList* prefix) {
|
||||
struct TerminalSpec {
|
||||
const char* executable;
|
||||
const char* separator; // nullptr when the command follows immediately
|
||||
};
|
||||
|
||||
static const TerminalSpec candidates[] = {
|
||||
{"x-terminal-emulator", "-e"}, {"gnome-terminal", "--"}, {"konsole", "-e"},
|
||||
{"xfce4-terminal", "-x"}, {"mate-terminal", "--"}, {"tilix", "-e"},
|
||||
{"alacritty", "-e"}, {"kitty", nullptr}, {"foot", nullptr},
|
||||
{"wezterm", "-e"}, {"urxvt", "-e"}, {"xterm", "-e"},
|
||||
};
|
||||
|
||||
const auto try_candidate = [program, prefix](const QString& executable, const char* separator) {
|
||||
const auto resolved = QStandardPaths::findExecutable(executable);
|
||||
if (resolved.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
*program = resolved;
|
||||
prefix->clear();
|
||||
if (separator != nullptr) {
|
||||
*prefix << QString::fromLatin1(separator);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
if (const auto from_env = qEnvironmentVariable("TERMINAL"); !from_env.isEmpty()) {
|
||||
// Reuse the known separator for an explicit terminal.
|
||||
const auto env_name = QFileInfo(from_env).fileName();
|
||||
const char* separator = "-e";
|
||||
for (const auto& candidate: candidates) {
|
||||
if (env_name == QLatin1String(candidate.executable)) {
|
||||
separator = candidate.separator;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (try_candidate(from_env, separator)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& candidate: candidates) {
|
||||
if (try_candidate(QString::fromLatin1(candidate.executable), candidate.separator)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void MainDialog::RunInterpreter(QProcess* process, const Configuration& info) {
|
||||
@@ -289,8 +338,16 @@ void MainDialog::RunInterpreter(QProcess* process, const Configuration& info) {
|
||||
}
|
||||
|
||||
{
|
||||
process->setProgram(GNOME);
|
||||
process->setArguments({"--", "bash", "-c", bash_file_name});
|
||||
QString terminal;
|
||||
QStringList terminal_prefix;
|
||||
if (FindTerminal(&terminal, &terminal_prefix)) {
|
||||
process->setProgram(terminal);
|
||||
process->setArguments(terminal_prefix + QStringList {"bash", "-c", bash_file_name});
|
||||
} else {
|
||||
// Run without a terminal as a fallback.
|
||||
process->setProgram(QStringLiteral("bash"));
|
||||
process->setArguments({QStringLiteral("-c"), bash_file_name});
|
||||
}
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
{
|
||||
@@ -319,6 +376,15 @@ void MainDialog::RunInterpreter(QProcess* process, const Configuration& info) {
|
||||
});
|
||||
#endif
|
||||
process->start();
|
||||
#if !defined(_WIN32)
|
||||
// Report immediate launch failures.
|
||||
if (!process->waitForStarted(5000)) {
|
||||
QMessageBox::critical(this, tr("Error"),
|
||||
tr("Failed to start:\n%1\n\n%2")
|
||||
.arg(process->program(), process->errorString()));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
process->waitForFinished(100);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user