[Build] Add precompiled headers for Qt-backed executables (#7235)

* [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.

* [Build] Format qtwidgets precompiled header

clang-format include regrouping and a missing trailing newline.

* [Build] Add PCH-aware ccache sloppiness config; format cmake/pch headers

---------

Co-authored-by: Lukas Brübach <Bruebach.Lukas@bdosecurity.de>
This commit is contained in:
BruebachL 2026-09-05 19:40:36 +02:00 committed by GitHub
parent 61e6a9913e
commit 14ecfff700
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 68 additions and 0 deletions

View file

@ -149,6 +149,9 @@ if [[ $MAKE_TEST ]]; then
fi fi
if [[ $USE_CCACHE ]]; then if [[ $USE_CCACHE ]]; then
flags+=("-DUSE_CCACHE=1") 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 if [[ $CCACHE_SIZE ]]; then
# note, this setting persists after running the script # note, this setting persists after running the script
ccache --max-size "$CCACHE_SIZE" ccache --max-size "$CCACHE_SIZE"

View file

@ -44,6 +44,10 @@ if(USE_CCACHE)
if(CCACHE_PROGRAM) if(CCACHE_PROGRAM)
# Support Unix Makefiles and Ninja # Support Unix Makefiles and Ninja
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}") 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}") message(STATUS "Found CCache ${CCACHE_PROGRAM}")
endif() endif()
endif() endif()

24
cmake/pch/qtcore_pch.h Normal file
View file

@ -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 <QBasicTimer>
#include <QByteArray>
#include <QDateTime>
#include <QDebug>
#include <QFile>
#include <QHash>
#include <QList>
#include <QLoggingCategory>
#include <QMap>
#include <QMetaObject>
#include <QObject>
#include <QRandomGenerator>
#include <QSharedPointer>
#include <QString>
#include <QStringList>
#include <QTimer>
#include <QVariant>

30
cmake/pch/qtwidgets_pch.h Normal file
View file

@ -0,0 +1,30 @@
/** @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 <QAction>
#include <QApplication>
#include <QFrame>
#include <QGraphicsItem>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QImage>
#include <QLabel>
#include <QLayout>
#include <QMainWindow>
#include <QMenu>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QPainter>
#include <QPushButton>
#include <QScrollArea>
#include <QTabWidget>
#include <QToolBar>
#include <QTreeWidget>
#include <QWidget>

View file

@ -516,6 +516,8 @@ qt6_add_executable(
MANUAL_FINALIZATION MANUAL_FINALIZATION
) )
target_precompile_headers(cockatrice PRIVATE "${CMAKE_SOURCE_DIR}/cmake/pch/qtwidgets_pch.h")
qt6_add_shaders( qt6_add_shaders(
cockatrice cockatrice
"onboarding_shaders" "onboarding_shaders"

View file

@ -18,6 +18,7 @@ include=("cockatrice/src" \
libcockatrice_* \ libcockatrice_* \
"oracle/src" \ "oracle/src" \
"servatrice/src" \ "servatrice/src" \
"cmake/pch" \
"tests") "tests")
exclude=("libcockatrice_rng/libcockatrice/rng/sfmt/" \ exclude=("libcockatrice_rng/libcockatrice/rng/sfmt/" \
"libcockatrice_utility/libcockatrice/utility/peglib.h" \ "libcockatrice_utility/libcockatrice/utility/peglib.h" \

View file

@ -112,6 +112,8 @@ qt6_add_executable(
MANUAL_FINALIZATION MANUAL_FINALIZATION
) )
target_precompile_headers(oracle PRIVATE "${CMAKE_SOURCE_DIR}/cmake/pch/qtwidgets_pch.h")
# ------------------------ # ------------------------
# Link libraries # Link libraries
# ------------------------ # ------------------------

View file

@ -95,6 +95,8 @@ set(DESKTOPDIR
# Build servatrice binary and link it # Build servatrice binary and link it
add_executable(servatrice MACOSX_BUNDLE ${servatrice_MOC_SRCS} ${servatrice_RESOURCES_RCC} ${servatrice_SOURCES}) 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") if(CMAKE_HOST_SYSTEM MATCHES "FreeBSD")
target_link_libraries( target_link_libraries(
servatrice libcockatrice_deck_list libcockatrice_network_server_remote Threads::Threads ${SERVATRICE_QT_MODULES} servatrice libcockatrice_deck_list libcockatrice_network_server_remote Threads::Threads ${SERVATRICE_QT_MODULES}