aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Vanbesien <tvanbesi@proton.me>2026-02-23 10:15:19 +0100
committerThomas Vanbesien <tvanbesi@proton.me>2026-02-23 10:15:19 +0100
commita132c560437fe09714c43aa2a8c52a529a95e32b (patch)
tree18a2a72be19f86d5fbb16bebcbee2acd77232f0b
parent547f2830beb89c4c5152959fe9f852e5237f79ad (diff)
downloadBobinkQtOpcUa-a132c560437fe09714c43aa2a8c52a529a95e32b.tar.gz
BobinkQtOpcUa-a132c560437fe09714c43aa2a8c52a529a95e32b.zip
Add Windows support to build system and improve dep detection
Use platform-specific library names for skip detection (.so vs .lib). Find qt-cmake on Windows (qt-cmake.bat). Set CMAKE_BUILD_TYPE on dep builds. Use explicit Qt6*_DIR variables instead of fragile QT_ADDITIONAL_PACKAGES_PREFIX_PATH for finding locally-built QtOpcUa. On Windows: copy DLLs to bin/ (no RPATH), point to system OpenSSL. On Linux: keep existing symlink approach for open62541 libs.
-rw-r--r--CMakeLists.txt11
-rw-r--r--cmake/BuildDeps.cmake54
2 files changed, 50 insertions, 15 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6a9265f..f35b498 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8,9 +8,14 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# Build external dependencies (open62541, qtopcua) if not already built
include(cmake/BuildDeps.cmake)
-# Tell Qt's find_package to also look in our local QtOpcUa install for
-# components (Qt6Config.cmake only searches its own install dir by default).
-list(PREPEND QT_ADDITIONAL_PACKAGES_PREFIX_PATH "${QTOPCUA_INSTALL_DIR}")
+# Point CMake directly at the locally-built QtOpcUa packages.
+# Qt6Config.cmake uses NO_DEFAULT_PATH when searching for components, so
+# QT_ADDITIONAL_PACKAGES_PREFIX_PATH should work but is fragile in practice
+# (Qt Creator can interfere). Setting <Package>_DIR is always checked first.
+set(Qt6OpcUa_DIR "${QTOPCUA_INSTALL_DIR}/lib/cmake/Qt6OpcUa")
+set(Qt6OpcUaPrivate_DIR "${QTOPCUA_INSTALL_DIR}/lib/cmake/Qt6OpcUaPrivate")
+set(Qt6OpcUaTools_DIR "${QTOPCUA_INSTALL_DIR}/lib/cmake/Qt6OpcUaTools")
+set(Qt6DeclarativeOpcua_DIR "${QTOPCUA_INSTALL_DIR}/lib/cmake/Qt6DeclarativeOpcua")
list(PREPEND CMAKE_PREFIX_PATH "${OPEN62541_INSTALL_DIR}")
find_package(Qt6 6.10.2 REQUIRED COMPONENTS Core Qml Quick OpcUa)
diff --git a/cmake/BuildDeps.cmake b/cmake/BuildDeps.cmake
index 890da57..b402510 100644
--- a/cmake/BuildDeps.cmake
+++ b/cmake/BuildDeps.cmake
@@ -32,7 +32,14 @@ endif()
# ======================================
# open62541
# ======================================
-if(NOT EXISTS "${OPEN62541_INSTALL_DIR}/lib/libopen62541.so")
+
+if(WIN32)
+ set(open62541_lib "open62541.lib")
+else()
+ set(open62541_lib "libopen62541.so")
+endif()
+
+if(NOT EXISTS "${OPEN62541_INSTALL_DIR}/lib/${open62541_lib}")
message(STATUS "Configuring open62541 in ${OPEN62541_BUILD_DIR}...")
set(_cmd
@@ -43,6 +50,7 @@ if(NOT EXISTS "${OPEN62541_INSTALL_DIR}/lib/libopen62541.so")
"${OPEN62541_BUILD_DIR}"
-G
Ninja
+ -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX=${OPEN62541_INSTALL_DIR}
-DBUILD_SHARED_LIBS=ON
-DUA_ENABLE_ENCRYPTION=OPENSSL
@@ -77,9 +85,15 @@ endif()
# QtOpcUa
# ======================================
-find_program(QT_CMAKE_COMMAND bin/qt-cmake REQUIRED)
+find_program(QT_CMAKE_COMMAND NAMES qt-cmake qt-cmake.bat PATHS ${CMAKE_PREFIX_PATH} PATH_SUFFIXES bin REQUIRED)
-if(NOT EXISTS "${QTOPCUA_INSTALL_DIR}/lib/libQt6OpcUa.so")
+if(WIN32)
+ set(qtopcua_lib "Qt6OpcUa.lib")
+else()
+ set(qtopcua_lib "libQt6OpcUa.so")
+endif()
+
+if(NOT EXISTS "${QTOPCUA_INSTALL_DIR}/lib/${qtopcua_lib}")
message(STATUS "Configuring qtopcua in ${QTOPCUA_BUILD_DIR}...")
set(_cmd
@@ -90,10 +104,15 @@ if(NOT EXISTS "${QTOPCUA_INSTALL_DIR}/lib/libQt6OpcUa.so")
"${QTOPCUA_BUILD_DIR}"
-G
Ninja
+ -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX=${QTOPCUA_INSTALL_DIR}
# Use our locally-built open62541, not the bundled copy
-DINPUT_open62541=system
-DCMAKE_PREFIX_PATH=${OPEN62541_INSTALL_DIR})
+ if(WIN32)
+ # Install with: winget install ShiningLight.OpenSSL.Dev
+ list(APPEND _cmd -DOPENSSL_ROOT_DIR:PATH="C:/Program Files/OpenSSL-Win64")
+ endif()
execute_process(COMMAND ${_cmd} RESULT_VARIABLE _result)
if(_result)
list(JOIN _cmd " " _cmd_str)
@@ -120,12 +139,23 @@ else()
message(STATUS "qtopcua already built, skipping")
endif()
-# The QtOpcUa backend plugin uses $ORIGIN-relative RUNPATH that resolves to
-# qtopcua-install/lib/. Symlink the open62541 libs there so dlopen finds them.
-file(GLOB _open62541_libs "${OPEN62541_INSTALL_DIR}/lib/libopen62541*")
-foreach(_lib ${_open62541_libs})
- get_filename_component(_name ${_lib} NAME)
- if(NOT EXISTS "${QTOPCUA_INSTALL_DIR}/lib/${_name}")
- file(CREATE_LINK ${_lib} "${QTOPCUA_INSTALL_DIR}/lib/${_name}" SYMBOLIC)
- endif()
-endforeach()
+if (WIN32)
+ # On Windows DLLs must be next to the .exe (no RPATH). Copy them to bin/.
+ file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
+ file(GLOB _dep_dlls
+ "${OPEN62541_INSTALL_DIR}/bin/*.dll"
+ "${QTOPCUA_INSTALL_DIR}/bin/*.dll")
+ foreach(_dll ${_dep_dlls})
+ file(COPY "${_dll}" DESTINATION "${CMAKE_BINARY_DIR}/bin")
+ endforeach()
+else()
+ # The QtOpcUa backend plugin uses $ORIGIN-relative RUNPATH that resolves to
+ # qtopcua-install/lib/. Symlink the open62541 libs there so dlopen finds them.
+ file(GLOB _open62541_libs "${OPEN62541_INSTALL_DIR}/lib/libopen62541*")
+ foreach(_lib ${_open62541_libs})
+ get_filename_component(_name ${_lib} NAME)
+ if(NOT EXISTS "${QTOPCUA_INSTALL_DIR}/lib/${_name}")
+ file(CREATE_LINK ${_lib} "${QTOPCUA_INSTALL_DIR}/lib/${_name}" SYMBOLIC)
+ endif()
+ endforeach()
+endif()