From f6b672cfb0d10b2bc4a5fcb01d09126b97f8dbd7 Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Wed, 12 Aug 2026 18:26:57 +0000 Subject: [PATCH 4/4] Qt4: add WITH_QT4 CMake build path Adds a WITH_QT4 option (default OFF, so the existing Qt6 build is unchanged) that switches the build over to Qt4, for platforms where Qt5/6 aren't available (e.g. macOS PowerPC via MacPorts). - ProjectDependencies.cmake: find_package(Qt4) instead of Qt6, skipping the Qt6-only QPA platform-plugin property lookups (Qt4 predates the QPA model, so they don't apply). - ProjectExternals.cmake: qt-solutions' own CMakeLists.txt (CMakeLists_qt-solutions.cmake.in) hardcodes Qt6, so under Qt4 locate the prebuilt MacPorts devel/qtsingleapplication-qt4 port instead (find_path/find_library against the Qt4 kit's own include/lib dirs) and expose it as the same qt-solutions::qtsingleapplication imported target used by src/CMakeLists.txt either way. - src/CMakeLists.txt: link Qt4::QtCore/QtGui/QtNetwork (Widgets and StateMachine are bundled into those under Qt4) instead of the Qt6 targets, and skip the whole bundle/fixup_bundle step, which relies on Qt6-only QPA plugin targets and isn't needed for a package-manager build that links the system Qt4 frameworks directly (the same model the historical qmake-based v1.3 build used). No JSON usage exists anywhere in this codebase, so qjson4 (also suggested as a MacPorts dependency) isn't needed. Note for whoever builds this: CMake's bundled FindQt4 module was removed from mainline CMake (~3.24+); this path needs an older CMake that still ships it, or a vendored replacement. Not addressed here since it's an environment concern, not a code one. Part of Qt4 buildability work for the macOS PowerPC port. --- CMake/Includes/ProjectDependencies.cmake | 37 +++++++++++++++--------- CMake/Includes/ProjectExternals.cmake | 28 +++++++++++++++++- CMake/Includes/ProjectSettings.cmake | 2 ++ src/CMakeLists.txt | 31 ++++++++++++++++---- 4 files changed, 77 insertions(+), 21 deletions(-) diff --git a/CMake/Includes/ProjectDependencies.cmake b/CMake/Includes/ProjectDependencies.cmake index 8d04a62..e39d548 100644 --- a/CMake/Includes/ProjectDependencies.cmake +++ b/CMake/Includes/ProjectDependencies.cmake @@ -3,21 +3,30 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) -find_package(Qt6 6.0 REQUIRED COMPONENTS Core Gui Widgets Network StateMachine) -if(MINGW) - get_target_property(_qwindows_dll Qt6::QWindowsIntegrationPlugin LOCATION) - if(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.7") - get_target_property(_qwinstyle_dylib Qt6::QModernWindowsStylePlugin LOCATION) - elseif(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.0") - get_target_property(_qwinstyle_dylib Qt6::QWindowsVistaStylePlugin LOCATION) - endif() +if(WITH_QT4) + # Qt4 is the last Qt version available on legacy platforms such as + # macOS PowerPC (via MacPorts). QStateMachine lives in QtCore there + # (it wasn't split into its own module until Qt5), and Qt4 predates + # the QPA platform-plugin model entirely, so none of the Qt6 + # plugin-property lookups below are applicable. + find_package(Qt4 4.8 REQUIRED COMPONENTS QtCore QtGui QtNetwork) +else() + find_package(Qt6 6.0 REQUIRED COMPONENTS Core Gui Widgets Network StateMachine) + if(MINGW) + get_target_property(_qwindows_dll Qt6::QWindowsIntegrationPlugin LOCATION) + if(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.7") + get_target_property(_qwinstyle_dylib Qt6::QModernWindowsStylePlugin LOCATION) + elseif(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.0") + get_target_property(_qwinstyle_dylib Qt6::QWindowsVistaStylePlugin LOCATION) + endif() - get_target_property(_schannel_dll Qt6::QSchannelBackendPlugin LOCATION) -endif() -if(APPLE) - get_target_property(_qcocoa_dylib Qt6::QCocoaIntegrationPlugin LOCATION) - if(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.0") - get_target_property(_qmacstyle_dylib Qt6::QMacStylePlugin LOCATION) + get_target_property(_schannel_dll Qt6::QSchannelBackendPlugin LOCATION) + endif() + if(APPLE) + get_target_property(_qcocoa_dylib Qt6::QCocoaIntegrationPlugin LOCATION) + if(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.0") + get_target_property(_qmacstyle_dylib Qt6::QMacStylePlugin LOCATION) + endif() endif() endif() diff --git a/CMake/Includes/ProjectExternals.cmake b/CMake/Includes/ProjectExternals.cmake index c5ed632..4f807e2 100644 --- a/CMake/Includes/ProjectExternals.cmake +++ b/CMake/Includes/ProjectExternals.cmake @@ -36,7 +36,33 @@ if(NOT spdlog_FOUND) include(ProjectExternals_spdlog) endif() -include(ProjectExternals_qt-solutions) +if(WITH_QT4) + # qt-solutions' own CMakeLists.txt (CMakeLists_qt-solutions.cmake.in) + # hardcodes Qt6, so under Qt4 use the prebuilt MacPorts + # devel/qtsingleapplication-qt4 port instead of building it ourselves. + find_path(QTSINGLEAPPLICATION_INCLUDE_DIR + NAMES QtSingleApplication + PATH_SUFFIXES QtSingleApplication + HINTS ${QT_INCLUDE_DIR} + ) + find_library(QTSINGLEAPPLICATION_LIBRARY + NAMES QtSingleApplication + HINTS ${QT_LIBRARY_DIR} + ) + if(NOT QTSINGLEAPPLICATION_INCLUDE_DIR OR NOT QTSINGLEAPPLICATION_LIBRARY) + message(FATAL_ERROR "Could NOT find QtSingleApplication! Install it with e.g. 'port install qtsingleapplication-qt4'") + endif() + message(STATUS "Library 'QtSingleApplication' found at ${QTSINGLEAPPLICATION_LIBRARY}") + + add_library(qt-solutions::qtsingleapplication STATIC IMPORTED) + set_target_properties(qt-solutions::qtsingleapplication PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${QTSINGLEAPPLICATION_INCLUDE_DIR}" + IMPORTED_LOCATION "${QTSINGLEAPPLICATION_LIBRARY}" + ) + mark_as_advanced(QTSINGLEAPPLICATION_INCLUDE_DIR QTSINGLEAPPLICATION_LIBRARY) +else() + include(ProjectExternals_qt-solutions) +endif() if(MINGW) if (NOT CMAKE_CROSSCOMPILING) include(ProjectExternals_openconnect) diff --git a/CMake/Includes/ProjectSettings.cmake b/CMake/Includes/ProjectSettings.cmake index f94f6b4..0e94801 100644 --- a/CMake/Includes/ProjectSettings.cmake +++ b/CMake/Includes/ProjectSettings.cmake @@ -1,5 +1,7 @@ option(PROJ_GNUTLS_DEBUG "Enable GnuTLS debug mode" OFF) +option(WITH_QT4 "Build against Qt4 instead of Qt6, for legacy platforms (e.g. macOS PowerPC) where Qt5/6 are unavailable" OFF) + option(PROJ_ADMIN_PRIV_ELEVATION "Admin privileges elevation; don't turn it off in production!! (UAC on Windows) " ON) if(MINGW) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4e0012a..92ba07f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -160,14 +160,25 @@ endif() target_link_libraries (${PROJECT_NAME} spdlog::spdlog qt-solutions::qtsingleapplication - - Qt6::Core - Qt6::Gui - Qt6::Widgets - Qt6::Network - Qt6::StateMachine ) +if(WITH_QT4) + # Widgets and StateMachine are bundled into QtGui/QtCore under Qt4. + target_link_libraries (${PROJECT_NAME} + Qt4::QtCore + Qt4::QtGui + Qt4::QtNetwork + ) +else() + target_link_libraries (${PROJECT_NAME} + Qt6::Core + Qt6::Gui + Qt6::Widgets + Qt6::Network + Qt6::StateMachine + ) +endif() + if(UNIX) target_link_libraries(${PROJECT_NAME} Threads::Threads @@ -187,6 +198,13 @@ install(TARGETS ${PROJECT_NAME} ) # fixup the bundle +# +# Not applicable under Qt4: it predates the QPA platform-plugin model +# entirely, and package-manager builds (e.g. the macOS PowerPC MacPorts +# port) link against the system-installed Qt4 frameworks directly rather +# than bundling a self-contained app, same as the historical qmake-based +# v1.3 build did. +if(NOT WITH_QT4) get_target_property(QT_LIBRARY_DIR Qt6::Core LOCATION) get_filename_component(QT_LIBRARY_DIR ${QT_LIBRARY_DIR} PATH) list(APPEND libSearchDirs ${QT_LIBRARY_DIR}) @@ -269,3 +287,4 @@ install(CODE " fixup_bundle(\"${APPS}\" \"${additionalLib}\" \"${libSearchDirs}\") " DESTINATION . COMPONENT App ) +endif() # NOT WITH_QT4 -- 2.43.0