CogRob/catkin_grpc

Linker error when using GRPC

Closed this issue · 5 comments

When I try to create a grpc service in an other catkin package, I have to manually add ".... /devel/lib/libgrpc++_unsecure.so" to target_link_libraries in the corresponding CMakeLists.txt. Otherwise I get a linker error when building the package.

That's very strange. This library should be automatically linked already: see

find_library(LIBGRPCPP_UNSECURE grpc++_unsecure

Do you have "GRPC" in your generate_proto statement. Do you mind sharing your CMakeLists with us?

The proto files are generated in an other package.
package with service:

cmake_minimum_required(VERSION`

 2.8.3)
project(corbslam_server)


IF (NOT CMAKE_BUILD_TYPE)
    SET(CMAKE_BUILD_TYPE Release)
ENDIF ()

MESSAGE("Build type: " ${CMAKE_BUILD_TYPE})

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}  -Wall -O3 -march=native ")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O3 -march=native ")

# Check C++11 or C++0x support
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if (COMPILER_SUPPORTS_CXX11)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
    add_definitions(-DCOMPILEDWITHC11)
    message(STATUS "Using flag -std=c++11.")
elseif (COMPILER_SUPPORTS_CXX0X)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
    add_definitions(-DCOMPILEDWITHC0X)
    message(STATUS "Using flag -std=c++0x.")
else ()
    message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif ()


list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules")

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
        roscpp
        rospy
        std_msgs
        message_generation
        tf
	    corbslam_client
	    grpc
        )
find_package(OpenCV REQUIRED)
find_package(Eigen3 3.1.0 REQUIRED)
find_package(Pangolin REQUIRED)
find_package(Boost COMPONENTS serialization system filesystem REQUIRED)


catkin_package(
        #  INCLUDE_DIRS include
        #  LIBRARIES orbslam_server
        #  CATKIN_DEPENDS roscpp rospy std_msgs
        #  DEPENDS system_lib
        CATKIN_DEPENDS message_runtime corbslam_client
)

include_directories(
        ${catkin_INCLUDE_DIRS}
        ${Boost_INCLUDE_DIR}
        ${EIGEN3_INCLUDE_DIR}
        ${Pangolin_INCLUDE_DIRS}
        ${PROJECT_SOURCE_DIR}
        ${PROJECT_SOURCE_DIR}/include
)


set(corbslam_server_SOURCES
        ${PROJECT_SOURCE_DIR}/src/MapFusion.cpp
        ${PROJECT_SOURCE_DIR}/src/main.cpp
        ${PROJECT_SOURCE_DIR}/src/ServerMap.cpp
        ${PROJECT_SOURCE_DIR}/src/ServerMapView.cpp
        ${PROJECT_SOURCE_DIR}/src/PubToClient.cpp
        ${PROJECT_SOURCE_DIR}/src/GlobalOptimize.cpp
        )


add_executable(corbslam_server
        ${corbslam_server_SOURCES}
)
target_link_libraries(corbslam_server
        ${catkin_LIBRARIES}
        ${Boost_LIBRARIES}
        ${OpenCV_LIBS}
        ${EIGEN3_LIBS}
        ${Pangolin_LIBRARIES}

        /home/fabian/SLAM/ws/devel/lib/libgrpc++_unsecure.so
        )

client package with proto file:

cmake_minimum_required(VERSION 2.8)
project(corbslam_client)

IF (NOT CMAKE_BUILD_TYPE)
    SET(CMAKE_BUILD_TYPE Release)
ENDIF ()

MESSAGE("Build type: " ${CMAKE_BUILD_TYPE})

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}  -Wall -O3 -march=native ")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O3 -march=native ")

# Check C++11 or C++0x support
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if (COMPILER_SUPPORTS_CXX11)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
    add_definitions(-DCOMPILEDWITHC11)
    message(STATUS "Using flag -std=c++11.")
elseif (COMPILER_SUPPORTS_CXX0X)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
    add_definitions(-DCOMPILEDWITHC0X)
    message(STATUS "Using flag -std=c++0x.")
else ()
    message(FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif ()

## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages

LIST(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake_modules)

find_package(catkin REQUIRED COMPONENTS
        roscpp
        rospy
        cv_bridge
        std_msgs
        tf
        message_generation
	    genmsg
        pcl_conversions
        pcl_ros
        grpc
        )

find_package(OpenCV REQUIRED)
find_package(Eigen3 REQUIRED)
find_package(Pangolin REQUIRED)
find_package(Boost COMPONENTS serialization system filesystem REQUIRED)

## Generate messages in the 'msg' folder
add_message_files(
        DIRECTORY msg
        FILES
        corbslam_message.msg
)

## Generate services in the 'srv' folder
add_service_files(
        DIRECTORY srv
        FILES
        corbslam_insert.srv
        corbslam_update.srv
)

## Generate actions in the 'action' folder
# add_action_files(
#   FILES
#   Action1.action
#   Action2.action
# )

## Generate added messages and services with any dependencies listed here
generate_messages(
        DEPENDENCIES
        std_msgs
)

generate_proto(corb_proto GRPC proto/corbslam.proto)

catkin_package(
          INCLUDE_DIRS include
          LIBRARIES corbslam_client corb_proto
           CATKIN_DEPENDS roscpp rospy std_msgs message_runtime grpc
)

include_directories(
        ${catkin_INCLUDE_DIRS}
        ${PROJECT_SOURCE_DIR}
        ${PROJECT_SOURCE_DIR}/include
        ${EIGEN3_INCLUDE_DIRS}
        ${OpenCV_INCLUDE_DIRS}
        ${Pangolin_INCLUDE_DIRS}
        ${Boost_INCLUDE_DIRS}
)

## Declare a C++ library

LINK_DIRECTORIES(/usr/local/lib )


add_library(${PROJECT_NAME}
        src/System.cc
        src/Tracking.cc
        src/LocalMapping.cc
        src/LoopClosing.cc
        src/ORBextractor.cc
        src/ORBmatcher.cc
        src/FrameDrawer.cc
        src/Converter.cc
        src/MapPoint.cc
        src/KeyFrame.cc
        src/Map.cc
        src/MapDrawer.cc
        src/Optimizer.cc
        src/PnPsolver.cc
        src/Frame.cc
        src/KeyFrameDatabase.cc
        src/Sim3Solver.cc
        src/Initializer.cc
        src/Viewer.cc
        include/Cache.h
        src/Cache.cc
        include/LightKeyFrame.h
        src/LightKeyFrame.cc
        include/LightMapPoint.h
        src/LightMapPoint.cc
        include/SerializeObject.h
        include/DataDriver.h
        src/DataDriver.cc
        include/TransPose.h
        src/TransPose.cpp
        src/ProtoConversions.cpp)

target_link_libraries(${PROJECT_NAME}
        ${OpenCV_LIBRARIES}
        ${catkin_LIBRARIES}
        ${EIGEN3_LIBRARIES}
        ${Pangolin_LIBRARIES}
        ${Boost_LIBRARIES}
        corb_proto 
        )
add_dependencies(corbslam_client ${${PROJECT_NAME}_EXPORTED_TARGETS} ${catkin_EXPORTED_TARGETS})

Thank you. I was able to reproduce the issue. The problem is that when catkin_package exports libraries, it doesn't export the dependencies automatically. As a workaround, you can use the following code in your client package with proto:

find_package(catkin REQUIRED COMPONENTS grpc)

set(GRPC_LIB_DIR ${grpc_PREFIX}/${CATKIN_GLOBAL_LIB_DESTINATION})
find_library(
    LIBPROTOBUF libprotobuf.a PATHS ${GRPC_LIB_DIR}/protobuf NO_DEFAULT_PATH)
find_library(LIBZ z PATHS ${GRPC_LIB_DIR} NO_DEFAULT_PATH)

set(ALL_PROTOBUF_LIBS ${LIBPROTOBUF} ${LIBZ})
message(STATUS "Found protobuf libraries: ${ALL_PROTOBUF_LIBS}")

find_library(LIBARES ares PATHS ${GRPC_LIB_DIR} NO_DEFAULT_PATH)
find_library(LIBBORINGSSL boringssl PATHS ${GRPC_LIB_DIR} NO_DEFAULT_PATH)
find_library(LIBGPR gpr PATHS ${GRPC_LIB_DIR} NO_DEFAULT_PATH)
find_library(LIBGRPC grpc PATHS ${GRPC_LIB_DIR} NO_DEFAULT_PATH)
find_library(LIBGRPCPP grpc++ PATHS ${GRPC_LIB_DIR} NO_DEFAULT_PATH)
find_library(LIBGRPC_CRONET grpc_cronet PATHS ${GRPC_LIB_DIR} NO_DEFAULT_PATH)
find_library(LIBGRPCPP_CORE_STATS grpc++_core_stats
             PATHS ${GRPC_LIB_DIR} NO_DEFAULT_PATH)
find_library(LIBGRPCPP_CRONET grpc++_cronet
             PATHS ${GRPC_LIB_DIR} NO_DEFAULT_PATH)
find_library(LIBGRPCPP_ERROR_DETAILS grpc++_error_details
             PATHS ${GRPC_LIB_DIR} NO_DEFAULT_PATH)
find_library(LIBGRPC_PLUGIN_SUPPORT grpc_plugin_support
             PATHS ${GRPC_LIB_DIR} NO_DEFAULT_PATH)
find_library(LIBGRPCPP_REFLECTION grpc++_reflection
             PATHS ${GRPC_LIB_DIR} NO_DEFAULT_PATH)
find_library(LIBGRPC_UNSECURE grpc_unsecure
             PATHS ${GRPC_LIB_DIR} NO_DEFAULT_PATH)
find_library(LIBGRPCPP_UNSECURE grpc++_unsecure
             PATHS ${GRPC_LIB_DIR} NO_DEFAULT_PATH)

set(ALL_GRPC_LIBS ${LIBARES} ${LIBBORINGSSL} ${LIBGPR} ${LIBGRPC} ${LIBGRPCPP}
    ${LIBGRPC_CRONET} ${LIBGRPCPP_CRONET} ${LIBGRPCPP_CORE_STATS}
    ${LIBGRPCPP_ERROR_DETAILS} ${LIBGRPC_PLUGIN_SUPPORT} ${LIBGRPCPP_REFLECTION}
    ${LIBGRPC_UNSECURE} ${LIBGRPCPP_UNSECURE})
message(STATUS "Found grpc libraries: ${ALL_GRPC_LIBS}")

catkin_package(
  CATKIN_DEPENDS grpc
  LIBRARIES ${ALL_GRPC_LIBS} ${ALL_PROTOBUF_LIBS}
)

I will dig deeper into this to see what is the best way to handle this case.

Thank you very much for your prompt answers and the workaround!

In fact, all you need is

find_package(catkin REQUIRED COMPONENTS grpc)
catkin_package(
  CATKIN_DEPENDS grpc
  LIBRARIES ${ALL_GRPC_LIBS} ${ALL_PROTOBUF_LIBS}
)

I will update the README to reflect this.