cmake_minimum_required(VERSION 3.0.2) project(robot_cpp VERSION 1.0.0 LANGUAGES CXX) if(DEFINED CATKIN_DEVEL_PREFIX OR DEFINED CATKIN_TOPLEVEL) set(BUILDING_WITH_CATKIN TRUE) message(STATUS "Building robot_cpp with Catkin") else() set(BUILDING_WITH_CATKIN FALSE) message(STATUS "Building robot_cpp with Standalone CMake") endif() # C++ Standard - must be set before find_package set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # Find dependencies find_package(yaml-cpp REQUIRED) find_package(console_bridge REQUIRED) if (NOT BUILDING_WITH_CATKIN) # Enable Position Independent Code set(CMAKE_POSITION_INDEPENDENT_CODE ON) # Cấu hình RPATH để tránh cycle trong runtime search path set(CMAKE_BUILD_RPATH_USE_ORIGIN TRUE) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) set(CMAKE_BUILD_RPATH "${CMAKE_BINARY_DIR}") set(PACKAGES_DIR robot_xmlrpcpp robot_time ) else() # ======================================================== # Catkin specific configuration # ======================================================== find_package(catkin REQUIRED COMPONENTS robot_xmlrpcpp robot_time ) catkin_package( INCLUDE_DIRS include LIBRARIES ${PROJECT_NAME} CATKIN_DEPENDS robot_xmlrpcpp robot_time # Note: yaml-cpp and console_bridge are system dependencies, # linked via target_link_libraries, not via catkin_package DEPENDS ) include_directories( include ${catkin_INCLUDE_DIRS} ) endif() # Use yaml-cpp target if available (modern CMake) if(TARGET yaml-cpp::yaml-cpp) set(YAML_CPP_TARGET yaml-cpp::yaml-cpp) message(STATUS "Using yaml-cpp target: yaml-cpp::yaml-cpp") elseif(TARGET yaml-cpp) set(YAML_CPP_TARGET yaml-cpp) message(STATUS "Using yaml-cpp target: yaml-cpp") elseif(yaml-cpp_LIBRARIES) # Fallback to library variable if target not available set(YAML_CPP_TARGET ${yaml-cpp_LIBRARIES}) message(STATUS "Using yaml-cpp library: ${YAML_CPP_TARGET}") else() # Last resort: use library name set(YAML_CPP_TARGET yaml-cpp) message(STATUS "Using yaml-cpp library name: yaml-cpp") endif() # Compiler flags if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") # Warning flags - disabled to suppress warnings during build # add_compile_options(-Wall -Wextra -Wpedantic -fPIC) add_compile_options(-w -fPIC) # -w suppresses all warnings endif() # Libraries add_library(${PROJECT_NAME} SHARED src/console.cpp src/node_handle.cpp src/plugin_loader_helper.cpp src/init.cpp ) # Enable C++17 filesystem feature target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17) if(BUILDING_WITH_CATKIN) add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) target_include_directories(${PROJECT_NAME} PUBLIC $ $ ) # Link filesystem library if needed (for GCC < 9 or Clang) set(FILESYSTEM_LIB "") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0") set(FILESYSTEM_LIB "stdc++fs") elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") find_library(FILESYSTEM_LIB c++fs) endif() target_link_libraries(${PROJECT_NAME} PUBLIC ${catkin_LIBRARIES} PRIVATE ${YAML_CPP_TARGET} PRIVATE dl # Required for dladdr() function used in plugin_loader_helper.cpp ) if(FILESYSTEM_LIB) target_link_libraries(${PROJECT_NAME} PRIVATE ${FILESYSTEM_LIB}) endif() else() target_include_directories(${PROJECT_NAME} PUBLIC $ $ ) # Link filesystem library if needed (for GCC < 9 or Clang) set(FILESYSTEM_LIB "") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0") set(FILESYSTEM_LIB "stdc++fs") elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") find_library(FILESYSTEM_LIB c++fs) endif() target_link_libraries(${PROJECT_NAME} PUBLIC ${PACKAGES_DIR} ${YAML_CPP_TARGET} PRIVATE dl # Required for dladdr() function used in plugin_loader_helper.cpp ) if(FILESYSTEM_LIB) target_link_libraries(${PROJECT_NAME} PRIVATE ${FILESYSTEM_LIB}) endif() set_target_properties(${PROJECT_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} ) endif() # Define CMAKE_BINARY_DIR as compile definition so it's available at runtime target_compile_definitions(${PROJECT_NAME} PRIVATE PNKX_NAV_CORE_BUILD_DIR="${CMAKE_BINARY_DIR}" ) if(BUILDING_WITH_CATKIN) ## Mark libraries for installation ## See http://docs.ros.org/melodic/api/catkin/html/howto/format1/building_libraries.html install(TARGETS ${PROJECT_NAME} ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION} RUNTIME DESTINATION ${CATKIN_GLOBAL_BIN_DESTINATION} ) ## Mark cpp header files for installation install(DIRECTORY include/ DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION} FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE ) else() install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}-targets ARCHIVE DESTINATION lib LIBRARY DESTINATION lib RUNTIME DESTINATION bin ) # Export targets install(EXPORT ${PROJECT_NAME}-targets FILE ${PROJECT_NAME}-targets.cmake NAMESPACE ${PROJECT_NAME}:: DESTINATION lib/cmake/${PROJECT_NAME} ) ## Mark cpp header files for installation install(DIRECTORY include/ DESTINATION include FILES_MATCHING PATTERN "*.h" PATTERN ".svn" EXCLUDE ) # ======================================================== # Install CMake Config File for find_package() # ======================================================== # Generate config file from template configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/robot_cppConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/robot_cppConfig.cmake @ONLY ) # Install config file install(FILES ${CMAKE_CURRENT_BINARY_DIR}/robot_cppConfig.cmake DESTINATION lib/cmake/${PROJECT_NAME} ) # Print configuration info message(STATUS "=================================") message(STATUS "Project: ${PROJECT_NAME}") message(STATUS "Version: ${PROJECT_VERSION}") message(STATUS "C++ Standard: ${CMAKE_CXX_STANDARD}") message(STATUS "Dependencies: robot_xmlrpcpp, robot_time, yaml-cpp, console_bridge") message(STATUS "=================================") endif() # ======================================================== # Test executable # ======================================================== option(BUILD_TESTS "Build test programs" OFF) if(BUILD_TESTS) add_executable(test_node_handle test/test_node_handle.cpp ) target_include_directories(test_node_handle PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include ) target_link_libraries(test_node_handle PRIVATE ${PROJECT_NAME} ${YAML_CPP_TARGET} ) set_target_properties(test_node_handle PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} ) # Link filesystem library if needed if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "9.0") target_link_libraries(test_node_handle PRIVATE stdc++fs) elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") find_library(FILESYSTEM_LIB c++fs) if(FILESYSTEM_LIB) target_link_libraries(test_node_handle PRIVATE ${FILESYSTEM_LIB}) endif() endif() # Add test to CTest add_test(NAME NodeHandleTest COMMAND test_node_handle) message(STATUS "Test executable 'test_node_handle' will be built") endif()