diff --git a/src/Libraries/robot_cpp/CMakeLists.txt b/src/Libraries/robot_cpp/CMakeLists.txt index 44d8381..91e0193 100644 --- a/src/Libraries/robot_cpp/CMakeLists.txt +++ b/src/Libraries/robot_cpp/CMakeLists.txt @@ -1,4 +1,18 @@ cmake_minimum_required(VERSION 3.0.2) + +# ======================================================== +# Dual-mode CMakeLists.txt: Supports both Catkin and Standalone CMake +# ======================================================== + +# Detect if building with Catkin +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() + project(robot_cpp) set(CMAKE_CXX_STANDARD 17) @@ -9,25 +23,10 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) # Find Packages # ======================================================== -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() - - if(BUILDING_WITH_CATKIN) ## Find catkin macros and libraries find_package(catkin REQUIRED COMPONENTS - robot_xmlrpcpp - robot_time - ) - catkin_package( - INCLUDE_DIRS include - LIBRARIES robot_cpp - CATKIN_DEPENDS robot_xmlrpcpp robot_time + robot_xmlrpcpp ) endif() @@ -45,7 +44,105 @@ if(PkgConfig_FOUND) endif() endif() +# If pkg-config didn't work, find shared library directly, prioritizing /usr/lib +if(NOT YAML_CPP_TARGET) + # First try system paths (avoid /usr/local which may have static library) + find_library(YAML_CPP_SHARED_LIB + NAMES yaml-cpp + PATHS /usr/lib + PATH_SUFFIXES x86_64-linux-gnu + NO_DEFAULT_PATH + ) + + if(YAML_CPP_SHARED_LIB AND EXISTS "${YAML_CPP_SHARED_LIB}") + # Verify it's actually a shared library (not a symlink to static) + get_filename_component(YAML_CPP_REAL_LIB "${YAML_CPP_SHARED_LIB}" REALPATH) + if(YAML_CPP_REAL_LIB MATCHES "\\.so") + set(YAML_CPP_TARGET ${YAML_CPP_SHARED_LIB}) + message(STATUS "Found yaml-cpp shared library in /usr/lib: ${YAML_CPP_SHARED_LIB}") + # Also find include directory + find_path(YAML_CPP_INCLUDE_DIR + NAMES yaml-cpp/yaml.h + PATHS /usr/include + NO_DEFAULT_PATH + ) + if(YAML_CPP_INCLUDE_DIR) + message(STATUS "Found yaml-cpp include directory: ${YAML_CPP_INCLUDE_DIR}") + endif() + endif() + endif() +endif() + +# Now use find_package, but temporarily exclude /usr/local to avoid static library +set(CMAKE_PREFIX_PATH_SAVED ${CMAKE_PREFIX_PATH}) +list(REMOVE_ITEM CMAKE_PREFIX_PATH "/usr/local") find_package(yaml-cpp QUIET) +set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH_SAVED}) + +# Use target if available and we haven't found a library yet +if(NOT YAML_CPP_TARGET) + 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") + else() + # Last resort: try to find any library, but check if it's static + find_library(YAML_CPP_ANY_LIB + NAMES yaml-cpp + PATHS /usr/lib /usr/local/lib /lib + PATH_SUFFIXES x86_64-linux-gnu + ) + + if(YAML_CPP_ANY_LIB) + if(YAML_CPP_ANY_LIB MATCHES "\\.a$") + message(FATAL_ERROR + "yaml-cpp static library found at: ${YAML_CPP_ANY_LIB}\n" + "This cannot be linked into a shared library.\n" + "Solution: Remove static library or use system shared library:\n" + " sudo rm /usr/local/lib/libyaml-cpp.a\n" + "Or ensure /usr/lib/x86_64-linux-gnu/libyaml-cpp.so is found first." + ) + else() + set(YAML_CPP_TARGET ${YAML_CPP_ANY_LIB}) + message(STATUS "Found yaml-cpp library: ${YAML_CPP_TARGET}") + endif() + else() + set(YAML_CPP_TARGET yaml-cpp) + message(WARNING "yaml-cpp library not found. Using library name 'yaml-cpp'") + endif() + endif() +endif() + +find_package(console_bridge REQUIRED) + +# ======================================================== +# Catkin specific configuration +# ======================================================== + +if(BUILDING_WITH_CATKIN) + ## The catkin_package macro generates cmake config files for your package + ## Note: yaml-cpp and console_bridge are system dependencies, not declared in DEPENDS + ## as they don't provide the required INCLUDE_DIRS/LIBRARIES variables for catkin + catkin_package( + INCLUDE_DIRS include + LIBRARIES robot_cpp + CATKIN_DEPENDS robot_xmlrpcpp + ) +endif() + +########### +## Build ## +########### + +## 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() + ## Include directories include_directories( include @@ -73,20 +170,32 @@ target_include_directories(${PROJECT_NAME} ## Link libraries # Use the determined yaml-cpp target/library -if(BUILDING_WITH_CATKIN) - add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) - target_link_libraries(${PROJECT_NAME} ${catkin_TARGETS}) -else() - target_link_libraries(${PROJECT_NAME} - PUBLIC - ${YAML_CPP_TARGET} - robot_xmlrpcpp - robot_time - PRIVATE - dl # Required for dladdr() function used in plugin_loader_helper.cpp +target_link_libraries(${PROJECT_NAME} + PUBLIC + ${YAML_CPP_TARGET} + robot_xmlrpcpp + robot_time + PRIVATE + dl # Required for dladdr() function used in plugin_loader_helper.cpp +) + +# Check if we're using static library and warn user +if(YAML_CPP_TARGET MATCHES "\\.a$" OR YAML_CPP_TARGET MATCHES "libyaml-cpp\\.a") + message(FATAL_ERROR + "yaml-cpp static library detected at: ${YAML_CPP_TARGET}\n" + "Static libraries cannot be linked into shared libraries without -fPIC.\n" + "Solution: Install shared library version:\n" + " sudo apt-get install libyaml-cpp-dev\n" + "Or rebuild yaml-cpp with -fPIC flag." ) endif() + +## Add cmake target dependencies +if(BUILDING_WITH_CATKIN) + add_dependencies(${PROJECT_NAME} ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS}) +endif() + set_target_properties(${PROJECT_NAME} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} )