CmvrControlStation/CMakeLists.txt

361 lines
14 KiB
CMake
Raw Permalink Normal View History

2026-09-18 16:22:20 +08:00
cmake_minimum_required(VERSION 3.16)
project(CmvrControlStation VERSION 1.0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
2026-09-18 16:22:20 +08:00
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOUIC_SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/ui")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
if(WIN32)
set(CMVR_MSQUIC_DEFAULT ON)
else()
set(CMVR_MSQUIC_DEFAULT OFF)
endif()
option(CMVR_WITH_MSQUIC "Build the embedded MsQuic test server" ${CMVR_MSQUIC_DEFAULT})
set(CMVR_MSQUIC_ROOT "" CACHE PATH "Optional MsQuic installation prefix on Linux")
set(CMVR_CXX_RUNTIME "" CACHE FILEPATH
"Optional libstdc++.so.6 matching a non-system Linux dependency prefix")
set(CMVR_ASSIMP_SCENE_PARSER "" CACHE FILEPATH
"Qt3D Assimp scene parser plugin used for URDF mesh files")
2026-09-18 16:22:20 +08:00
set(CMVR_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include")
set(CMVR_LIB_DIR "${CMAKE_CURRENT_SOURCE_DIR}/lib")
set(CMVR_TOOLS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tools")
set(CMVR_CERT_DIR "${CMAKE_CURRENT_SOURCE_DIR}/certs")
set(PROTO_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/protos")
set(GENERATED_ROOT "${CMAKE_CURRENT_BINARY_DIR}/generated_cpp")
find_package(Qt5 5.12 REQUIRED COMPONENTS
Core Gui Widgets Multimedia 3DCore 3DRender 3DExtras 3DInput 3DAnimation)
get_target_property(CMVR_QMAKE_EXECUTABLE Qt5::qmake IMPORTED_LOCATION)
if(CMVR_QMAKE_EXECUTABLE)
execute_process(
COMMAND "${CMVR_QMAKE_EXECUTABLE}" -query QT_INSTALL_PLUGINS
OUTPUT_VARIABLE CMVR_QT_PLUGIN_ROOT
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
if(NOT CMVR_ASSIMP_SCENE_PARSER)
find_file(CMVR_ASSIMP_SCENE_PARSER
NAMES assimpsceneimport.dll assimpsceneimportd.dll libassimpsceneimport.so
HINTS
"${CMVR_QT_PLUGIN_ROOT}/sceneparsers"
"/usr/lib/${CMAKE_LIBRARY_ARCHITECTURE}/qt5/plugins/sceneparsers")
endif()
if(NOT CMVR_ASSIMP_SCENE_PARSER OR NOT EXISTS "${CMVR_ASSIMP_SCENE_PARSER}")
message(FATAL_ERROR
"Qt3D's Assimp scene parser was not found. It is required to display "
"STL, DAE, and 3DS meshes from bundled URDF models. On Ubuntu install "
"qt3d-assimpsceneimport-plugin, or set CMVR_ASSIMP_SCENE_PARSER to the "
"plugin file supplied by the selected Qt installation.")
endif()
if(WIN32)
# The checked-in native libraries use the Qt 5.12.4 MinGW 7.3 64-bit ABI.
set(PROTOC "${CMVR_TOOLS_DIR}/run_protoc.cmd")
set(GRPC_CPP_PLUGIN "${CMVR_TOOLS_DIR}/grpc_cpp_plugin.exe")
foreach(REQUIRED_FILE IN ITEMS
"${PROTOC}"
"${GRPC_CPP_PLUGIN}"
"${CMVR_LIB_DIR}/libgrpc++.a"
"${CMVR_LIB_DIR}/libprotobuf.a"
"${CMVR_LIB_DIR}/libavcodec.dll.a"
"${CMVR_LIB_DIR}/liburdfdom_model.dll.a")
if(NOT EXISTS "${REQUIRED_FILE}")
message(FATAL_ERROR "Required Windows dependency not found: ${REQUIRED_FILE}")
endif()
endforeach()
else()
find_package(Protobuf CONFIG QUIET)
if(NOT Protobuf_FOUND)
find_package(Protobuf REQUIRED)
endif()
find_package(gRPC CONFIG REQUIRED)
find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(FFMPEG REQUIRED IMPORTED_TARGET
libavcodec libavutil libswscale)
find_path(CMVR_URDFDOM_INCLUDE_DIR urdf_parser/urdf_parser.h
PATH_SUFFIXES include include/urdfdom)
find_path(CMVR_TINYXML_INCLUDE_DIR tinyxml.h PATH_SUFFIXES include)
find_library(CMVR_URDFDOM_MODEL_LIBRARY NAMES urdfdom_model)
if(NOT CMVR_URDFDOM_INCLUDE_DIR OR NOT CMVR_TINYXML_INCLUDE_DIR OR
NOT CMVR_URDFDOM_MODEL_LIBRARY)
message(FATAL_ERROR
"urdfdom/tinyxml was not found. Install liburdfdom-dev or add its prefix "
"to CMAKE_PREFIX_PATH.")
endif()
if(NOT TARGET protobuf::protoc)
message(FATAL_ERROR "The Protobuf package does not provide protobuf::protoc")
endif()
if(NOT TARGET gRPC::grpc_cpp_plugin)
message(FATAL_ERROR "The gRPC package does not provide gRPC::grpc_cpp_plugin")
endif()
set(PROTOC "$<TARGET_FILE:protobuf::protoc>")
set(GRPC_CPP_PLUGIN "$<TARGET_FILE:gRPC::grpc_cpp_plugin>")
# A Conda-provided Qt/gRPC stack may carry an older libstdc++ than the
# host compiler. Link against the runtime next to the imported dependency
# so symbol versions selected at link time match the library loaded from
# the generated RUNPATH. System packages resolve to the system runtime.
if(NOT CMVR_CXX_RUNTIME)
foreach(DEPENDENCY_TARGET IN ITEMS gRPC::grpc++ Qt5::Core)
get_target_property(DEPENDENCY_LOCATION
${DEPENDENCY_TARGET} IMPORTED_LOCATION_RELEASE)
if(NOT DEPENDENCY_LOCATION)
get_target_property(DEPENDENCY_LOCATION
${DEPENDENCY_TARGET} IMPORTED_LOCATION)
endif()
if(DEPENDENCY_LOCATION)
get_filename_component(DEPENDENCY_LIB_DIR
"${DEPENDENCY_LOCATION}" DIRECTORY)
if(EXISTS "${DEPENDENCY_LIB_DIR}/libstdc++.so.6")
set(CMVR_CXX_RUNTIME
"${DEPENDENCY_LIB_DIR}/libstdc++.so.6")
message(STATUS
"Using dependency-prefix C++ runtime: ${CMVR_CXX_RUNTIME}")
break()
endif()
endif()
endforeach()
endif()
endif()
if(CMVR_WITH_MSQUIC)
if(WIN32)
if(NOT EXISTS "${CMVR_INCLUDE_DIR}/msquic.h" OR
NOT EXISTS "${CMVR_LIB_DIR}/msquic.dll")
message(FATAL_ERROR
"CMVR_WITH_MSQUIC is enabled, but include/msquic.h or lib/msquic.dll is missing")
endif()
set(CMVR_MSQUIC_INCLUDE_DIR "${CMVR_INCLUDE_DIR}")
else()
find_path(CMVR_MSQUIC_INCLUDE_DIR msquic.h
HINTS "${CMVR_MSQUIC_ROOT}"
PATH_SUFFIXES include)
find_library(CMVR_MSQUIC_LIBRARY NAMES msquic
HINTS "${CMVR_MSQUIC_ROOT}"
PATH_SUFFIXES lib lib64)
if(NOT CMVR_MSQUIC_INCLUDE_DIR OR NOT CMVR_MSQUIC_LIBRARY)
message(FATAL_ERROR
"CMVR_WITH_MSQUIC=ON requires a Linux MsQuic installation. "
"Set CMVR_MSQUIC_ROOT or configure with -DCMVR_WITH_MSQUIC=OFF.")
endif()
get_filename_component(CMVR_MSQUIC_LIBRARY_DIR
"${CMVR_MSQUIC_LIBRARY}" DIRECTORY)
endif()
endif()
2026-09-18 16:22:20 +08:00
set(CMVR_SOURCES
2026-09-18 16:22:20 +08:00
src/audiostreammanager.cpp
src/audiostreammanager.h
src/configeditorwidget.cpp
src/configeditorwidget.h
src/main.cpp
src/mainwindow.cpp
src/mainwindow_ui.cpp
src/mainwindow.h
src/quictestserver.cpp
src/quictestserver.h
src/rpcservicewidget.cpp
src/rpcservicewidget.h
src/robotclient.cpp
src/robotclient.h
src/trendwidget.cpp
src/trendwidget.h
src/uiicons.h
2026-09-18 16:22:20 +08:00
src/urdfviewerwidget.cpp
src/urdfviewerwidget.h
src/videodecoder.cpp
src/videodecoder.h
src/videoframe.h
src/videorenderwidget.cpp
src/videorenderwidget.h
ui/handeyecalibrationwidget.cpp
ui/handeyecalibrationwidget.h
ui/handeyecalibrationwidget.ui
2026-09-18 16:22:20 +08:00
ui/mainwindow.ui
ui/systemservicepage.ui
ui/armservicepage.ui
ui/cameraservicepage.ui
ui/agvservicepage.ui
ui/agvstatusdialog.ui
2026-09-18 16:22:20 +08:00
ui/audioservicepage.ui
ui/quicserverpage.ui
ui/diagnosticspage.ui
ui/rpcservicewidget.ui
resources.qrc)
add_executable(CmvrControlStation ${CMVR_SOURCES})
if(WIN32)
set_target_properties(CmvrControlStation PROPERTIES WIN32_EXECUTABLE TRUE)
endif()
2026-09-18 16:22:20 +08:00
set_target_properties(CmvrControlStation PROPERTIES
DEBUG_POSTFIX "_d"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/bin/$<LOWER_CASE:$<CONFIG>>")
target_compile_definitions(CmvrControlStation PRIVATE
CMVR_WITH_GRPC=1
CMVR_WITH_MSQUIC=$<BOOL:${CMVR_WITH_MSQUIC}>)
if(WIN32)
target_compile_definitions(CmvrControlStation PRIVATE _WIN32_WINNT=0x0600)
endif()
target_include_directories(CmvrControlStation PRIVATE "${GENERATED_ROOT}")
if(WIN32)
target_include_directories(CmvrControlStation PRIVATE
"${CMVR_INCLUDE_DIR}"
"${CMVR_INCLUDE_DIR}/urdfdom_headers")
else()
target_include_directories(CmvrControlStation PRIVATE
"${CMVR_URDFDOM_INCLUDE_DIR}"
"${CMVR_TINYXML_INCLUDE_DIR}"
"${CMVR_INCLUDE_DIR}/urdfdom_headers")
endif()
if(CMVR_WITH_MSQUIC)
target_include_directories(CmvrControlStation PRIVATE "${CMVR_MSQUIC_INCLUDE_DIR}")
if(UNIX AND CMVR_MSQUIC_LIBRARY_DIR)
set_property(TARGET CmvrControlStation APPEND PROPERTY
BUILD_RPATH "${CMVR_MSQUIC_LIBRARY_DIR}")
endif()
endif()
2026-09-18 16:22:20 +08:00
target_link_libraries(CmvrControlStation PRIVATE
Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Multimedia
Qt5::3DCore Qt5::3DRender Qt5::3DExtras Qt5::3DInput Qt5::3DAnimation)
# Generate every project-local CMVR message. This avoids source-tree generated
# files and automatically picks up newly added configuration messages.
file(GLOB_RECURSE PROTO_FILES CONFIGURE_DEPENDS
"${PROTO_ROOT}/cmvr/api/*.proto"
"${PROTO_ROOT}/cmvr/common/*.proto"
"${PROTO_ROOT}/cmvr/config/*.proto"
"${PROTO_ROOT}/cmvr/msgs/agv.proto"
"${PROTO_ROOT}/cmvr/quic_edge/v1/*.proto")
2026-09-18 16:22:20 +08:00
set(SERVICE_NAMES
cmvr/api/agv_service
cmvr/api/arm_service
cmvr/api/biohead_service
cmvr/api/camera_service
cmvr/api/configuration_service
cmvr/api/dexhand_service
cmvr/api/hlc_service
cmvr/api/microphone_service
cmvr/api/speaker_service
cmvr/api/system_service
cmvr/api/test_service)
set(GENERATED_FILES)
foreach(PROTO_FILE IN LISTS PROTO_FILES)
file(RELATIVE_PATH PROTO_RELATIVE "${PROTO_ROOT}" "${PROTO_FILE}")
string(REGEX REPLACE "\\.proto$" "" PROTO_NAME "${PROTO_RELATIVE}")
2026-09-18 16:22:20 +08:00
set(PB_CC "${GENERATED_ROOT}/${PROTO_NAME}.pb.cc")
set(PB_H "${GENERATED_ROOT}/${PROTO_NAME}.pb.h")
get_filename_component(PROTO_OUTPUT_DIR "${PB_CC}" DIRECTORY)
add_custom_command(
OUTPUT "${PB_CC}" "${PB_H}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${PROTO_OUTPUT_DIR}"
COMMAND "${PROTOC}"
"--proto_path=${PROTO_ROOT}"
"--cpp_out=${GENERATED_ROOT}"
2026-09-18 16:22:20 +08:00
"${PROTO_FILE}"
DEPENDS "${PROTO_FILE}" ${PROTO_FILES}
2026-09-18 16:22:20 +08:00
VERBATIM)
list(APPEND GENERATED_FILES "${PB_CC}" "${PB_H}")
endforeach()
foreach(SERVICE_NAME IN LISTS SERVICE_NAMES)
set(PROTO_FILE "${PROTO_ROOT}/${SERVICE_NAME}.proto")
set(GRPC_CC "${GENERATED_ROOT}/${SERVICE_NAME}.grpc.pb.cc")
set(GRPC_H "${GENERATED_ROOT}/${SERVICE_NAME}.grpc.pb.h")
get_filename_component(PROTO_OUTPUT_DIR "${GRPC_CC}" DIRECTORY)
add_custom_command(
OUTPUT "${GRPC_CC}" "${GRPC_H}"
COMMAND ${CMAKE_COMMAND} -E make_directory "${PROTO_OUTPUT_DIR}"
COMMAND "${PROTOC}"
"--proto_path=${PROTO_ROOT}"
"--grpc_out=${GENERATED_ROOT}"
"--plugin=protoc-gen-grpc=${GRPC_CPP_PLUGIN}"
2026-09-18 16:22:20 +08:00
"${PROTO_FILE}"
DEPENDS "${PROTO_FILE}" ${PROTO_FILES}
2026-09-18 16:22:20 +08:00
VERBATIM)
list(APPEND GENERATED_FILES "${GRPC_CC}" "${GRPC_H}")
endforeach()
target_sources(CmvrControlStation PRIVATE ${GENERATED_FILES})
if(WIN32)
file(GLOB ABSL_STATIC_LIBS "${CMVR_LIB_DIR}/libabsl_*.a")
target_link_libraries(CmvrControlStation PRIVATE
"-Wl,--start-group"
"${CMVR_LIB_DIR}/libgrpc++.a"
"${CMVR_LIB_DIR}/libgrpc.a"
"${CMVR_LIB_DIR}/libgpr.a"
"${CMVR_LIB_DIR}/libaddress_sorting.a"
"${CMVR_LIB_DIR}/libre2.a"
"${CMVR_LIB_DIR}/libupb.a"
"${CMVR_LIB_DIR}/libcares.a"
"${CMVR_LIB_DIR}/libssl.a"
"${CMVR_LIB_DIR}/libcrypto.a"
"${CMVR_LIB_DIR}/libzlibstatic.a"
"${CMVR_LIB_DIR}/libprotobuf.a"
${ABSL_STATIC_LIBS}
"-Wl,--end-group"
"${CMVR_LIB_DIR}/libavcodec.dll.a"
"${CMVR_LIB_DIR}/libavutil.dll.a"
"${CMVR_LIB_DIR}/libswscale.dll.a"
"${CMVR_LIB_DIR}/liburdfdom_model.dll.a"
ws2_32 crypt32 advapi32 bcrypt dbghelp iphlpapi secur32 ntdll)
else()
if(CMVR_CXX_RUNTIME)
target_link_libraries(CmvrControlStation PRIVATE "${CMVR_CXX_RUNTIME}")
endif()
target_link_libraries(CmvrControlStation PRIVATE
protobuf::libprotobuf
gRPC::grpc++
PkgConfig::FFMPEG
Threads::Threads
"${CMVR_URDFDOM_MODEL_LIBRARY}")
endif()
if(WIN32)
file(GLOB CMVR_RUNTIME_DLLS "${CMVR_LIB_DIR}/*.dll")
foreach(RUNTIME_DLL IN LISTS CMVR_RUNTIME_DLLS)
add_custom_command(TARGET CmvrControlStation POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${RUNTIME_DLL}" "$<TARGET_FILE_DIR:CmvrControlStation>")
endforeach()
endif()
2026-09-18 16:22:20 +08:00
foreach(CERTIFICATE IN ITEMS quic-test-server.pfx quic-test-ca.crt)
if(EXISTS "${CMVR_CERT_DIR}/${CERTIFICATE}")
add_custom_command(TARGET CmvrControlStation POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMVR_CERT_DIR}/${CERTIFICATE}"
"$<TARGET_FILE_DIR:CmvrControlStation>/${CERTIFICATE}")
install(FILES "${CMVR_CERT_DIR}/${CERTIFICATE}" DESTINATION bin)
endif()
2026-09-18 16:22:20 +08:00
endforeach()
2026-09-18 16:22:20 +08:00
add_custom_command(TARGET CmvrControlStation POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory
"$<TARGET_FILE_DIR:CmvrControlStation>/sceneparsers"
2026-09-18 16:22:20 +08:00
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${CMVR_ASSIMP_SCENE_PARSER}"
"$<TARGET_FILE_DIR:CmvrControlStation>/sceneparsers/"
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${CMAKE_CURRENT_SOURCE_DIR}/models"
"$<TARGET_FILE_DIR:CmvrControlStation>/models")
2026-09-18 16:22:20 +08:00
install(TARGETS CmvrControlStation RUNTIME DESTINATION bin)
install(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/models/"
DESTINATION bin/models)
install(PROGRAMS "${CMVR_ASSIMP_SCENE_PARSER}"
DESTINATION bin/sceneparsers)