From bf20980dd1867915e051abc37d47ad14cc93110f Mon Sep 17 00:00:00 2001 From: Magnus Gille Date: Wed, 10 Dec 2025 10:38:29 -0800 Subject: [PATCH] Improve the build speed by 2-3X by using PCH (#4746) * Improve the build speed by 2-3X by using PCH. This avoids rebuilding large parts of QT and C++ std headers over and over. * Unfortunately QMake is too opinionated for this to work on macOS so it is used on Windows and Linux only. * Remove qwindowsvistastyle.dll opengl32sw.dll from QT6 as they're not needed. * Revert fa84a37 since we don't need it anymore. --- .gitignore | 13 +++++ appveyor.yml | 4 +- qwt/src/src.pro | 3 + src/Charts/GoldenCheetah.h | 7 ++- src/Core/TimeUtils.h | 7 ++- src/FileIO/RideFileCommand.h | 4 +- src/Resources/win32/GC3.7-Master-W64-QT6.nsi | 4 -- src/src.pro | 30 ++++++++++ src/stable.h | 61 ++++++++++++++++++++ 9 files changed, 119 insertions(+), 14 deletions(-) create mode 100644 src/stable.h diff --git a/.gitignore b/.gitignore index 9039732d7..24e748ee4 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,16 @@ doc/contrib/WASP Packet Protocol.pdf # Qt testlib target_wrapper.sh + +# Precompiled Headers +*.gch +*.pch +*.gch/ +_pch/ + +# Generated Source Files +*_lex.cpp +*_yacc.cpp +*_yacc.h +qrc_*.cpp + diff --git a/appveyor.yml b/appveyor.yml index 4ea44acf1..0a0e11a6b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -221,12 +221,12 @@ build_script: # Windows - cmd: qmake.exe build.pro -r -spec win32-msvc -- cmd: if not exist qwt\lib\qwt.lib jom -j1 sub-qwt & exit /b 1 +- cmd: if not exist qwt\lib\qwt.lib jom -j1 sub-qwt - cmd: jom -j2 sub-src # Linux / macOS - sh: qmake build.pro -r QMAKE_CXXFLAGS_WARN_ON+="-Wno-unused-private-field -Wno-c++11-narrowing -Wno-deprecated-declarations -Wno-deprecated-register -Wno-nullability-completeness -Wno-sign-compare -Wno-inconsistent-missing-override" QMAKE_CFLAGS_WARN_ON+="-Wno-deprecated-declarations -Wno-sign-compare" -- sh: if test ! -f qwt/lib/libqwt.a; then make sub-qwt; false; fi +- sh: if test ! -f qwt/lib/libqwt.a; then make sub-qwt; fi - sh: make -j2 sub-src after_build: diff --git a/qwt/src/src.pro b/qwt/src/src.pro index 96e06245a..7bf618d55 100644 --- a/qwt/src/src.pro +++ b/qwt/src/src.pro @@ -14,6 +14,9 @@ include( $${QWT_ROOT}/qwtconfig.pri ) include( $${QWT_ROOT}/qwtbuild.pri ) include( $${QWT_ROOT}/qwtfunctions.pri ) +# Fix for parallel build race condition where moc_predefs.h is missing +compiler_moc_header_make_all.depends += compiler_moc_predefs_make_all + QWT_OUT_ROOT = $${OUT_PWD}/.. TEMPLATE = lib diff --git a/src/Charts/GoldenCheetah.h b/src/Charts/GoldenCheetah.h index 2906f11dc..63982b811 100644 --- a/src/Charts/GoldenCheetah.h +++ b/src/Charts/GoldenCheetah.h @@ -41,6 +41,7 @@ class Perspective; #include #include #include +#include #include "GcWindowRegistry.h" #include "TimeUtils.h" @@ -121,10 +122,10 @@ private: int oWidth, oHeight, oX, oY, mX, mY; double oHeightFactor, oWidthFactor; -public slots: +public Q_SLOTS: void _closeWindow(); -signals: +Q_SIGNALS: void controlsChanged(QWidget*); void titleChanged(QString); void subtitleChanged(QString); @@ -302,7 +303,7 @@ public: void setControls(QWidget *x); void addHelper(QString name, QWidget *widget); // add to the overlay widget -public slots: +public Q_SLOTS: void hideRevealControls(); void saveImage(); void saveChart(); diff --git a/src/Core/TimeUtils.h b/src/Core/TimeUtils.h index 7780101b6..dcb910f3d 100644 --- a/src/Core/TimeUtils.h +++ b/src/Core/TimeUtils.h @@ -28,6 +28,7 @@ #include #include #include +#include QString interval_to_str(double secs); // output like 1h 2m 3s double str_to_interval(QString s); // convert 1h 2m 3s -> 3123.0 , e.g. @@ -81,7 +82,7 @@ class DateRange : QObject bool isValid() const { return valid; } - signals: + Q_SIGNALS: void changed(QDate from, QDate to); protected: @@ -133,10 +134,10 @@ class DateSettingsEdit : public QWidget int prevN() { return prevperiod->value(); } void setPrevN(int x) { return prevperiod->setValue(x); } - private slots: + private Q_SLOTS: void setDateSettings(); - signals: + Q_SIGNALS: void useStandardRange(); void useThruToday(); void useCustomRange(DateRange); diff --git a/src/FileIO/RideFileCommand.h b/src/FileIO/RideFileCommand.h index d16fe5ebf..e3d9addd2 100644 --- a/src/FileIO/RideFileCommand.h +++ b/src/FileIO/RideFileCommand.h @@ -79,10 +79,10 @@ class RideFileCommand : public QObject int undoCount(); int redoCount(); - public slots: + public Q_SLOTS: void clearHistory(); - signals: + Q_SIGNALS: void beginCommand(bool undo, RideCommand *cmd); void endCommand(bool undo, RideCommand *cmd); diff --git a/src/Resources/win32/GC3.7-Master-W64-QT6.nsi b/src/Resources/win32/GC3.7-Master-W64-QT6.nsi index 02ff1a2d9..62e657faa 100644 --- a/src/Resources/win32/GC3.7-Master-W64-QT6.nsi +++ b/src/Resources/win32/GC3.7-Master-W64-QT6.nsi @@ -127,7 +127,6 @@ Section "Golden Cheetah (required)" Sec1 SetOutPath "$INSTDIR\platforms" File "platforms\qwindows.dll" SetOutPath "$INSTDIR" - File "opengl32sw.dll" File "OpenSSL License.txt" SetOutPath "$INSTDIR\position" File "position\qtposition_nmea.dll" @@ -218,7 +217,6 @@ Section "Golden Cheetah (required)" Sec1 File "sqldrivers\qsqlpsql.dll" SetOutPath "$INSTDIR\styles" File "styles\qmodernwindowsstyle.dll" - File "styles\qwindowsvistastyle.dll" SetOutPath "$INSTDIR\tls" File "tls\qcertonlybackend.dll" File "tls\qopensslbackend.dll" @@ -369,7 +367,6 @@ Section Uninstall Delete "$INSTDIR\license.txt" Delete "$INSTDIR\multimedia\ffmpegmediaplugin.dll" Delete "$INSTDIR\multimedia\windowsmediaplugin.dll" - Delete "$INSTDIR\opengl32sw.dll" Delete "$INSTDIR\OpenSSL License.txt" Delete "$INSTDIR\networkinformation\qnetworklistmanager.dll" Delete "$INSTDIR\platforms\qwindows.dll" @@ -454,7 +451,6 @@ Section Uninstall Delete "$INSTDIR\sqldrivers\qsqlodbc.dll" Delete "$INSTDIR\sqldrivers\qsqlpsql.dll" Delete "$INSTDIR\styles\qmodernwindowsstyle.dll" - Delete "$INSTDIR\styles\qwindowsvistastyle.dll" Delete "$INSTDIR\tls\qcertonlybackend.dll" Delete "$INSTDIR\tls\qopensslbackend.dll" Delete "$INSTDIR\tls\qschannelbackend.dll" diff --git a/src/src.pro b/src/src.pro index 7d6ddeefb..9b967a30c 100644 --- a/src/src.pro +++ b/src/src.pro @@ -45,6 +45,13 @@ greaterThan(QT_MAJOR_VERSION, 5) { } CONFIG += c++11 +###========================== +### PRECOMPILED HEADER +###========================== +PRECOMPILED_HEADER = stable.h +CONFIG += precompile_header + + ###======================================================================= ### Directory Structure - Split into subdirs to be more manageable @@ -155,6 +162,10 @@ macx { HEADERS += Train/VideoWindow.h SOURCES += Train/VideoWindow.cpp + # PCH crashes clang if we have multiple -arch flags (universal binary) + message("Disabling Precompiled Headers on macOS to avoid multi-arch Clang errors.") + CONFIG -= precompile_header + } else { # not on mac we need our own full screen support and segment control button @@ -165,6 +176,8 @@ macx { SOURCES += Train/VideoWindow.cpp } + + # X11 if (defined(GC_WANT_X11)) { LIBS += -lX11 @@ -587,6 +600,9 @@ LEXSOURCES += Core/DataFilter.l \ Train/WorkoutFilter.l \ Train/TrainerDayAPIQuery.l +# Fix parallel build races (YACC headers must exist before LEX runs) +compiler_lex_make_all.depends += compiler_yacc_decl_make_all + ###========================================= ### HEADER FILES [scanned by qmake, for moc] @@ -830,3 +846,17 @@ DEFERRES += Core/RouteWindow.h Core/RouteWindow.cpp Core/RouteItem.h Core/RouteI OTHER_FILES += Resources/python/library.py Python/SIP/goldencheetah.sip + +###============================================================================ +### FIX: Disable Precompiled Header for C files +### The PCH contains C++ specific headers (Qt, STL) which causes compilation errors +### when the PCH is forced upon C files by gcc. +###============================================================================ + +for(src, SOURCES) { + contains(src, .*\.c$) { + eval($${src}.CONFIG -= precompile_header) + } +} + + diff --git a/src/stable.h b/src/stable.h new file mode 100644 index 000000000..c3f334daa --- /dev/null +++ b/src/stable.h @@ -0,0 +1,61 @@ +/* + * stable.h - Precompiled Header for GoldenCheetah + * + * PURPOSE: + * This file contains the "Precompiled Header" (PCH) for the project. + * It includes massive, stable headers (like Qt and standard library) that rarely change. + * The compiler parses this file ONCE and reuses the binary result for every other source file, + * significantly speeding up build times. + * + * HOW TO MODIFY: + * 1. ONLY add headers here that are: + * - Very commonly used (included in many files). + * - STABLE (they almost never change). + * 2. DO NOT add local project headers (e.g. "Athlete.h") unless they are extremely stable. + * If you change a header listed here, the ENTIRE project will rebuild from scratch. + * 3. After modifying this file, run `make clean` to ensure the PCH is regenerated. + */ + +#ifndef STABLE_H +#define STABLE_H + +#if defined(__cplusplus) +// C++ Standard Library +#include +#include +#include +#include + +// Qt Core +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Qt GUI / Widgets +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + + +#endif // STABLE_H