From b2efe84a5482d7080ffc3a1e356b61acd6db9778 Mon Sep 17 00:00:00 2001 From: Marie Ramlow Date: Wed, 23 Apr 2025 17:01:58 +0200 Subject: [PATCH 1/6] build project with meson --- globals.cpp | 4 +-- globals.h | 3 --- main.cpp | 16 ++++++------ meson.build | 56 ++++++++++++++++++++++++++++++++++++++++ tools/curl.cpp | 6 +---- tools/curl.h | 6 +---- tools/install.cpp | 24 ++++++++--------- tools/install.h | 2 +- tools/js.cpp | 9 +------ tools/netcon.cpp | 10 +++---- tools/package.cpp | 4 +-- tools/qt.cpp | 4 +-- tools/update.cpp | 8 +++--- ui/mainwindow_extend.cpp | 6 ++--- 14 files changed, 98 insertions(+), 60 deletions(-) create mode 100644 meson.build diff --git a/globals.cpp b/globals.cpp index 389f67c..abfeb48 100644 --- a/globals.cpp +++ b/globals.cpp @@ -6,7 +6,7 @@ #include "tools/package.h" // ToolsPackage // Points to the system-specific designated cache directory -#ifndef TARGET_WINDOWS +#ifndef WIN32 std::filesystem::path CACHE_DIR = (std::filesystem::path(std::getenv("HOME")) / ".cache") / "spplice-cpp"; #else std::filesystem::path CACHE_DIR = std::filesystem::temp_directory_path() / "spplice-cpp"; @@ -14,7 +14,7 @@ std::filesystem::path CACHE_DIR = std::filesystem::temp_directory_path() / "sppl bool CACHE_ENABLE = true; // Points to the system-specific designated application directory -#ifndef TARGET_WINDOWS +#ifndef WIN32 const std::filesystem::path APP_DIR = (std::filesystem::path(std::getenv("HOME")) / ".config") / "spplice-cpp"; #else const std::filesystem::path APP_DIR = std::filesystem::path(std::getenv("APPDATA")) / "spplice-cpp"; diff --git a/globals.h b/globals.h index 9b5191b..8763307 100644 --- a/globals.h +++ b/globals.h @@ -7,9 +7,6 @@ #include "tools/package.h" // ToolsPackage -// Comment this line to target Linux, uncomment to target Windows -#define TARGET_WINDOWS - extern std::filesystem::path CACHE_DIR; extern bool CACHE_ENABLE; extern const std::filesystem::path APP_DIR; diff --git a/main.cpp b/main.cpp index 8637d7a..4ae2dac 100644 --- a/main.cpp +++ b/main.cpp @@ -13,7 +13,7 @@ #include #include // Platform specific includes -#ifdef TARGET_WINDOWS +#ifdef WIN32 #include #endif // Main window dependencies @@ -26,8 +26,8 @@ #include #include #include "ui/mainwindow_extend.h" -#include "ui/repositories.h" -#include "ui/settings.h" +#include "ui_Repositories.h" +#include "ui_Settings.h" // Project globals #include "globals.h" @@ -144,7 +144,7 @@ void signalHandler (int signal) { crashHandler("Unknown Signal", signal); } -#ifdef TARGET_WINDOWS +#ifdef WIN32 // Handles low-level exceptions on Windows LONG WINAPI windowsExceptionHandler (EXCEPTION_POINTERS* info) { crashHandler("Windows Exception", (uint)(info->ExceptionRecord->ExceptionCode)); @@ -296,7 +296,7 @@ int main (int argc, char *argv[]) { QLineEdit *cacheInput = dialogUI.CacheDirInput; // Write the cache directory to the input field -#ifndef TARGET_WINDOWS +#ifndef WIN32 cacheInput->setText(QString::fromStdString(CACHE_DIR.string())); #else cacheInput->setText(QString::fromStdWString(CACHE_DIR.wstring())); @@ -305,7 +305,7 @@ int main (int argc, char *argv[]) { // Connect the cache directory "Apply" button QObject::connect(dialogUI.CacheDirBtn, &QPushButton::clicked, [cacheInput]() { -#ifndef TARGET_WINDOWS +#ifndef WIN32 const std::filesystem::path newPath(cacheInput->text().toStdString()); #else const std::filesystem::path newPath(cacheInput->text().toStdWString()); @@ -418,7 +418,7 @@ int main (int argc, char *argv[]) { }); -#ifndef TARGET_WINDOWS +#ifndef WIN32 // Dynamically set the window icon on Linux app.setWindowIcon(QIcon(":/resources/icon.ico")); #endif @@ -483,7 +483,7 @@ int main (int argc, char *argv[]) { std::signal(SIGABRT, signalHandler); std::signal(SIGINT, signalHandler); -#ifdef TARGET_WINDOWS +#ifdef WIN32 // Register Windows low-level exception handler SetUnhandledExceptionFilter(windowsExceptionHandler); #endif diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..2781dbb --- /dev/null +++ b/meson.build @@ -0,0 +1,56 @@ +project('spplice', 'cpp') + +qt = import('qt5') + +qt_dep = dependency('qt5', modules: ['Widgets', 'Concurrent']) + +duktape = dependency('duktape') +curl = dependency('libcurl') +libarchive = dependency('libarchive') + +ui = qt.compile_ui(sources : files([ + 'ui/MainWindow.ui', + 'ui/PackageItem.ui', + 'ui/ErrorDialog.ui', + 'ui/PackageInfo.ui', + 'ui/Repositories.ui', + 'ui/Settings.ui', +])) + +moc_files = qt.compile_moc(headers : files([ + 'ui/mainwindow_extend.h', + 'tools/package.h', +])) + +resources = qt.compile_resources( + sources: [ + 'resources.qrc' + ] +) + +executable( + 'SppliceCPP', + sources : [ + moc_files, + ui, + 'ui/mainwindow_extend.cpp', + 'main.cpp', + 'globals.cpp', + 'tools/curl.cpp', + 'tools/update.cpp', + 'tools/qt.cpp', + 'tools/install.cpp', + 'tools/package.cpp', + 'tools/repo.cpp', + 'tools/js.cpp', + 'tools/netcon.cpp', + 'tools/merge.cpp', + resources, + ], + dependencies: [ + qt_dep, + duktape, + curl, + libarchive, + ] +) diff --git a/tools/curl.cpp b/tools/curl.cpp index 30b295b..85c6121 100644 --- a/tools/curl.cpp +++ b/tools/curl.cpp @@ -8,11 +8,7 @@ // Definitions for this source file #include "curl.h" -#ifndef TARGET_WINDOWS - #include "../deps/linux/include/curl/curl.h" -#else - #include "../deps/win32/include/curl/curl.h" -#endif +#include "curl/curl.h" // Initializes CURL globally void ToolsCURL::init () { diff --git a/tools/curl.h b/tools/curl.h index b0c28a3..fcfc2eb 100644 --- a/tools/curl.h +++ b/tools/curl.h @@ -3,11 +3,7 @@ #include -#ifndef TARGET_WINDOWS - #include "../deps/linux/include/curl/curl.h" -#else - #include "../deps/win32/include/curl/curl.h" -#endif +#include "curl/curl.h" class ToolsCURL { public: diff --git a/tools/install.cpp b/tools/install.cpp index 9d6aad7..b60da69 100644 --- a/tools/install.cpp +++ b/tools/install.cpp @@ -19,7 +19,7 @@ #include "js.h" // ToolsJS #include "merge.h" // ToolsMerge -#ifdef TARGET_WINDOWS +#ifdef WIN32 #include "../deps/win32/include/archive.h" #include "../deps/win32/include/archive_entry.h" @@ -100,7 +100,7 @@ bool ToolsInstall::extractLocalFile (const std::filesystem::path path, const std } // Retrieves the path to a process executable using its name -#ifndef TARGET_WINDOWS +#ifndef WIN32 std::string ToolsInstall::getProcessPath (const std::string &processName) { DIR *dir = opendir("/proc"); @@ -182,7 +182,7 @@ std::wstring ToolsInstall::getProcessPath (const std::string &processName) { #endif // Returns true if the Portal 2 process is running -#ifndef TARGET_WINDOWS +#ifndef WIN32 bool ToolsInstall::isGameRunning () { return ToolsInstall::getProcessPath("portal2_linux") != "" || ToolsInstall::getProcessPath("portal2.exe") != ""; } @@ -193,7 +193,7 @@ bool ToolsInstall::isGameRunning () { #endif // Finds the Steam binary and uses it to start Portal 2 -#ifndef TARGET_WINDOWS +#ifndef WIN32 bool startPortal2 (const std::vector extraArgs) { std::string steamPath = ToolsInstall::getProcessPath("steam"); @@ -315,7 +315,7 @@ bool startPortal2 (const std::vector extraArgs) { #endif // Creates a symbolic link for a directory on Linux, and an NTFS junction on Windows -#ifndef TARGET_WINDOWS +#ifndef WIN32 bool linkDirectory (const std::filesystem::path target, const std::filesystem::path linkName) { if (symlink(target.c_str(), linkName.c_str()) != 0) { @@ -409,7 +409,7 @@ bool linkDirectory (const std::filesystem::path target, const std::filesystem::p #endif // Creates a symbolic link for a file on Linux and a hard link on Windows -#ifndef TARGET_WINDOWS +#ifndef WIN32 bool linkFile (const std::filesystem::path target, const std::filesystem::path linkName) { if (symlink(target.c_str(), linkName.c_str()) != 0) { @@ -439,7 +439,7 @@ bool linkFile (const std::filesystem::path target, const std::filesystem::path l #endif // Removes a symbolic link to a directory on Linux, or an NTFS junction on Windows -#ifndef TARGET_WINDOWS +#ifndef WIN32 bool unlinkDirectory (const std::filesystem::path target) { if (unlink(target.c_str()) != 0) { @@ -471,7 +471,7 @@ bool unlinkDirectory (const std::filesystem::path target) { } #endif -#ifndef TARGET_WINDOWS +#ifndef WIN32 bool isDirectoryLink (const std::filesystem::path linkName) { struct stat path_stat; @@ -566,7 +566,7 @@ std::string installPackageDirectory (const std::filesystem::path packageDirector } // Find the Portal 2 game files path -#ifndef TARGET_WINDOWS +#ifndef WIN32 std::string gameProcessPath = ""; while (gameProcessPath.length() == 0) { gameProcessPath = ToolsInstall::getProcessPath("portal2_linux"); @@ -738,7 +738,7 @@ std::string ToolsInstall::installMergedPackage (std::vector #include #include -#include "../deps/shared/duktape/duktape.h" +#include "duktape.h" #include "../globals.h" // Project globals -#ifndef TARGET_WINDOWS - #include "../deps/linux/include/curl/curl.h" -#else - #include "../deps/win32/include/curl/curl.h" - #include -#endif - #include "netcon.h" // ToolsNetCon #include "curl.h" // ToolsCURL #include "install.h" // ToolsInstall diff --git a/tools/netcon.cpp b/tools/netcon.cpp index 6f33c4e..dbe9ecd 100644 --- a/tools/netcon.cpp +++ b/tools/netcon.cpp @@ -4,7 +4,7 @@ #include "../globals.h" // Project globals -#ifndef TARGET_WINDOWS +#ifndef WIN32 #include #include #include @@ -16,14 +16,14 @@ // Definitions for this source file #include "netcon.h" -#ifdef TARGET_WINDOWS +#ifdef WIN32 // Counts the amount of open netcon sockets for Winsock setup and cleanup int openSockets = 0; #endif // Closes the given socket void ToolsNetCon::disconnect (int sockfd) -#ifndef TARGET_WINDOWS +#ifndef WIN32 { close(sockfd); } @@ -38,7 +38,7 @@ void ToolsNetCon::disconnect (int sockfd) // Attempts to connect to the game's TCP console on SPPLICE_NETCON_PORT int ToolsNetCon::attemptConnection () { -#ifdef TARGET_WINDOWS +#ifdef WIN32 // If this is the first socket we've made, set up Winsock if (++openSockets == 1) { WSADATA wsaData; @@ -88,7 +88,7 @@ bool ToolsNetCon::sendCommand (int sockfd, std::string command) { } // Close our eyes and pretend Windows poll is the same as Linux -#ifdef TARGET_WINDOWS +#ifdef WIN32 #define pollfd(a) WSAPOLLFD(a) #define poll(a, b, c) WSAPoll(a, b, c) #else diff --git a/tools/package.cpp b/tools/package.cpp index 6ab4bb6..4167412 100644 --- a/tools/package.cpp +++ b/tools/package.cpp @@ -15,8 +15,8 @@ #include #include -#include "../ui/packageitem.h" -#include "../ui/packageinfo.h" +#include "ui_PackageItem.h" +#include "ui_PackageInfo.h" #include "../globals.h" #include "curl.h" // ToolsCURL diff --git a/tools/qt.cpp b/tools/qt.cpp index f3b19a0..a6b30cf 100644 --- a/tools/qt.cpp +++ b/tools/qt.cpp @@ -8,7 +8,7 @@ #include #include #include -#include "../ui/errordialog.h" +#include "ui_ErrorDialog.h" #include "curl.h" // ToolsCURL #include "qt.h" // ToolsQT #include "install.h" // ToolsInstall @@ -20,7 +20,7 @@ // Given a path to an image and a QSize, returns a pixmap of that image QPixmap ToolsQT::getPixmapFromPath (const std::filesystem::path &path, const QSize size) { -#ifndef TARGET_WINDOWS +#ifndef WIN32 return QPixmap(QString::fromStdString(path.string())).scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); #else return QPixmap(QString::fromStdWString(path.wstring())).scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); diff --git a/tools/update.cpp b/tools/update.cpp index 222e7ab..c606275 100644 --- a/tools/update.cpp +++ b/tools/update.cpp @@ -4,7 +4,7 @@ #include #include -#ifdef TARGET_WINDOWS +#ifdef WIN32 #include #else #include @@ -17,7 +17,7 @@ // Definitions for this source file #include "update.h" -#ifndef TARGET_WINDOWS +#ifndef WIN32 const std::string updateBinary = "SppliceCPP"; #else const std::string updateBinary = "_autoupdate"; @@ -25,7 +25,7 @@ std::filesystem::path getExecutablePath () { -#ifdef TARGET_WINDOWS +#ifdef WIN32 wchar_t buffer[MAX_PATH]; DWORD size = GetModuleFileNameW(NULL, buffer, MAX_PATH); if (size == 0 || size == MAX_PATH) return std::filesystem::path(); @@ -102,7 +102,7 @@ void ToolsUpdate::installUpdate () { LOGFILE << "[I] Found own executable at " << executablePath << std::endl; // Swap the running executable with the one we just downloaded -#ifdef TARGET_WINDOWS +#ifdef WIN32 // If on Windows, defer replacing until next reboot to avoid conflicts if (MoveFileExW(updatePath.c_str(), executablePath.c_str(), MOVEFILE_DELAY_UNTIL_REBOOT)) { LOGFILE << "[I] Scheduled update file replacement for next reboot" << std::endl; diff --git a/ui/mainwindow_extend.cpp b/ui/mainwindow_extend.cpp index 1bd5c63..b7a8d92 100644 --- a/ui/mainwindow_extend.cpp +++ b/ui/mainwindow_extend.cpp @@ -1,7 +1,7 @@ // Headers for this source file #include "mainwindow_extend.h" // The UI class we're extending -#include "mainwindow.h" +#include "ui_MainWindow.h" #include #include @@ -98,7 +98,7 @@ void MainWindow::dropEvent (QDropEvent *event) { foreach (const QUrl &url, mimeData->urls()) { // Retrieve file path -#ifndef TARGET_WINDOWS +#ifndef WIN32 std::filesystem::path filePath = url.toLocalFile().toStdString(); #else std::filesystem::path filePath = url.toLocalFile().toStdWString(); @@ -188,7 +188,7 @@ void MainWindow::dropEvent (QDropEvent *event) { // Determine output path for the package icon file const std::string iconFileName = timess.str() + "_icon"; const std::filesystem::path iconDestinationPath = archivePath / iconFileName; -#ifndef TARGET_WINDOWS +#ifndef WIN32 const QString iconDestinationQString = QString::fromStdString(iconDestinationPath.string()); #else const QString iconDestinationQString = QString::fromStdWString(iconDestinationPath.wstring()); From 47d8443b111ee793f64046bf8d7ed1799a35461f Mon Sep 17 00:00:00 2001 From: Marie Ramlow Date: Wed, 23 Apr 2025 17:01:58 +0200 Subject: [PATCH 2/6] .gitignore: add .cache for clangd --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e127519..9ce5fed 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ qt5build deps dist setup/Output +.cache From 6f3fd84f95c1847b52c2e7dde00c33b46baa1f56 Mon Sep 17 00:00:00 2001 From: Marie Ramlow Date: Wed, 23 Apr 2025 17:01:58 +0200 Subject: [PATCH 3/6] meson: install executable by default --- meson.build | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/meson.build b/meson.build index 2781dbb..1ff6a59 100644 --- a/meson.build +++ b/meson.build @@ -52,5 +52,6 @@ executable( duktape, curl, libarchive, - ] + ], + install: true ) From b29875fca5f5f112b87f1e981f5c47065e2681fe Mon Sep 17 00:00:00 2001 From: Marie Ramlow Date: Wed, 23 Apr 2025 17:01:58 +0200 Subject: [PATCH 4/6] add nix package --- .gitignore | 1 + flake.lock | 27 +++++++++++++++++++++++++++ flake.nix | 18 ++++++++++++++++++ nix/package.nix | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+) create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 nix/package.nix diff --git a/.gitignore b/.gitignore index 9ce5fed..76bf832 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ deps dist setup/Output .cache +/result diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..9cbe77a --- /dev/null +++ b/flake.lock @@ -0,0 +1,27 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1745279238, + "narHash": "sha256-AQ7M9wTa/Pa/kK5pcGTgX/DGqMHyzsyINfN7ktsI7Fo=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "9684b53175fc6c09581e94cc85f05ab77464c7e3", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-24.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..8266ae8 --- /dev/null +++ b/flake.nix @@ -0,0 +1,18 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-24.11"; + }; + + outputs = { self, nixpkgs }: + let + forEachSystem = f: nixpkgs.lib.genAttrs [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ] + (system: f nixpkgs.legacyPackages.${system}); + in { + overlays = (final: prev: { + ssplice-cpp = prev.callPackage ./nix/package.nix { }; + }); + packages = forEachSystem (pkgs: { + ssplice-cpp = pkgs.callPackage ./nix/package.nix { }; + }); + }; +} diff --git a/nix/package.nix b/nix/package.nix new file mode 100644 index 0000000..7a1e7e4 --- /dev/null +++ b/nix/package.nix @@ -0,0 +1,32 @@ +{ + lib, + stdenv, + meson, + libsForQt5, + duktape, + curl, + libarchive, + pkg-config, + ninja, +}: + +stdenv.mkDerivation { + pname = "splice-cpp"; + version = "0.9.5"; + + src = lib.cleanSource ../.; + + nativeBuildInputs = [ + meson + libsForQt5.wrapQtAppsHook + pkg-config + ninja + ]; + + buildInputs = [ + libsForQt5.qtbase + duktape + curl + libarchive + ]; +} From e83de3a25c889a5b3791cbf4aa7fc6db284307d0 Mon Sep 17 00:00:00 2001 From: Marie Ramlow Date: Wed, 23 Apr 2025 17:01:58 +0200 Subject: [PATCH 5/6] add option to build with Qt 6 --- meson.build | 10 +++++++--- meson.options | 1 + meson_options.txt | 1 + nix/package.nix | 10 +++++++--- 4 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 meson.options create mode 120000 meson_options.txt diff --git a/meson.build b/meson.build index 1ff6a59..db3b5d2 100644 --- a/meson.build +++ b/meson.build @@ -1,8 +1,12 @@ project('spplice', 'cpp') -qt = import('qt5') - -qt_dep = dependency('qt5', modules: ['Widgets', 'Concurrent']) +if get_option('USE_QT6') + qt = import('qt6') + qt_dep = dependency('qt6', modules: ['Core', 'Widgets', 'Gui', 'Concurrent']) +else + qt = import('qt5') + qt_dep = dependency('qt5', modules: ['Widgets', 'Concurrent']) +endif duktape = dependency('duktape') curl = dependency('libcurl') diff --git a/meson.options b/meson.options new file mode 100644 index 0000000..f3d4c1d --- /dev/null +++ b/meson.options @@ -0,0 +1 @@ +option('USE_QT6', type : 'boolean', value : false, description : 'Build with QT6') diff --git a/meson_options.txt b/meson_options.txt new file mode 120000 index 0000000..7b28df2 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1 @@ +meson.options \ No newline at end of file diff --git a/nix/package.nix b/nix/package.nix index 7a1e7e4..81e3ef4 100644 --- a/nix/package.nix +++ b/nix/package.nix @@ -2,7 +2,7 @@ lib, stdenv, meson, - libsForQt5, + kdePackages, duktape, curl, libarchive, @@ -18,15 +18,19 @@ stdenv.mkDerivation { nativeBuildInputs = [ meson - libsForQt5.wrapQtAppsHook + kdePackages.wrapQtAppsHook pkg-config ninja ]; buildInputs = [ - libsForQt5.qtbase + kdePackages.qtbase duktape curl libarchive ]; + + mesonFlags = [ + (lib.mesonBool "USE_QT6" true) + ]; } From c7a7e391408beb69a4b6ea486fb752d764ff3013 Mon Sep 17 00:00:00 2001 From: Marie Ramlow Date: Wed, 23 Apr 2025 17:01:58 +0200 Subject: [PATCH 6/6] flake: add devShell --- flake.nix | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/flake.nix b/flake.nix index 8266ae8..c93cb04 100644 --- a/flake.nix +++ b/flake.nix @@ -14,5 +14,21 @@ packages = forEachSystem (pkgs: { ssplice-cpp = pkgs.callPackage ./nix/package.nix { }; }); + devShells = forEachSystem (pkgs: { + default = pkgs.mkShell { + nativeBuildInputs = with pkgs; [ + meson + pkg-config + ninja + ]; + buildInputs = with pkgs; [ + kdePackages.qtbase + duktape + curl + libarchive + kdePackages.qtwayland + ]; + }; + }); }; }