# ====================================== # BuildDeps.cmake # # Configure, build, and install open62541 and QtOpcUa from git submodules under # deps/. # # Skip detection: if the built .so already exists, the corresponding dep is # skipped. Delete the file to rebuild. # ====================================== set(OPEN62541_SOURCE_DIR "${CMAKE_SOURCE_DIR}/deps/open62541") set(OPEN62541_BUILD_DIR "${CMAKE_BINARY_DIR}/deps/open62541-build") set(OPEN62541_INSTALL_DIR "${CMAKE_BINARY_DIR}/deps/open62541-install") set(QTOPCUA_SOURCE_DIR "${CMAKE_SOURCE_DIR}/deps/qtopcua") set(QTOPCUA_BUILD_DIR "${CMAKE_BINARY_DIR}/deps/qtopcua-build") set(QTOPCUA_INSTALL_DIR "${CMAKE_BINARY_DIR}/deps/qtopcua-install") # Verify submodules are initialized if(NOT EXISTS "${OPEN62541_SOURCE_DIR}/CMakeLists.txt") message( FATAL_ERROR "open62541 submodule not initialized. Run: git submodule update --init --recursive" ) endif() if(NOT EXISTS "${QTOPCUA_SOURCE_DIR}/CMakeLists.txt") message( FATAL_ERROR "qtopcua submodule not initialized. Run: git submodule update --init --recursive" ) endif() # ====================================== # open62541 # ====================================== 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 ${CMAKE_COMMAND} -S "${OPEN62541_SOURCE_DIR}" -B "${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 -DUA_ENABLE_DISCOVERY=ON) execute_process(COMMAND ${_cmd} RESULT_VARIABLE _result) if(_result) list(JOIN _cmd " " _cmd_str) message(FATAL_ERROR "${_cmd_str} failed: ${_result}") endif() message(STATUS "Building open62541 in ${OPEN62541_BUILD_DIR}...") set(_cmd ${CMAKE_COMMAND} --build "${OPEN62541_BUILD_DIR}" --parallel) execute_process(COMMAND ${_cmd} RESULT_VARIABLE _result) if(_result) list(JOIN _cmd " " _cmd_str) message(FATAL_ERROR "${_cmd_str} failed: ${_result}") endif() message(STATUS "Installing open62541 to ${OPEN62541_INSTALL_DIR}...") set(_cmd ${CMAKE_COMMAND} --install "${OPEN62541_BUILD_DIR}") execute_process(COMMAND ${_cmd} RESULT_VARIABLE _result) if(_result) list(JOIN _cmd " " _cmd_str) message(FATAL_ERROR "${_cmd_str} failed: ${_result}") endif() else() message(STATUS "open62541 already built, skipping") endif() # ====================================== # QtOpcUa # ====================================== find_program( QT_CMAKE_COMMAND NAMES qt-cmake qt-cmake.bat PATHS ${CMAKE_PREFIX_PATH} PATH_SUFFIXES bin REQUIRED) 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 ${QT_CMAKE_COMMAND} -S "${QTOPCUA_SOURCE_DIR}" -B "${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) set(_openssl_dir "C:/Program Files/OpenSSL-Win64") if(NOT EXISTS "${_openssl_dir}") message( FATAL_ERROR "OpenSSL development files not found at ${_openssl_dir}.\n" "Install with: winget install ShiningLight.OpenSSL.Dev") endif() list(APPEND _cmd -DOPENSSL_ROOT_DIR:PATH=${_openssl_dir}) endif() execute_process(COMMAND ${_cmd} RESULT_VARIABLE _result) if(_result) list(JOIN _cmd " " _cmd_str) message(FATAL_ERROR "${_cmd_str} failed: ${_result}") endif() message(STATUS "Building qtopcua in ${QTOPCUA_BUILD_DIR}...") set(_cmd ${QT_CMAKE_COMMAND} --build "${QTOPCUA_BUILD_DIR}" --parallel) execute_process(COMMAND ${_cmd} RESULT_VARIABLE _result) if(_result) list(JOIN _cmd " " _cmd_str) message(FATAL_ERROR "${_cmd_str} failed: ${_result}") endif() message(STATUS "Installing qtopcua to ${QTOPCUA_INSTALL_DIR}...") set(_cmd ${QT_CMAKE_COMMAND} --install "${QTOPCUA_BUILD_DIR}") execute_process(COMMAND ${_cmd} RESULT_VARIABLE _result) if(_result) list(JOIN _cmd " " _cmd_str) message(FATAL_ERROR "${_cmd_str} failed: ${_result}") endif() else() message(STATUS "qtopcua already built, skipping") endif() 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()