361 lines
14 KiB
CMake
361 lines
14 KiB
CMake
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)
|
|
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")
|
|
|
|
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()
|
|
|
|
set(CMVR_SOURCES
|
|
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
|
|
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
|
|
ui/mainwindow.ui
|
|
ui/systemservicepage.ui
|
|
ui/armservicepage.ui
|
|
ui/cameraservicepage.ui
|
|
ui/agvservicepage.ui
|
|
ui/agvstatusdialog.ui
|
|
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()
|
|
|
|
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()
|
|
|
|
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")
|
|
|
|
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}")
|
|
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}"
|
|
"${PROTO_FILE}"
|
|
DEPENDS "${PROTO_FILE}" ${PROTO_FILES}
|
|
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}"
|
|
"${PROTO_FILE}"
|
|
DEPENDS "${PROTO_FILE}" ${PROTO_FILES}
|
|
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()
|
|
|
|
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()
|
|
endforeach()
|
|
|
|
add_custom_command(TARGET CmvrControlStation POST_BUILD
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory
|
|
"$<TARGET_FILE_DIR:CmvrControlStation>/sceneparsers"
|
|
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")
|
|
|
|
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)
|