Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/CMakeLists.txt
T
berrux-dev e067c21b0d Enable Codification/OHP/PlanEditor/OrgChart plugin groups (G12 225); harden new_docker_build.sh
First-build fixes (DDS members, Qt6 transitive WebChannel/PrintSupport drops, logger init, Qt5 guard); script: log_warn, BUILD_WLS default ON, Poppler image+APT, XmlPatterns 6.0 wording
2026-10-21 13:50:10 +02:00

1145 lines
53 KiB
CMake
Executable File

#
# Haupt CMakeLists.txt für das Projekt TDS
#
# $Id$
# $HeadURL$
# $Author$
#
# Setzen von CMAKE_INSTALL_PREFIX auf "/shd/CTC" falls nicht über Kommandozeile angegeben
#
CMAKE_MINIMUM_REQUIRED(VERSION 3.16)
IF(POLICY CMP0069)
CMAKE_POLICY(SET CMP0069 NEW) # cmake >= 3.9.0 - INTERPROCEDURAL_OPTIMIZATION behavior
ENDIF()
IF(POLICY CMP0071)
CMAKE_POLICY(SET CMP0071 NEW) # cmake >= 3.10.0 - automatically process generated sources with AUTOMOC
ENDIF()
IF(POLICY CMP0072)
CMAKE_POLICY(SET CMP0072 NEW) # cmake >= 3.11.0 - prefer libOpenGL.so over legacy libGL.so
ENDIF()
IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
SET(CMAKE_INSTALL_PREFIX "/shd/CTC" CACHE STRING "Install path prefix, prepended onto install directories." FORCE)
ENDIF()
#
# # Setzen von CMAKE_BUILD_TYPE auf "Debug" falls nicht über Kommandozeile angegeben
#
IF(NOT DEFINED CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel." FORCE)
ENDIF()
ADD_DEFINITIONS(-DEXPORT_BDV_TOPIC_AS_JSON)
SET(_ver "1.2.0")
IF(DEFINED LTS_VERSION_MAJOR AND DEFINED LTS_VERSION_MINOR AND DEFINED LTS_VERSION_PATCH)
SET(_ver "${LTS_VERSION_MAJOR}.${LTS_VERSION_MINOR}.${LTS_VERSION_PATCH}")
ENDIF()
PROJECT(LTS VERSION ${_ver})
MESSAGE(STATUS "LTS Version: ${LTS_VERSION_MAJOR}.${LTS_VERSION_MINOR}.${LTS_VERSION_PATCH}")
# Enable CTest integration for unit tests
include(CTest)
function(NGL_ADD_SUBDIR_GUARDED subdir)
if(MIGRATE_MODULE STREQUAL "")
add_subdirectory(${subdir})
else()
# normalize to forward slashes
string(REPLACE "\\" "/" _mig "${MIGRATE_MODULE}")
string(REPLACE "\\" "/" _sub "${subdir}")
# also compare basenames so MIGRATE_MODULE=Lts/DDS matches subdir 'DDS' when called from Lts
get_filename_component(_mig_base "${_mig}" NAME)
get_filename_component(_sub_base "${_sub}" NAME)
# If MIGRATE_MODULE either starts with the subdir, equals it, contains it as a path component,
# or the basename matches, include the subdir. This makes nested paths like
# 'Lts/Proxies/TrainingAreaBase' include both 'Lts' and its child 'Proxies'.
if(_mig MATCHES "^${_sub}(/|$)" OR _sub MATCHES "^${_mig}(/|$)" OR _mig MATCHES ".*/${_sub}(/|$)" OR _sub MATCHES ".*/${_mig}(/|$)" OR _mig_base STREQUAL _sub OR _sub_base STREQUAL _mig)
message(STATUS "Including subdir ${subdir} because MIGRATE_MODULE=${MIGRATE_MODULE}")
add_subdirectory(${subdir})
else()
message(STATUS "Skipping subdir ${subdir} because MIGRATE_MODULE=${MIGRATE_MODULE}")
endif()
endif()
endfunction()
SET(LTS_VERSION_DATE "01.01.2018" CACHE STRING "The date when this software was compiled")
ADD_DEFINITIONS(-DLTS_VERSION_MAJOR=\"${LTS_VERSION_MAJOR}\")
ADD_DEFINITIONS(-DLTS_VERSION_MINOR=\"${LTS_VERSION_MINOR}\")
ADD_DEFINITIONS(-DLTS_VERSION_PATCH=\"${LTS_VERSION_PATCH}\")
ADD_DEFINITIONS(-DLTS_VERSION_DATE=\"${LTS_VERSION_DATE}\")
IF(JENKINS_BUILD_NUMBER)
ADD_DEFINITIONS(-DJENKINS_BUILD_NUMBER=\"${JENKINS_BUILD_NUMBER}\")
ELSE()
ADD_DEFINITIONS(-DJENKINS_BUILD_NUMBER=\"unknown\")
ENDIF()
ADD_DEFINITIONS(-DAPP6C)
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
# Resolve <DDS/...> and other framework includes to the real headers under
# Lts/ BEFORE the migration stub tree in include/. The stub tree shadows them
# otherwise and opens namespace DDSGeneric around framework includes, which
# pulls Qt/std definitions into that namespace and breaks every consumer.
# (The qt5 legacy has no include/ tree; Lts/ is the real include root.)
include_directories(BEFORE ${CMAKE_SOURCE_DIR}/Lts)
include_directories(${CMAKE_SOURCE_DIR}/include)
# Legacy also used source-root-relative includes (<Lts/Services/<Svc>/logger.h>, ...);
# the source root must be an include root so those resolve.
include_directories(${CMAKE_SOURCE_DIR})
# Include directory for generated export headers
include_directories(${CMAKE_BINARY_DIR})
include_directories(${CMAKE_SOURCE_DIR}/Z/src)
# Include directories for external dependencies and internal modules
include_directories(${CMAKE_SOURCE_DIR}/Z/src)
include_directories(${CMAKE_SOURCE_DIR}/Z/src/ngltools)
include_directories(${CMAKE_SOURCE_DIR}/Lts/Viewer/SituationMap/Symbology)
# <Symbology/...> headers (symbol_dictionary.h, sidc_codec.h, ...) are consumed tree-wide
# (e.g. AdvancedSymbology/asb_data_plugin_interface.h is pulled into PpmCommon), so the
# parent dir must be a global root too, not only on the AdvancedSymbology target.
include_directories(${CMAKE_SOURCE_DIR}/Lts/Viewer/SituationMap)
# Generated SymbologyGui/advancedsymbologygui_export.h lives in the build dir; the source
# SituationMap root above only covers the source Symbology headers.
include_directories(${CMAKE_BINARY_DIR}/Lts/Viewer/SituationMap)
include_directories(${CMAKE_SOURCE_DIR}/Lts/Viewer/LtsDataView)
include_directories(${CMAKE_SOURCE_DIR}/Lts/Proxies/TrainingAreaBase)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/ProjectDataManagement)
include_directories(${CMAKE_SOURCE_DIR}/Lts/Services)
# Consumers include generated DDS service headers by service-prefixed name
# (<ParticipantManagement/ppm.hpp>, <GuezNasat/gna_dtc.h>, ...). Those headers
# live in the per-service BUILD dirs, so the binary Lts/Services ROOT must be
# visible tree-wide (the per-service build dirs below only satisfy the bare
# <ppm.hpp> form). Placed right after the source Lts/Services so a header
# present in both still resolves to the source (binary only supplies the
# generated headers). This mirrors the legacy <Services/...> form.
include_directories(${CMAKE_BINARY_DIR}/Lts/Services)
# Generated DDS headers for Proxies (GuezNasat/gna_dtc.h, ...) live under the binary
# Lts/Proxies dir; consumers include them by proxy-prefixed name (<GuezNasat/gna_dtc.h>).
include_directories(${CMAKE_BINARY_DIR}/Lts/Proxies)
include_directories(${CMAKE_SOURCE_DIR}/include/ProjectDataManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/InfrastructureManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/InfrastructureManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Plugins/InfrastructureManagement/Shared)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/AssetManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/AssetManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/AudioVideoManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/AudioVideoManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/ExerciseEventManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/ExerciseEventManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/ExerciseManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/ExerciseManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/FileManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/NotificationManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/NotificationManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/ParticipantManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/ParticipantManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/ReportManagement)
include_directories(${CMAKE_SOURCE_DIR}/include/ReportManagement)
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/SituationReplay)
include_directories(${CMAKE_SOURCE_DIR}/include/SituationReplay)
# Evaluations' generated evl_db_structs.h includes <evl_enums.hpp> by bare name, and that
# header is consumed from OcBaseDownload as well, so its build dir must be visible tree-wide
# like the services above. There is no include/Evaluations stub tree, so only the build dir
# is added (same shape as FileManagement above, which has no stub tree either).
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/Evaluations)
include_directories(${CMAKE_SOURCE_DIR}/Lts/Proxies/GuezNasat)
# GuezNasat's generated export header (svcgnacommon_export.h) lives in the build dir;
# logger.h includes it by bare name, so the build dir must be visible tree-wide.
include_directories(${CMAKE_BINARY_DIR}/Lts/Proxies/GuezNasat)
include_directories(${CMAKE_SOURCE_DIR}/Lts/DDS)
include_directories(${CMAKE_SOURCE_DIR}/Lts/DDS/QosProfile)
# Generated DDS headers (BUILD_RTI=ON)
include_directories(${CMAKE_BINARY_DIR}/Lts)
# <Core/core.hpp> consumers (LtsCoordinate, AES/CES, HLA proxies) resolve the
# rtiddsgen-generated core.hpp from the DDS build dir (the qt5 include order);
# the OFF-era stub copies in include/Core/ have been removed.
include_directories(${CMAKE_BINARY_DIR}/Lts/DDS)
include_directories(${CMAKE_SOURCE_DIR}/Lts/Common)
include_directories(${CMAKE_SOURCE_DIR}/Lts/Common/LtsUtils)
include_directories(${CMAKE_BINARY_DIR}/Lts/Common/LtsUtils/LtsUtilsCore)
# LtsUtilsSettings's generated ltsutilssettings_export.h is included by bare name from
# settings.h. Consumer targets that reach settings.h transitively (without linking
# LtsUtilsSettings themselves) cannot see it through the target's PUBLIC interface, so the
# directory holding the generated header has to be visible tree-wide. The directory contains
# only that generated header, so appending it cannot shadow an existing include.
include_directories(${CMAKE_BINARY_DIR}/Lts/Common/LtsUtils/LtsUtilsSettings)
# LtsUtilsGui ConnectDialog's generated ltsutilsguiconnectdialog_export.h is included by bare
# name from connect_dialog.h / connect_dialog_nt.h; same tree-wide visibility as the dirs above.
include_directories(${CMAKE_BINARY_DIR}/Lts/Common/LtsUtils/LtsUtilsGui/ConnectDialog)
# DDSConnector's generated ddsconnector_export.h is included by bare name from
# dds_connector.h and pub_sub_base.h, and reaches targets (the AES ModuleTests) that include
# DDSConnector headers without linking ddsconnector. Same shape as LtsUtilsSettings above: the
# directory holds only the generated header.
include_directories(${CMAKE_BINARY_DIR}/Lts/DDS/DDSConnector)
# The generated msg_db_structs.h includes <msg_enums.hpp> by bare name, and Messaging is
# reached transitively from OcBaseDownload and the proxy handlers, so its build dir must be
# visible tree-wide like the services above. Unlike them there is no include/Messaging stub
# tree, so only the build dir is added.
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/Messaging)
include_directories(${CMAKE_SOURCE_DIR}/Z/src/NGLLogger)
include_directories(${CMAKE_SOURCE_DIR}/include/Viewer/SituationMap)
include_directories(${CMAKE_SOURCE_DIR}/include/OperatorManagement)
# The generated opm_db_structs.h includes <opm_enums.hpp> by bare name and is reached
# transitively from OcBaseDownload, so the OperatorManagement build dir has to be visible
# tree-wide next to its include/ stub tree above.
include_directories(${CMAKE_BINARY_DIR}/Lts/Services/OperatorManagement)
# The plugin interface headers live under Lts/Plugins/<Svc>/ and are included both as
# <Plugins/<Svc>/x.h> (the qt5 spelling, resolved through the Lts/ root) and, since the
# migration dropped the leading segment, as <Svc>/x.h>. Lts/Plugins is therefore needed on
# the path. It is appended last so it can only ever resolve includes that were unresolvable
# before: every include that resolves today is found in an earlier directory, so no existing
# resolution can change.
include_directories(${CMAKE_SOURCE_DIR}/Lts/Plugins)
SET(CMAKE_CXX_STANDARD 17)
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
SET(CMAKE_CXX_VISIBILITY_PRESET hidden)
# Qt6 Migration: Removed CMAKE_POSITION_INDEPENDENT_CODE - Qt6 handles PIC automatically
# and this setting conflicts with Qt6's reduce_relocations feature
# SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
IF(CMAKE_VERSION VERSION_GREATER 3.15.9)
OPTION(USE_UNITY_BUILDS "Use Unity builds to speed up compilation (cmake 3.16 or newer required!)" OFF)
IF (USE_UNITY_BUILDS)
SET(CMAKE_UNITY_BUILD ON)
SET(CMAKE_UNITY_BUILD_BATCH_SIZE 40)
ENDIF()
ENDIF()
# Qt6 Migration: Options to disable modules with missing dependencies (WebEngine, XmlPatterns, ArcGIS)
# These can be enabled once the required system dependencies are available in the build environment
OPTION(BUILD_PLUGINS_PLANEDITOR "Build PlanEditor plugin (requires Qt6 WebEngine + ArcGIS SDK)" OFF)
OPTION(BUILD_PLUGINS_ONLINEHELP "Build OnlineHelp plugin (requires Qt6 WebEngine)" OFF)
OPTION(BUILD_PLUGINS_SERVICEMONITOR "Build ServiceMonitor plugin (requires Qt6 WebEngine)" OFF)
OPTION(BUILD_PLUGINS_PARTICIPANT_ORG_CHART "Build ParticipantOrgChart (requires Qt6 WebEngine)" OFF)
OPTION(BUILD_PLUGINS_MSDL "Build MSDL module (requires Qt6 XmlPatterns)" OFF)
OPTION(BUILD_PLUGINS_SAAB "Build Saab module (requires Qt6 XmlPatterns)" OFF)
OPTION(BUILD_RTI "Build RTI Connext DDS dependent modules" OFF)
OPTION(BUILD_VIEWER_ONLY "Build only Viewer module (no RTI required)" OFF)
# Add Lts/ include path globally for QosProfile and other Lts headers
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/Lts)
IF(BUILD_RTI)
# Define BUILD_RTI as preprocessor macro for all targets
ADD_COMPILE_DEFINITIONS(BUILD_RTI)
# External (RTI) DDS is available: compile the BUILD_WITH_EXTERNAL_DDS code paths
# (used by 73 guards across plugins, e.g. MrkCommon's MarkerManagementDialogModel /
# CustomViewMarker). Legacy always compiled this DDS code; the flag is a migration
# option that was never wired into CMake, so its absence silently dropped the
# definitions while the unguarded class declarations still referenced them (link error).
ADD_COMPILE_DEFINITIONS(BUILD_WITH_EXTERNAL_DDS)
ENDIF()
OPTION(BUILD_ARCGIS "Build ArcGIS SDK dependent modules" ON)
OPTION(BUILD_FILTERMANAGEMENT "Build FilterManagement plugins (temporarily disabled for migration)" OFF)
OPTION(BUILD_CODIFICATION "Build CodificationManagement plugins (requires KDReports)" OFF)
OPTION(BUILD_GRANTLEE "Build CodeGen SQL files using KTextTemplate parser (KF6::TextTemplate)" ON)
# If BUILD_GRANTLEE is OFF but ngl_codegen is needed (for IDL codegen),
# provide it as an imported executable target from pre-built location
IF(NOT BUILD_GRANTLEE)
# ngl_codegen is copied to build/bin/ by run_final_migration.sh
# Create an imported target so MacroCodeGenIdl.cmake can find it
IF(NOT TARGET ngl_codegen)
ADD_EXECUTABLE(ngl_codegen IMPORTED GLOBAL)
SET_TARGET_PROPERTIES(ngl_codegen PROPERTIES
IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/bin/ngl_codegen"
)
MESSAGE(STATUS "Using pre-built ngl_codegen from ${CMAKE_BINARY_DIR}/bin/ngl_codegen")
ENDIF()
ENDIF()
OPTION(BUILD_LTSWEBSOCKET "Build LtsWebSocket module (requires NGLLogger)" ON)
IF(WIN32)
SET(EXTERNAL_LIBRARY_DIR "C:/Development/Projekte/SituationMap/ExtFw" CACHE STRING "Library dir with all external dependencies")
LIST(APPEND CMAKE_PREFIX_PATH "${EXTERNAL_LIBRARY_DIR}")
LIST(APPEND CMAKE_PROGRAM_PATH "${EXTERNAL_LIBRARY_DIR}/bin;${EXTERNAL_LIBRARY_DIR}/dev-utils/bin")
ELSE()
# Linux: ArcGIS SDK Pfad konfigurieren (nur wenn BUILD_ARCGIS=ON)
IF(BUILD_ARCGIS)
# Use environment variable ARCGIS_ROOT if set, otherwise default to /workspace/external/... (Docker) or host path
IF(DEFINED ENV{ARCGIS_ROOT})
SET(ARCGIS_SDK_DIR "$ENV{ARCGIS_ROOT}" CACHE STRING "ArcGIS Runtime SDK for Qt directory")
ELSEIF(EXISTS "/workspace/external/ArcGIS/MapsSDK_Qt_300.0.0/ArcGIS_Maps_SDK_Qt_300.0.0/qt300.0.0/sdk")
SET(ARCGIS_SDK_DIR "/workspace/external/ArcGIS/MapsSDK_Qt_300.0.0/ArcGIS_Maps_SDK_Qt_300.0.0/qt300.0.0/sdk" CACHE STRING "ArcGIS Runtime SDK for Qt directory")
ELSE()
SET(ARCGIS_SDK_DIR "/repo/external/ArcGIS/MapsSDK_Qt_300.0.0/ArcGIS_Maps_SDK_Qt_300.0.0/qt300.0.0/sdk" CACHE STRING "ArcGIS Runtime SDK for Qt directory")
ENDIF()
IF(EXISTS "${ARCGIS_SDK_DIR}")
LIST(APPEND CMAKE_PREFIX_PATH "${ARCGIS_SDK_DIR}")
MESSAGE(STATUS "ArcGIS SDK found at: ${ARCGIS_SDK_DIR}")
# arcgisversion.h (a custom RME file in the SDK include dir) is pulled in via
# <SituationMap/Map/layer_factory.h> by many non-ArcGIS plugin targets (e.g.
# IsmResGuiPlugin); the ArcGIS::ArcGIS target include dir does not reach them, so
# expose the SDK include dir tree-wide when the SDK is present.
include_directories(${ARCGIS_SDK_DIR}/include)
ELSE()
MESSAGE(WARNING "ArcGIS SDK not found at: ${ARCGIS_SDK_DIR}")
ENDIF()
ENDIF()
ENDIF()
# Set CMAKE_MODULE_PATH early so FIND_PACKAGE can find our custom Find modules
SET(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
INCLUDE(FindLibraryWithDebug)
# Find ArcGIS SDK globally if BUILD_ARCGIS is enabled
# This creates ArcGIS::ArcGIS target for all modules to use
IF(BUILD_ARCGIS)
FIND_PACKAGE(ArcGIS REQUIRED)
ENDIF()
ENABLE_TESTING()
INCLUDE(CTest)
CONFIGURE_FILE(CTestCustom.ctest ${CMAKE_BINARY_DIR}/CTestCustom.ctest COPYONLY)
CONFIGURE_FILE(lts-cc.conf ${CMAKE_BINARY_DIR}/lts-cc.conf.distrib COPYONLY)
# Add bundled GeographicLib cmake config to find modern targets (GeographicLib::GeographicLib_SHARED)
LIST(APPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/include/GeographicLib/lib/cmake")
SET(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
IF(WIN32)
SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
ELSE(WIN32)
SET(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib)
ENDIF()
#
# Disallow in-source build
#
INCLUDE(MacroEnsureOutOfSourceBuild)
macro_ensure_out_of_source_build("In-Source build nicht erlaubt!")
#
# Qt ist wichtig - zuerst suchen
#
SET(CMAKE_AUTOMOC TRUE)
SET(CMAKE_AUTOUIC TRUE)
SET(QT_USE_IMPORTED_TARGETS TRUE)
# Check for OpenGL first (required by Qt6Gui)
find_package(OpenGL)
# Prefer Qt6, fallback to Qt5. Create Qt6::*-aliases when Qt6 is found so existing CMakeLists continue to work.
# Try to find Qt6 with GUI components first
set(QT6_GUI_AVAILABLE FALSE)
set(QT6_FOUND FALSE)
set(QT6_CORE5COMPAT_AVAILABLE FALSE)
# First check if Core5Compat is available
find_package(Qt6 6.2 COMPONENTS Core5Compat QUIET)
if(Qt6Core5Compat_FOUND)
set(QT6_CORE5COMPAT_AVAILABLE TRUE)
message(STATUS "Found Qt6Core5Compat")
endif()
# Find Qt6 core components first (without OpenGL which may not be available)
# WebSockets is required by the migrated services (FileManagement's THP script
# server uses QWebSocketServer; LtsWebSocket/httq enable their real websocket
# paths via QT6_WEBSOCKETS_AVAILABLE when the module is found).
find_package(Qt6 6.2 COMPONENTS Concurrent Core LinguistTools Network
Multimedia Sql SerialPort Test Xml Positioning Svg WebSockets PrintSupport OpenGL QUIET)
if(Qt6_FOUND)
# Skip GUI find_package - it fails without OpenGL. We'll create manual targets below.
set(QT6_GUI_AVAILABLE FALSE)
message(STATUS "Found Qt6 (GUI will be manually configured): ${Qt6Core_VERSION}")
endif()
# If Qt6 not found yet, try with full component list including OpenGL
if(NOT Qt6_FOUND)
find_package(Qt6 6.2 COMPONENTS Concurrent Core LinguistTools Network OpenGL PrintSupport
Multimedia Sql Svg SerialPort Test UiTools WebSockets WebEngineCore WebEngineWidgets
Widgets Xml Positioning QUIET)
if(Qt6_FOUND AND OpenGL_FOUND)
set(QT6_GUI_AVAILABLE TRUE)
message(STATUS "Found Qt6 with GUI support (OpenGL): ${Qt6Core_VERSION}")
endif()
endif()
if(NOT Qt6_FOUND)
# Final fallback - try to find Qt6 with minimum required components
find_package(Qt6 6.2 COMPONENTS Core REQUIRED)
message(STATUS "Found Qt6 (minimal): ${Qt6Core_VERSION}")
endif()
# Qt6::XmlPatterns (consumed by the MSDL/Saab import libs, gated by
# BUILD_PLUGINS_MSDL / BUILD_PLUGINS_SAAB): the XmlPatterns module (its own
# qtxmlpatterns repo) was removed in Qt 6.0 and never re-introduced, so no Qt 6
# install carries it. It is NOT part of the component lists above (a missing
# component there would flip Qt6_FOUND off and disable the whole GUI path).
# Find it separately; when absent the two plugins must stay disabled - their
# CMakeLists reference Qt6::XmlPatterns in link libraries and CMake errors at
# generate time for an undefined namespaced target.
if(NOT TARGET Qt6::XmlPatterns)
find_package(Qt6XmlPatterns QUIET)
if(Qt6XmlPatterns_FOUND)
message(STATUS "Found Qt6XmlPatterns")
else()
message(STATUS "Qt6XmlPatterns not found (PpmMSDLGuiPlugin/PpmSAABGuiPlugin require it; keep BUILD_PLUGINS_MSDL/BUILD_PLUGINS_SAAB OFF)")
endif()
endif()
# Qt6::WebChannel (consumed by PpmOrgChartGuiPlugin's QWebChannel page setup):
# in Qt5 Qt5::WebEngineWidgets transitively linked Qt5::WebChannel (Qt5's
# webengine depended on webchannel), but Qt6 dropped that dependency, so the
# module must be found and linked explicitly. Separate QUIET find - never let
# a missing optional component flip Qt6_FOUND off.
if(NOT TARGET Qt6::WebChannel)
find_package(Qt6 6.2 COMPONENTS WebChannel QUIET)
if(Qt6WebChannel_FOUND)
message(STATUS "Found Qt6WebChannel")
else()
message(STATUS "Qt6WebChannel not found (PpmOrgChartGuiPlugin requires it; keep BUILD_PLUGINS_PARTICIPANT_ORG_CHART OFF)")
endif()
endif()
# Manual Qt6 configuration - create imported targets for available libraries
if(NOT TARGET Qt6::Core)
find_package(Qt6 6.2 COMPONENTS Core REQUIRED)
endif()
# Qt State Machine (QState/QStateMachine) was moved out of QtGui in Qt6 into the
# separate "Qt State Machine" add-on (the qtscxml package). In Qt5 the state
# machine classes lived inside QtGui/QtCore, so the ExerciseManagement state
# machines (exercise_state_base/exercise_state_machine) compiled without an
# explicit StateMachine dependency. Probe for the module now; if present the
# affected targets link Qt6::StateMachine (guarded per-target below).
find_package(Qt6 6.2 COMPONENTS StateMachine QUIET)
# Create imported targets for all available Qt6 libraries
# Use Qt6 installation path from find_package or fall back to system paths
if(Qt6Core_DIR)
# <Qt6Core_DIR> is the cmake package dir: <prefix>/lib/cmake/Qt6Core in the
# standard Qt layout and <prefix>/<multiarch>/cmake/Qt6Core in the Debian/
# Ubuntu layout — so the library dir is two levels up in both. (Going three
# levels up and appending /lib only matches the standard layout; in the
# Debian validation container it resolved to /usr/lib/lib and every manual
# target below was silently skipped, breaking all targets linking
# Qt6::Sql / Qt6::Xml / Qt6::Test.)
get_filename_component(QT6_LIB_DIR "${Qt6Core_DIR}/../.." ABSOLUTE)
get_filename_component(QT6_ARCH_DIR "${QT6_LIB_DIR}" NAME)
# The standard layout keeps headers in <prefix>/include; Debian/Ubuntu keeps
# them in <prefix>/include/<multiarch>/qt6 — probe the multiarch form first.
if(EXISTS "${QT6_LIB_DIR}/../../include/${QT6_ARCH_DIR}/qt6")
get_filename_component(QT6_INC_DIR "${QT6_LIB_DIR}/../../include/${QT6_ARCH_DIR}/qt6" ABSOLUTE)
else()
get_filename_component(QT6_INC_DIR "${QT6_LIB_DIR}/../include" ABSOLUTE)
endif()
elseif(DEFINED ENV{QT_BASE_DIR} AND DEFINED ENV{QT_VERSION} AND DEFINED ENV{QT_ARCH_DIR})
set(QT6_LIB_DIR "$ENV{QT_BASE_DIR}/$ENV{QT_VERSION}/$ENV{QT_ARCH_DIR}/lib")
set(QT6_INC_DIR "$ENV{QT_BASE_DIR}/$ENV{QT_VERSION}/$ENV{QT_ARCH_DIR}/include")
else()
set(QT6_LIB_DIR "/usr/lib/x86_64-linux-gnu")
set(QT6_INC_DIR "/usr/include/x86_64-linux-gnu/qt6")
endif()
# Qt6::DBus
if(NOT TARGET Qt6::DBus AND EXISTS "${QT6_LIB_DIR}/libQt6DBus.so.6")
add_library(Qt6::DBus SHARED IMPORTED)
set_target_properties(Qt6::DBus PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6DBus.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtDBus;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core"
)
endif()
# Qt6::Gui (needs OpenGL libs, X11, EGL)
if(NOT TARGET Qt6::Gui AND EXISTS "${QT6_LIB_DIR}/libQt6Gui.so.6")
add_library(Qt6::Gui SHARED IMPORTED)
set_target_properties(Qt6::Gui PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Gui.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtGui;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::DBus;${QT6_LIB_DIR}/libQt6OpenGL.so.6;${QT6_LIB_DIR}/libEGL.so.1;${QT6_LIB_DIR}/libGLX.so.0;${QT6_LIB_DIR}/libX11.so.6;${CMAKE_DL_LIBS};pthread"
)
endif()
# Set variable for legacy code that uses ${Qt6_Gui} — like Qt6_Widgets below,
# subdirectory CMakeLists contain `set(Qt6_Gui ${Qt6_Gui})` optional-guard
# no-ops that keep this root-scope value.
if(TARGET Qt6::Gui)
set(Qt6_Gui Qt6::Gui)
endif()
# Qt6::Widgets - create manual target (find_package fails without OpenGL)
if(EXISTS "${QT6_LIB_DIR}/libQt6Widgets.so.6")
if(NOT TARGET Qt6::Widgets)
add_library(Qt6::Widgets SHARED IMPORTED)
endif()
set_target_properties(Qt6::Widgets PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Widgets.so.6"
INTERFACE_INCLUDE_DIRECTORIES "/usr/include/x86_64-linux-gnu/qt6/QtWidgets;/usr/include/x86_64-linux-gnu/qt6"
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui"
)
# Set variable for legacy code that uses ${Qt6_Widgets}
set(Qt6_Widgets Qt6::Widgets)
set(QT6_GUI_AVAILABLE TRUE)
message(STATUS "Manually configured Qt6 Widgets target")
endif()
# Qt6::OpenGL - create manual target if not found (QOpenGLPaintDevice, used by ArcGIS SDK)
if(NOT TARGET Qt6::OpenGL AND EXISTS "${QT6_LIB_DIR}/libQt6OpenGL.so.6")
add_library(Qt6::OpenGL SHARED IMPORTED)
set_target_properties(Qt6::OpenGL PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6OpenGL.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtGui;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core"
)
message(STATUS "Manually configured Qt6 OpenGL target")
endif()
# Qt6::OpenGLWidgets - create manual target if not found
# (QOpenGLWidget, used by the ArcGIS SDK MapGraphicsView/SceneGraphicsView objects;
# Qt6 splits QOpenGLWidget into its own libQt6OpenGLWidgets.so)
if(NOT TARGET Qt6::OpenGLWidgets AND EXISTS "${QT6_LIB_DIR}/libQt6OpenGLWidgets.so.6")
add_library(Qt6::OpenGLWidgets SHARED IMPORTED)
set_target_properties(Qt6::OpenGLWidgets PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6OpenGLWidgets.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtWidgets;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui;Qt6::Widgets"
)
message(STATUS "Manually configured Qt6 OpenGLWidgets target")
endif()
# Qt6::Sql - create manual target if not found
if(NOT TARGET Qt6::Sql AND EXISTS "${QT6_LIB_DIR}/libQt6Sql.so.6")
add_library(Qt6::Sql SHARED IMPORTED)
set_target_properties(Qt6::Sql PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Sql.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtSql;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core"
)
message(STATUS "Manually configured Qt6 Sql target")
endif()
# Qt6::Xml - create manual target if not found
if(NOT TARGET Qt6::Xml AND EXISTS "${QT6_LIB_DIR}/libQt6Xml.so.6")
add_library(Qt6::Xml SHARED IMPORTED)
set_target_properties(Qt6::Xml PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Xml.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtXml;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core"
)
message(STATUS "Manually configured Qt6 Xml target")
endif()
# Qt6::Network - create manual target if not found
if(NOT TARGET Qt6::Network AND EXISTS "${QT6_LIB_DIR}/libQt6Network.so.6")
add_library(Qt6::Network SHARED IMPORTED)
set_target_properties(Qt6::Network PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Network.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtNetwork;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core"
)
message(STATUS "Manually configured Qt6 Network target")
endif()
# Qt6::Test - create manual target if not found
if(NOT TARGET Qt6::Test AND EXISTS "${QT6_LIB_DIR}/libQt6Test.so.6")
add_library(Qt6::Test SHARED IMPORTED)
set_target_properties(Qt6::Test PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Test.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtTest;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core"
)
message(STATUS "Manually configured Qt6 Test target")
endif()
# Qt6::Multimedia - create manual target if not found
if(NOT TARGET Qt6::Multimedia AND EXISTS "${QT6_LIB_DIR}/libQt6Multimedia.so.6")
add_library(Qt6::Multimedia SHARED IMPORTED)
set_target_properties(Qt6::Multimedia PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Multimedia.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtMultimedia;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui"
)
message(STATUS "Manually configured Qt6 Multimedia target")
endif()
# Stub Qt6::Multimedia target if not available (needed by OscSystemGuiPlugin, etc.)
if(NOT TARGET Qt6::Multimedia)
add_library(Qt6::Multimedia INTERFACE IMPORTED)
set_target_properties(Qt6::Multimedia PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "QT_NO_MULTIMEDIA"
)
message(STATUS "Created stub target for Qt6::Multimedia (library not available)")
endif()
# Qt6::Svg - create manual target if not found. Also require the headers:
# the container can ship the runtime library (libqt6svg6 via Recommends)
# without qt6-svg-dev, and an imported target with a non-existent
# INTERFACE_INCLUDE_DIRECTORIES entry fails the CMake generate step for
# every Svg consumer. Without headers the stub below is used instead.
if(NOT TARGET Qt6::Svg AND EXISTS "${QT6_LIB_DIR}/libQt6Svg.so.6" AND EXISTS "${QT6_INC_DIR}/QtSvg")
add_library(Qt6::Svg SHARED IMPORTED)
set_target_properties(Qt6::Svg PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6Svg.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtSvg;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui"
)
message(STATUS "Manually configured Qt6 Svg target")
endif()
# Stub Qt6::Svg target if not available (needed by various plugins)
if(NOT TARGET Qt6::Svg)
add_library(Qt6::Svg INTERFACE IMPORTED)
message(STATUS "Created stub target for Qt6::Svg (library not available)")
endif()
# Qt6::SerialPort - create manual target if not found
if(NOT TARGET Qt6::SerialPort AND EXISTS "${QT6_LIB_DIR}/libQt6SerialPort.so.6")
add_library(Qt6::SerialPort SHARED IMPORTED)
set_target_properties(Qt6::SerialPort PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6SerialPort.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtSerialPort;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core"
)
message(STATUS "Manually configured Qt6 SerialPort target")
endif()
# Stub Qt6::SerialPort target if not available (needed by TrainingAreaBaseOC)
if(NOT TARGET Qt6::SerialPort)
add_library(Qt6::SerialPort INTERFACE IMPORTED)
set_target_properties(Qt6::SerialPort PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "QT_NO_SERIALPORT"
)
message(STATUS "Created stub target for Qt6::SerialPort (library not available)")
endif()
# Qt6::WebEngineCore - real imported target if the library exists (stub below otherwise).
# The stub carries no library, so targets linking it (e.g. SmoSystemMonitorGuiPlugin)
# fail --no-undefined on QWebEngine* symbols.
if(NOT TARGET Qt6::WebEngineCore AND EXISTS "${QT6_LIB_DIR}/libQt6WebEngineCore.so.6")
add_library(Qt6::WebEngineCore SHARED IMPORTED)
set_target_properties(Qt6::WebEngineCore PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6WebEngineCore.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtWebEngineCore;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui"
)
message(STATUS "Manually configured Qt6 WebEngineCore target")
endif()
# Qt6::WebEngineWidgets - real imported target if the library exists.
if(NOT TARGET Qt6::WebEngineWidgets AND EXISTS "${QT6_LIB_DIR}/libQt6WebEngineWidgets.so.6")
add_library(Qt6::WebEngineWidgets SHARED IMPORTED)
set_target_properties(Qt6::WebEngineWidgets PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6WebEngineWidgets.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtWebEngineWidgets;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui;Qt6::Widgets;Qt6::WebEngineCore"
)
message(STATUS "Manually configured Qt6 WebEngineWidgets target")
endif()
# Stub Qt6::WebEngineCore target if not available (needed by thp_viewer)
if(NOT TARGET Qt6::WebEngineCore)
add_library(Qt6::WebEngineCore INTERFACE IMPORTED)
set_target_properties(Qt6::WebEngineCore PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "QT_NO_WEBENGINE"
)
message(STATUS "Created stub target for Qt6::WebEngineCore (library not available)")
endif()
# Stub Qt6::WebEngineWidgets target if not available (needed by thp_viewer)
if(NOT TARGET Qt6::WebEngineWidgets)
add_library(Qt6::WebEngineWidgets INTERFACE IMPORTED)
set_target_properties(Qt6::WebEngineWidgets PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "QT_NO_WEBENGINE"
)
message(STATUS "Created stub target for Qt6::WebEngineWidgets (library not available)")
endif()
# Stub KDReports::KDReports target if not available (needed by LtsReportDisplay)
# UNKNOWN (not INTERFACE) so FindKDReports.cmake can upgrade it with a real
# IMPORTED_LOCATION; an INTERFACE imported target ignores IMPORTED_LOCATION.
if(NOT TARGET KDReports::KDReports)
add_library(KDReports::KDReports UNKNOWN IMPORTED)
set_target_properties(KDReports::KDReports PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "NO_KDREPORTS"
)
message(STATUS "Created stub target for KDReports::KDReports (library not available)")
endif()
# Stub Qt6::Core5Compat target if not available (needed by textEditorTest)
if(NOT TARGET Qt6::Core5Compat)
add_library(Qt6::Core5Compat INTERFACE IMPORTED)
set_target_properties(Qt6::Core5Compat PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "QT_NO_CORE5COMPAT"
)
message(STATUS "Created stub target for Qt6::Core5Compat (library not available)")
endif()
# Qt6::WebSockets - create manual target if not found (the container's Qt6
# discovery takes the minimal path, so find_package never creates the
# component targets). The migrated FileManagement service (THP script
# server) needs the real module.
if(NOT TARGET Qt6::WebSockets AND EXISTS "${QT6_LIB_DIR}/libQt6WebSockets.so.6")
add_library(Qt6::WebSockets SHARED IMPORTED)
set_target_properties(Qt6::WebSockets PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6WebSockets.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtWebSockets;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Network"
)
set(QT6_WEBSOCKETS_REAL_FOUND TRUE)
message(STATUS "Manually configured Qt6 WebSockets target")
endif()
# Stub Qt6::WebSockets target if not available (needed by LtsWebSocket, httq, etc.)
if(NOT TARGET Qt6::WebSockets)
add_library(Qt6::WebSockets INTERFACE IMPORTED)
set_target_properties(Qt6::WebSockets PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "QT_NO_WEBSOCKETS"
)
message(STATUS "Created stub target for Qt6::WebSockets (library not available)")
endif()
# Qt6::PrintSupport - create manual target if not found
if(NOT TARGET Qt6::PrintSupport AND EXISTS "${QT6_LIB_DIR}/libQt6PrintSupport.so.6")
add_library(Qt6::PrintSupport SHARED IMPORTED)
set_target_properties(Qt6::PrintSupport PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6PrintSupport.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtPrintSupport;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui;Qt6::Widgets"
)
message(STATUS "Manually configured Qt6 PrintSupport target")
endif()
# Stub Qt6::PrintSupport target if not available (needed by textEditorTest, thp_viewer)
if(NOT TARGET Qt6::PrintSupport)
add_library(Qt6::PrintSupport INTERFACE IMPORTED)
set_target_properties(Qt6::PrintSupport PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "QT_NO_PRINTSUPPORT"
)
message(STATUS "Created stub target for Qt6::PrintSupport (library not available)")
endif()
# Qt6::OpenGL - create manual target if not found
if(NOT TARGET Qt6::OpenGL AND EXISTS "${QT6_LIB_DIR}/libQt6OpenGL.so.6")
add_library(Qt6::OpenGL SHARED IMPORTED)
set_target_properties(Qt6::OpenGL PROPERTIES
IMPORTED_LOCATION "${QT6_LIB_DIR}/libQt6OpenGL.so.6"
INTERFACE_INCLUDE_DIRECTORIES "${QT6_INC_DIR}/QtOpenGL;${QT6_INC_DIR}"
INTERFACE_LINK_LIBRARIES "Qt6::Core;Qt6::Gui"
)
message(STATUS "Manually configured Qt6 OpenGL target")
endif()
# Stub Qt6::OpenGL target if not available (needed by PwsGuiPlugin)
if(NOT TARGET Qt6::OpenGL)
add_library(Qt6::OpenGL INTERFACE IMPORTED)
set_target_properties(Qt6::OpenGL PROPERTIES
INTERFACE_COMPILE_DEFINITIONS "QT_NO_OPENGL"
)
message(STATUS "Created stub target for Qt6::OpenGL (library not available)")
endif()
# Set variable for legacy code that uses ${Qt6_WebSockets} — subdirectory
# CMakeLists contain `set(Qt6_WebSockets ${Qt6_WebSockets})` optional-guard
# no-ops that keep this root-scope value.
if(TARGET Qt6::WebSockets)
set(Qt6_WebSockets Qt6::WebSockets)
endif()
# The real Qt6 WebSockets module is available (either via find_package or the
# manual import above): enable the real websocket code paths in httq,
# LtsWebSocket and the migrated services (they check this macro; without it
# they fall back to websocket-less operation).
if(Qt6WebSockets_FOUND OR QT6_WEBSOCKETS_REAL_FOUND)
add_compile_definitions(QT6_WEBSOCKETS_AVAILABLE)
endif()
MESSAGE(STATUS "Qt version is ${Qt6Core_VERSION}, GUI available: ${QT6_GUI_AVAILABLE}")
#
# RTI Connext DDS - manuelle Konfiguration da keine CMake Config Files vorhanden
#
IF(BUILD_RTI)
# Support environment variable override, otherwise use relative path from repo root
IF(DEFINED ENV{DDS_PATH})
SET(RTI_INSTALL_DIR "$ENV{DDS_PATH}" CACHE PATH "RTI Connext DDS installation directory")
ELSE()
# In Docker container: /workspace/external/rti_connext_dds-7.7.0
# On host: ${CMAKE_SOURCE_DIR}/../../../external/rti_connext_dds-7.7.0
IF(EXISTS "/workspace/external/rti_connext_dds-7.7.0")
SET(RTI_INSTALL_DIR "/workspace/external/rti_connext_dds-7.7.0" CACHE PATH "RTI Connext DDS installation directory")
ELSEIF(EXISTS "${CMAKE_SOURCE_DIR}/../../../external/rti_connext_dds-7.7.0")
SET(RTI_INSTALL_DIR "${CMAKE_SOURCE_DIR}/../../../external/rti_connext_dds-7.7.0" CACHE PATH "RTI Connext DDS installation directory")
ELSE()
SET(RTI_INSTALL_DIR "/opt/RTI" CACHE PATH "RTI Connext DDS installation directory")
ENDIF()
ENDIF()
# Also set RTI_DIR for FindRTI.cmake compatibility (used by subdirectories)
SET(RTI_DIR "${RTI_INSTALL_DIR}" CACHE PATH "RTI base path" FORCE)
IF(EXISTS "${RTI_INSTALL_DIR}")
SET(RTI_LIB_DIR "${RTI_INSTALL_DIR}/lib/x64Linux4gcc8.5.0")
SET(RTI_INCLUDE_DIR "${RTI_INSTALL_DIR}/include/ndds/hpp")
# RTI hat vier Include-Pfade:
# - include/ für ndds/... und andere Top-Level Headers (z.B. ndds/ndds_config_common.h)
# - include/ndds/ für osapi/... Headers (z.B. osapi/osapi_platform.h)
# - include/ndds/hpp für C++ Headers (dds/..., rti/...)
# - include/rti für rti/... Headers
SET(RTI_INCLUDE_DIRS
"${RTI_INSTALL_DIR}/include"
"${RTI_INSTALL_DIR}/include/ndds"
"${RTI_INSTALL_DIR}/include/ndds/hpp"
"${RTI_INSTALL_DIR}/include/rti"
)
# RTI Include-Pfade global hinzufügen (auch für Tests die keine RTI Libraries linken)
INCLUDE_DIRECTORIES(${RTI_INCLUDE_DIRS})
# RTI Include-Pfade auch an MOC weitergeben (für Q_OBJECT Header mit RTI Types)
SET(CMAKE_AUTOMOC_INCLUDE_DIRECTORIES ${CMAKE_AUTOMOC_INCLUDE_DIRECTORIES} ${RTI_INCLUDE_DIRS})
# The generated <svc>_topic_type_plugin.h / <svc>_record_replay_plugin.h
# headers use Q_INTERFACES(DDSGeneric::TopicTypePlugin), so moc must see
# the Q_DECLARE_INTERFACE in Lts/DDS/... (resolved through the Lts include
# root). Without this path every <svc>TopicTypePlugin fails with
# "Undefined interface" even though the compiler sees the header.
SET(CMAKE_AUTOMOC_INCLUDE_DIRECTORIES ${CMAKE_AUTOMOC_INCLUDE_DIRECTORIES} ${CMAKE_SOURCE_DIR}/Lts)
# The ElevationMapManager stub header (include/Viewer/SituationMap/ElevationMap/)
# lives apart from its source (src/...), so moc needs its directory explicitly.
# NOTE: this must be set at root scope - subdir-scope appends do not reach
# the AutogenInfo MOC_INCLUDES.
SET(CMAKE_AUTOMOC_INCLUDE_DIRECTORIES ${CMAKE_AUTOMOC_INCLUDE_DIRECTORIES} ${CMAKE_SOURCE_DIR}/include/Viewer/SituationMap/ElevationMap)
# The migrated Projects declare Q_INTERFACES(ProjectPlugin::Plugin) and include
# <PluginInterfaces/project_plugin_interface.h>. That include dir
# (Lts/Common/PluginInterfaces/..) is only a target-level PUBLIC include of
# ProjectPluginInterface and is NOT part of the global include_directories that
# reach the AutogenInfo MOC_INCLUDES, so moc fails with "Undefined interface".
# Add the Lts/Common root explicitly (mirrors the Lts append above) so moc can
# resolve the interface. Must be set at root scope - subdir appends do not
# reach the AutogenInfo MOC_INCLUDES.
SET(CMAKE_AUTOMOC_INCLUDE_DIRECTORIES ${CMAKE_AUTOMOC_INCLUDE_DIRECTORIES} ${CMAKE_SOURCE_DIR}/Lts/Common)
# The TrainingAreaBase tab plugins (tabPluginHla / tabPluginWlsTetra /
# tabPluginDebugJsonDir / ...) declare Q_INTERFACES(TrainingAreaBase::Plugin::Plugin)
# and include <TrainingAreaBase/tab_plugin_interface.h>. That include dir
# (Lts/Proxies) is only a target-level INTERFACE include of tabPluginInterface and
# is NOT part of the global include_directories that reach the AutogenInfo
# MOC_INCLUDES, so moc fails with "Undefined interface". Add the Lts/Proxies root
# explicitly so moc can resolve the interface. Must be set at root scope - subdir
# appends do not reach the AutogenInfo MOC_INCLUDES.
SET(CMAKE_AUTOMOC_INCLUDE_DIRECTORIES ${CMAKE_AUTOMOC_INCLUDE_DIRECTORIES} ${CMAKE_SOURCE_DIR}/Lts/Proxies)
# Designer plugins (ltswidgetsplugin) declare Q_INTERFACES(QDesignerCustomWidgetInterface)
# and include <QtUiPlugin/QDesignerCustomWidgetInterface>. That interface's
# Q_DECLARE_INTERFACE lives in the Qt6 QtUiPlugin module, which moc cannot resolve
# without the Qt6 parent include dir (it is only a target-level INTERFACE include of
# Qt6::UiTools and does not reach the global AutogenInfo MOC_INCLUDES). Add Qt6::Core's
# interface include dirs (which expose the <QtModule>/header root) so moc finds the
# interface. Must be set at root scope.
get_target_property(_qt6_autmoc_incs Qt6::Core INTERFACE_INCLUDE_DIRECTORIES)
SET(CMAKE_AUTOMOC_INCLUDE_DIRECTORIES ${CMAKE_AUTOMOC_INCLUDE_DIRECTORIES} ${_qt6_autmoc_incs})
# IMPORTED Targets für RTI Libraries erstellen
# Debug und Release Varianten korrekt konfigurieren
FOREACH(lib nddsc nddscore nddscpp nddscpp2 nddsctesthelpers)
ADD_LIBRARY(RTI::${lib} SHARED IMPORTED)
# Debug Library
IF(EXISTS "${RTI_LIB_DIR}/lib${lib}d.so")
SET_TARGET_PROPERTIES(RTI::${lib} PROPERTIES
IMPORTED_LOCATION_DEBUG "${RTI_LIB_DIR}/lib${lib}d.so"
)
ENDIF()
# Release Library
IF(EXISTS "${RTI_LIB_DIR}/lib${lib}.so")
SET_TARGET_PROPERTIES(RTI::${lib} PROPERTIES
IMPORTED_LOCATION_RELEASE "${RTI_LIB_DIR}/lib${lib}.so"
IMPORTED_LOCATION_RELWITHDEBINFO "${RTI_LIB_DIR}/lib${lib}.so"
IMPORTED_LOCATION_MINSIZEREL "${RTI_LIB_DIR}/lib${lib}.so"
)
ENDIF()
# Include Verzeichnisse für alle Varianten
# RTI_UNIX required for basic types (RTI_INT32, RTI_UINT32, etc.)
# RTI_POSIX_THREADS required for pthread support
SET_TARGET_PROPERTIES(RTI::${lib} PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${RTI_INCLUDE_DIRS}"
INTERFACE_COMPILE_DEFINITIONS "RTI_LINUX;RTI_UNIX;RTI_POSIX_THREADS"
)
ENDFOREACH()
MESSAGE(STATUS "RTI Connext DDS found at: ${RTI_INSTALL_DIR}")
MESSAGE(STATUS "RTI Libraries: ${RTI_LIB_DIR}")
MESSAGE(STATUS "RTI Platform: RTI_LINUX")
ELSE()
MESSAGE(WARNING "RTI Connext DDS not found at: ${RTI_INSTALL_DIR}, BUILD_RTI will fail")
ENDIF()
ENDIF(BUILD_RTI)
# Alias Targets für RTI Libraries (für Abwärtskompatibilität)
# Ermöglicht Verwendung von "ddscore" statt "RTI::nddscore" in CMakeLists.txt Files
# HINWEIS: ddscore, ddsftc, ddsfts, ddsconnector werden von Lts/DDS Modulen als echte Targets erstellt
# Daher hier KEINE ALIAS für diese Targets erstellen um Kollisionen zu vermeiden
IF(BUILD_RTI)
# BUILD_RTI=ON: Targets werden von Lts/DDS/Core/CMakeLists.txt erstellt - hier keine Stubs!
# Alias-Typen werden später erstellt, wenn RTI:: Targets verfügbar sind
IF(TARGET RTI::nddsc)
ADD_LIBRARY(ddsc ALIAS RTI::nddsc)
# ddscore wird von Lts/DDS/Core/CMakeLists.txt als echtes Target erstellt - kein Alias hier!
ADD_LIBRARY(ddscpp2 ALIAS RTI::nddscpp2)
# Optionale Targets nur als ALIAS erstellen wenn verfügbar (RTI 7.x hat nicht alle Legacy-Bibliotheken)
IF(TARGET RTI::nddscpp)
ADD_LIBRARY(ddscpp ALIAS RTI::nddscpp)
ENDIF()
IF(TARGET RTI::nddsctesthelpers)
ADD_LIBRARY(nddsctesthelpers ALIAS RTI::nddsctesthelpers)
ENDIF()
ENDIF()
# HINWEIS: ddsftc, ddsfts, ddsconnector werden von Lts/DDS/FTC Modulen als INTERFACE Targets erstellt
# Hier KEINE ALIAS erstellen um Target-Kollisionen zu vermeiden
ELSE()
# BUILD_RTI=OFF: Leere Interface-Libraries als Platzhalter
ADD_LIBRARY(ddsc INTERFACE)
ADD_LIBRARY(ddscore INTERFACE)
ADD_LIBRARY(ddscpp INTERFACE)
ADD_LIBRARY(ddscpp2 INTERFACE)
ADD_LIBRARY(nddsctesthelpers INTERFACE)
# HINWEIS: ddsftc, ddsfts, ddsconnector werden von Lts/DDS/FTC Modulen als INTERFACE Targets erstellt
# Hier KEINE Platzhalter erstellen um Target-Kollisionen zu vermeiden
ENDIF(BUILD_RTI)
ADD_DEFINITIONS(-DQT_USE_QSTRINGBUILDER)
ADD_DEFINITIONS(-DQT_NO_CAST_TO_ASCII)
ADD_DEFINITIONS(-DQT_NO_CAST_FROM_ASCII)
ADD_DEFINITIONS(-DQT_NO_URL_CAST_FROM_STRING)
ADD_DEFINITIONS(-DQT_DEPRECATED_WARNINGS)
ADD_DEFINITIONS(-DQT_NO_CAST_FROM_BYTEARRAY)
#ADD_DEFINITIONS(-DQT_NO_DEPRECATED)
ADD_DEFINITIONS(-DQT_DISABLE_DEPRECATED_BEFORE=0x050900)
ADD_DEFINITIONS(-DQT_NO_FOREACH)
IF(NOT WIN32)
ADD_DEFINITIONS(-DQT_STRICT_ITERATORS)
ENDIF()
#
# Ein paar NGL-spezifische Macros
#
INCLUDE(NGLMacros)
INCLUDE(MacroCodeGenIdl)
#
# Projektspezifische Einstellungen?
#
NGL_INSTALL(SV AAR WS FILES lts-cc.conf DESTINATION . RENAME lts-cc.conf.distrib)
OPTION(ETS_MODE "Build for ETS (No B-Contamination etc)" OFF)
IF(ETS_MODE)
ADD_DEFINITIONS(-DETS_MODE)
ENDIF()
OPTION(TABLET_MODE "Build for TABLET " OFF)
IF(TABLET_MODE)
ADD_DEFINITIONS(-DTABLET_MODE)
ENDIF()
OPTION(GUEZ_MODE "Build for GUEZ " ON)
IF(GUEZ_MODE)
ADD_DEFINITIONS(-DGUEZ_MODE)
ENDIF()
#
# Doxygen
#
INCLUDE(DoxygenMacros)
IF(NOT DOXYGEN_OUT_DIR)
SET(DOXYGEN_OUT_DIR ${CMAKE_BINARY_DIR}/doxygen)
ENDIF()
ADD_DOXYGEN_TARGET(TDS ${CMAKE_SOURCE_DIR}/doxygen/Doxyfile.in ${CMAKE_BINARY_DIR}/Doxyfile
${CMAKE_SOURCE_DIR}/doxygen/rheinmetall_defence_logo.jpg
${DOXYGEN_OUT_DIR})
IF(NOT DOXYGEN_OUT_DIR_2025)
SET(DOXYGEN_OUT_DIR_2025 ${CMAKE_BINARY_DIR}/doxygen2025)
ENDIF()
ADD_DOXYGEN_TARGET(TDS2025 ${CMAKE_SOURCE_DIR}/doxygen/Doxyfile2025.in ${CMAKE_BINARY_DIR}/Doxyfile
${CMAKE_SOURCE_DIR}/doxygen/rheinmetall_defence_logo.jpg
${DOXYGEN_OUT_DIR_2025})
#
# Compilerflags
#
IF(WIN32)
ADD_DEFINITIONS(-DWIN32 -D_USE_MATH_DEFINES -D_WIN32_WINNT=0x0501 -DUNICODE)
ELSE()
ADD_DEFINITIONS(-D_LINUX)
ENDIF()
IF(MSVC)
# C4250: 'class1' : inherits 'class2::member' via dominance
# C4251: 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
# C4290: C++ exception specification ignored except to indicate a function is not __declspec(nothrow)
# C4496: 'function': was declared deprecated
# C4267: 'var' : conversion from 'size_t' to 'type', possible loss of data
ADD_DEFINITIONS(-wd4250
-wd4251
-wd4290
-wd4496
-wd4267
-D_CRT_SECURE_NO_DEPRECATE
-D_CRT_NONSTDC_NO_DEPRECATE
-D_SCL_SECURE_NO_WARNINGS
-D_WINSOCK_DEPRECATED_NO_WARNINGS
/bigobj
)
# komplette Programmoptimierung
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /MP")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
# .pdb - Datei nicht gefunden
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /IGNORE:4099")
SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /IGNORE:4099")
# min() und max() nicht als Macros
ADD_DEFINITIONS(-DNOMINMAX)
SET(CMAKE_MSVCIDE_RUN_PATH "" CACHE PATH "Run path to use when starting programs from MSVC")
ENDIF()
IF(UNIX)
# Alle Warnungen aktivieren
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra -Wmissing-include-dirs")
# disable
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-overloaded-virtual")
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
IF(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8.0)
MESSAGE(FATAL_ERROR "gcc 4.8 or higher is required to build TDS: ${CMAKE_CXX_COMPILER_VERSION}")
ENDIF()
IF(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.9.99)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-strict-aliasing")
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-attribute=const")
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-final-types")
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-final-methods")
# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wsuggest-override")
ENDIF()
ENDIF()
ENDIF()
OPTION(USE_IPO "Use interprocedural optimizations (cmake 3.9 or higher required)" OFF)
IF (USE_IPO AND CMAKE_VERSION VERSION_GREATER 3.8.9)
INCLUDE(CheckIPOSupported)
check_ipo_supported(RESULT result OUTPUT output)
IF(result)
SET(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
ELSE()
MESSAGE(WARNING "IPO is not supported: ${output}")
ENDIF()
ENDIF()
OPTION(USE_ASAN "Use Address Sanitizer (current Clang only)" OFF)
IF (USE_ASAN)
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
MESSAGE(STATUS "enable Address Sanitizer with Clang (is: ${CMAKE_CXX_COMPILER_ID})")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-optimize-sibling-calls -fsanitize-address-use-after-scope -fno-omit-frame-pointer -g -O1")
ELSE()
MESSAGE(STATUS "Address Sanitizer only supported with Clang (is: ${CMAKE_CXX_COMPILER_ID})")
ENDIF()
ENDIF(USE_ASAN)
OPTION(USE_UBSAN "Use UndefinedBehavior Sanitizer (current Clang only)" OFF)
IF (USE_UBSAN)
IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined")
ELSE()
MESSAGE(STATUS "UndefinedBehavior only supported with Clang (is: ${CMAKE_CXX_COMPILER_ID})")
ENDIF()
ENDIF(USE_UBSAN)
OPTION(BUILD_RPM "Build a RPM - install script in scripts subdir" OFF)
# Build component options for NGL_ADD_LIBRARY
OPTION(BUILD_ALL "Build all components" ON)
OPTION(BUILD_SV "Build SV component" ON)
OPTION(BUILD_WS "Build WS component" ON)
OPTION(BUILD_AAR "Build AAR component" ON)
OPTION(BUILD_TOOLSWS "Build TOOLSWS component" ON)
OPTION(BUILD_TOOLSSV "Build TOOLSSV component" ON)
OPTION(BUILD_HLA "Build HLA component" ON)
# If BUILD_ALL is ON, enable all individual component flags
IF(BUILD_ALL)
SET(BUILD_SV ON CACHE BOOL "Build SV component" FORCE)
SET(BUILD_WS ON CACHE BOOL "Build WS component" FORCE)
SET(BUILD_AAR ON CACHE BOOL "Build AAR component" FORCE)
SET(BUILD_TOOLSWS ON CACHE BOOL "Build TOOLSWS component" FORCE)
SET(BUILD_TOOLSSV ON CACHE BOOL "Build TOOLSSV component" FORCE)
SET(BUILD_HLA ON CACHE BOOL "Build HLA component" FORCE)
ENDIF()
IF(BUILD_RPM)
ADD_SUBDIRECTORY(scripts)
ELSE()
ADD_DEFINITIONS(-DLTS_DEBUG)
ENDIF()
IF (NOT DEFINED _pname)
IF(GUEZ_MODE)
SET (_pname "guez")
ADD_DEFINITIONS(-DPROJECTBUILD="guez")
MESSAGE(STATUS "NO ProjectName givin! BUT GUEZ_MODE set PROJECTBUILD to guez")
ELSE()
MESSAGE(WARNING "NO ProjectName givin! Can't install coresponding lts-cc.conf! and PROJECTBUILD is empty")
ADD_DEFINITIONS(-DPROJECTBUILD="")
ENDIF()
ELSE()
MESSAGE(STATUS "ProjectName givin! PROJECTBUILD is ${_pname} ")
ADD_DEFINITIONS(-DPROJECTBUILD=\"${_pname}\")
ENDIF()
#
# DDS benoetigt zwingend RTI
#
FIND_PACKAGE(RTI QUIET)
if(NOT RTI_FOUND)
message(WARNING "RTI not found; creating placeholder RTI::* imported targets to allow configure without RTI installation")
set(_rti_libs nddscore nddsc nddscpp2 rtiroutingservice)
foreach(_lib ${_rti_libs})
if(NOT TARGET RTI::${_lib})
add_library(RTI::${_lib} UNKNOWN IMPORTED)
set_property(TARGET RTI::${_lib} PROPERTY INTERFACE_INCLUDE_DIRECTORIES "")
endif()
endforeach()
endif()
# Respect MIGRATE_MODULE: when set to a relative path (e.g. "Lts/Common"), only add
# the top-level subdirectories required to configure/build that module. This allows
# per-module migration builds via -DMIGRATE_MODULE=<path>.
if(NOT DEFINED MIGRATE_MODULE)
set(MIGRATE_MODULE "" CACHE STRING "If set, only add subdirectories covering this module (path relative to repo root)")
endif()
# Add only guarded subdirectories
NGL_ADD_SUBDIR_GUARDED(TetraIF)
NGL_ADD_SUBDIR_GUARDED(Z/src)
# Services are included before plugins via Lts/CMakeLists.txt (LTS_SUBDIRS order)
NGL_ADD_SUBDIR_GUARDED(Lts)
# Add migration tests - skip when MIGRATE_MODULE targets specific Lts modules (tests need full codebase)
# MUST be after Lts configuration so tests can access Lts targets (LtsTimelineClassic, codegen_base, etc.)
if(NOT DEFINED MIGRATE_MODULE OR MIGRATE_MODULE STREQUAL "" OR MIGRATE_MODULE STREQUAL "tests")
ADD_SUBDIRECTORY(tests)
else()
message(STATUS "MIGRATE_MODULE=${MIGRATE_MODULE} - skipping tests (need full codebase)")
endif()
# TrainingAreaBase is included via Lts/Proxies when Lts is processed
# Special-case: when migrating TetraIF, also include ProjectDataManagement so generated headers
# and internal logger target are available in the same build tree for TetraIF dependents.
if(DEFINED MIGRATE_MODULE AND MIGRATE_MODULE STREQUAL "TetraIF")
message(STATUS "Including helper modules for TetraIF migration: Lts/Plugins/ProjectDataManagement")
# Services already included above when BUILD_RTI=ON
add_subdirectory(Lts/Plugins/ProjectDataManagement)
endif()
# at last, to make sure we get all targets in NGL_TS_TARGETS property
NGL_ADD_SUBDIR_GUARDED(translations)
#-----------------------------------------------------------------------------------------------------
OPTION(BUILD_QAV "Build script for local QAV analysis" OFF)
IF (BUILD_QAV)
ADD_SUBDIRECTORY(qav)
ENDIF()