From 4e9d14816371f8310af6c47eaad9d0a0c76baee0 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Tue, 1 Sep 2026 16:11:02 +0200 Subject: [PATCH 01/10] [TabSupervisor] Initialize all tabs (#7231) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Lukas Brübach --- cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp index c177dce35..ed0ddaf06 100644 --- a/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp +++ b/cockatrice/src/interface/widgets/tabs/tab_supervisor.cpp @@ -116,9 +116,10 @@ void CloseButton::paintEvent(QPaintEvent * /*event*/) } TabSupervisor::TabSupervisor(AbstractClient *_client, QMenu *tabsMenu, QWidget *parent) - : QTabWidget(parent), userInfo(nullptr), client(_client), tabsMenu(tabsMenu), tabVisualDeckStorage(nullptr), - tabServer(nullptr), tabAccount(nullptr), tabDeckStorage(nullptr), tabReplays(nullptr), tabAdmin(nullptr), - tabLog(nullptr), tabReport(nullptr), tabModeration(nullptr), isLocalGame(false) + : QTabWidget(parent), userInfo(nullptr), client(_client), tabsMenu(tabsMenu), tabHome(nullptr), + tabVisualDeckStorage(nullptr), tabServer(nullptr), tabAccount(nullptr), tabDeckStorage(nullptr), + tabReplays(nullptr), tabAdmin(nullptr), tabCardArtRules(nullptr), tabLog(nullptr), tabReport(nullptr), + tabModeration(nullptr), isLocalGame(false) { setElideMode(Qt::ElideRight); setMovable(true); From 35ebae8d7fa09de5157a522f6d6c96fa341f91cb Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Fri, 4 Sep 2026 05:20:52 +0200 Subject: [PATCH 02/10] [Build] Bump cmake_minimum_required from 3.10 to 3.16 (#7232) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 3.16 is already required by Qt6 (and enforced at find_package time). This unlocks native target_precompile_headers(), better AUTOMOC/AUTORCC handling, and qt6_finalize_project() without a version guard. Co-authored-by: Lukas Brübach --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bac46c2bc..3db871e2c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,8 +5,8 @@ # This file sets all the variables shared between the projects # like the installation path, compilation flags etc.. -# cmake 3.16 is required if using qt6 -cmake_minimum_required(VERSION 3.10) +# 3.16 required for Qt6 and target_precompile_headers() +cmake_minimum_required(VERSION 3.16) # Use compiler cache (ccache) option(USE_CCACHE "Cache the build results with ccache" OFF) From fcfb14cf569c1025e942e12133f977ca655af8bb Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Fri, 4 Sep 2026 05:20:53 +0200 Subject: [PATCH 03/10] [Build] Use pipes for GCC/Clang compilation (#7233) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass -pipe so GCC/Clang transfer intermediate representation between compiler stages over pipes instead of temporary files, reducing build I/O. Co-authored-by: Lukas Brübach --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3db871e2c..5ef0f5573 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -184,6 +184,9 @@ elseif(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${FLAG}") endif() endforeach() + + # Reduce compiler I/O by using pipes between stages instead of temp files + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe") else() # other: osx/llvm, bsd/llvm set(CMAKE_CXX_FLAGS_RELEASE "-O2") @@ -192,6 +195,9 @@ else() else() set(CMAKE_CXX_FLAGS_DEBUG "-g -O0 -Wall -Wextra") endif() + + # Reduce compiler I/O by using pipes between stages instead of temp files + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pipe") endif() # GNU systems need to define the Mersenne exponent for the RNG to compile w/o warning From 3ec62df3e7c1dc5eefe5a004926689d85a4fa918 Mon Sep 17 00:00:00 2001 From: BruebachL <44814898+BruebachL@users.noreply.github.com> Date: Fri, 4 Sep 2026 05:20:53 +0200 Subject: [PATCH 04/10] [Protocol] Remove duplicate event_game_state_changed.proto entry (#7234) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The .proto file appeared twice in the PROTO_FILES list, causing protoc to process it twice on every build. Keep a single entry. Co-authored-by: Lukas Brübach --- libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt b/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt index 3a193ae3c..f22828f46 100644 --- a/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt +++ b/libcockatrice_protocol/libcockatrice/protocol/pb/CMakeLists.txt @@ -90,7 +90,6 @@ set(PROTO_FILES event_game_log_notice.proto event_game_say.proto event_game_state_changed.proto - event_game_state_changed.proto event_join.proto event_join_room.proto event_kicked.proto From 21c54a029bc1297275a531e196606fa420fb741b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Tue, 1 Sep 2026 16:15:29 +0200 Subject: [PATCH 05/10] [Build] Add precompiled headers for Qt-backed executables Reparsing QtCore/QtGui/QtWidgets/QtNetwork in ~460 client translation units is the dominant compilation cost. Precompile the two common layers: - qtcore_pch.h (Qt Core only; safe even for headless Servatrice) - qtwidgets_pch.h (adds Gui/Widgets/Network; used by Cockatrice and Oracle) target_precompile_headers() requires CMake 3.16, now the project minimum. Estimated 30-50% faster client rebuilds. --- cmake/pch/qtcore_pch.h | 24 ++++++++++++++++++++++++ cmake/pch/qtwidgets_pch.h | 31 +++++++++++++++++++++++++++++++ cockatrice/CMakeLists.txt | 2 ++ oracle/CMakeLists.txt | 2 ++ servatrice/CMakeLists.txt | 2 ++ 5 files changed, 61 insertions(+) create mode 100644 cmake/pch/qtcore_pch.h create mode 100644 cmake/pch/qtwidgets_pch.h diff --git a/cmake/pch/qtcore_pch.h b/cmake/pch/qtcore_pch.h new file mode 100644 index 000000000..9954bc8b9 --- /dev/null +++ b/cmake/pch/qtcore_pch.h @@ -0,0 +1,24 @@ +/** @file qtcore_pch.h + * @brief Precompiled header for all Qt targets (Qt Core only). + * + * Safe for every target that links Qt Core, including the headless + * Servatrice binary. Keep this header free of any widget/gui types. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include \ No newline at end of file diff --git a/cmake/pch/qtwidgets_pch.h b/cmake/pch/qtwidgets_pch.h new file mode 100644 index 000000000..e39d28de4 --- /dev/null +++ b/cmake/pch/qtwidgets_pch.h @@ -0,0 +1,31 @@ +/** @file qtwidgets_pch.h + * @brief Precompiled header for GUI targets (Cockatrice client, Oracle). + * + * Includes the Qt Core precompiled header plus the heavy Gui, Widgets and + * Network layers that virtually every client translation unit re-parses. + * Do not use on Servatrice (headless, QT_DONT_USE_QTGUI). + */ + +#include "qtcore_pch.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include \ No newline at end of file diff --git a/cockatrice/CMakeLists.txt b/cockatrice/CMakeLists.txt index 2f629fed2..44bfa90e0 100644 --- a/cockatrice/CMakeLists.txt +++ b/cockatrice/CMakeLists.txt @@ -516,6 +516,8 @@ qt6_add_executable( MANUAL_FINALIZATION ) +target_precompile_headers(cockatrice PRIVATE "${CMAKE_SOURCE_DIR}/cmake/pch/qtwidgets_pch.h") + qt6_add_shaders( cockatrice "onboarding_shaders" diff --git a/oracle/CMakeLists.txt b/oracle/CMakeLists.txt index 0736db7f5..ec09f1dee 100644 --- a/oracle/CMakeLists.txt +++ b/oracle/CMakeLists.txt @@ -113,6 +113,8 @@ qt6_add_executable( MANUAL_FINALIZATION ) +target_precompile_headers(oracle PRIVATE "${CMAKE_SOURCE_DIR}/cmake/pch/qtwidgets_pch.h") + # ------------------------ # Link libraries # ------------------------ diff --git a/servatrice/CMakeLists.txt b/servatrice/CMakeLists.txt index aba63800c..5d8089ad1 100644 --- a/servatrice/CMakeLists.txt +++ b/servatrice/CMakeLists.txt @@ -95,6 +95,8 @@ set(DESKTOPDIR # Build servatrice binary and link it add_executable(servatrice MACOSX_BUNDLE ${servatrice_MOC_SRCS} ${servatrice_RESOURCES_RCC} ${servatrice_SOURCES}) +target_precompile_headers(servatrice PRIVATE "${CMAKE_SOURCE_DIR}/cmake/pch/qtcore_pch.h") + if(CMAKE_HOST_SYSTEM MATCHES "FreeBSD") target_link_libraries( servatrice libcockatrice_deck_list libcockatrice_network_server_remote Threads::Threads ${SERVATRICE_QT_MODULES} From fe07d43b91829a1c7e8e7386d3e6a0f90a2bfafc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Tue, 1 Sep 2026 16:47:22 +0200 Subject: [PATCH 06/10] [Build] Format qtwidgets precompiled header clang-format include regrouping and a missing trailing newline. --- cmake/pch/qtwidgets_pch.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cmake/pch/qtwidgets_pch.h b/cmake/pch/qtwidgets_pch.h index e39d28de4..2c63f450e 100644 --- a/cmake/pch/qtwidgets_pch.h +++ b/cmake/pch/qtwidgets_pch.h @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include #include @@ -26,6 +28,3 @@ #include #include #include - -#include -#include \ No newline at end of file From 39962d3b6aaad3d7c63cd10867704485b0307387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Wed, 2 Sep 2026 15:09:53 +0200 Subject: [PATCH 07/10] [Build] Add PCH-aware ccache sloppiness config; format cmake/pch headers --- .ci/compile.sh | 3 +++ CMakeLists.txt | 4 ++++ cmake/pch/qtcore_pch.h | 2 +- format.sh | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.ci/compile.sh b/.ci/compile.sh index 8a16d3243..bd8c900c8 100755 --- a/.ci/compile.sh +++ b/.ci/compile.sh @@ -149,6 +149,9 @@ if [[ $MAKE_TEST ]]; then fi if [[ $USE_CCACHE ]]; then flags+=("-DUSE_CCACHE=1") + # PCH-aware caching is required or ccache refuses to cache any TU that + # consumes a precompiled header, silently recompiling everything on every run. + ccache --set-config sloppiness=pch_defines,time_macros if [[ $CCACHE_SIZE ]]; then # note, this setting persists after running the script ccache --max-size "$CCACHE_SIZE" diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ef0f5573..239329a95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,6 +44,10 @@ if(USE_CCACHE) if(CCACHE_PROGRAM) # Support Unix Makefiles and Ninja set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}") + # PCH-aware caching, matching .ci/compile.sh: without this ccache refuses + # to cache any TU that consumes a precompiled header, so every PCH-backed + # target recompiles from scratch on each build. + execute_process(COMMAND ${CCACHE_PROGRAM} --set-config sloppiness=pch_defines,time_macros) message(STATUS "Found CCache ${CCACHE_PROGRAM}") endif() endif() diff --git a/cmake/pch/qtcore_pch.h b/cmake/pch/qtcore_pch.h index 9954bc8b9..cc3dd12ee 100644 --- a/cmake/pch/qtcore_pch.h +++ b/cmake/pch/qtcore_pch.h @@ -21,4 +21,4 @@ #include #include #include -#include \ No newline at end of file +#include diff --git a/format.sh b/format.sh index 3fa435be1..4a91aee47 100755 --- a/format.sh +++ b/format.sh @@ -18,6 +18,7 @@ include=("cockatrice/src" \ libcockatrice_* \ "oracle/src" \ "servatrice/src" \ +"cmake/pch" \ "tests") exclude=("libcockatrice_rng/libcockatrice/rng/sfmt/" \ "libcockatrice_utility/libcockatrice/utility/peglib.h" \ From 7f8eb50ef2e3944b4c403148d6caa7c662ea50c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Tue, 1 Sep 2026 16:41:01 +0200 Subject: [PATCH 08/10] [Build] Enable ccache by default when it is installed ccache is a near free win for both clean and incremental rebuilds and has no effect on systems where it is not installed (find_program guards the whole block). Aligns the CMake default with the documented behavior; users can still arch with -DUSE_CCACHE=OFF. --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 239329a95..9775872ac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ cmake_minimum_required(VERSION 3.16) # Use compiler cache (ccache) -option(USE_CCACHE "Cache the build results with ccache" OFF) +option(USE_CCACHE "Cache the build results with ccache" ON) # Treat warnings as errors (Debug builds only) option(WARNING_AS_ERROR "Treat warnings as errors in debug builds" ON) # Check for translation updates From 2c78a994afca81bf12c3e89f0217fcbc5c1b961f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Tue, 1 Sep 2026 17:18:55 +0200 Subject: [PATCH 09/10] [Build] Disable ccache auto-engage on Windows (MSVC) --- CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9775872ac..7b80387bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,7 +39,9 @@ else() ) endif() -if(USE_CCACHE) +# ccache does not support MSVC and must not auto-engage on Windows +# (it is installed unintentionally on the Windows CI runner) +if(USE_CCACHE AND NOT WIN32) find_program(CCACHE_PROGRAM ccache) if(CCACHE_PROGRAM) # Support Unix Makefiles and Ninja From bcca82e082fc846531fe26223798827b279ed677 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20Br=C3=BCbach?= Date: Wed, 2 Sep 2026 15:13:00 +0200 Subject: [PATCH 10/10] [Build] Report ccache skip on Windows explicitly --- CMakeLists.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7b80387bb..d50318015 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,7 +40,9 @@ else() endif() # ccache does not support MSVC and must not auto-engage on Windows -# (it is installed unintentionally on the Windows CI runner) +# (it is installed unintentionally on the Windows CI runner). +# NOTE: this keys off the target OS, so a mingw/Ninja configuration on Windows +# also opts out of ccache even though the GNUCXX branch below supports it. if(USE_CCACHE AND NOT WIN32) find_program(CCACHE_PROGRAM ccache) if(CCACHE_PROGRAM) @@ -52,6 +54,9 @@ if(USE_CCACHE AND NOT WIN32) execute_process(COMMAND ${CCACHE_PROGRAM} --set-config sloppiness=pch_defines,time_macros) message(STATUS "Found CCache ${CCACHE_PROGRAM}") endif() +elseif(USE_CCACHE AND WIN32) + # An explicit opt-in must not disappear silently on Windows. + message(STATUS "ccache disabled: not supported for the MSVC toolchain on Windows") endif() if(WIN32 OR USE_VCPKG)