# Undefined Reference in Linking Using colcon

Background: I work in underwater robotics, and DCCL is a library for encoding of messages to fit within our extremely constrained message sizes based on an original protobuf format. Just for practice before applying this to one of our real messages, I'm modifying the basic publisher/subscriber from the tutorial to encode the message to DCCL before sending. It seems to do just fine with the protobuf library, but I'm getting an undefined reference error on the DCCL library, which I assuming is a linking error.

Error:

teddybouch@Norby:~/workspace/ros2_ws$colcon build --packages-select cpp_pubsub Starting >>> cpp_pubsub --- stderr: cpp_pubsub /usr/bin/ld: CMakeFiles/talker.dir/src/publisher_member_function.cpp.o: in function MinimalPublisher::timer_callback()': publisher_member_function.cpp:(.text._ZN16MinimalPublisher14timer_callbackEv[_ZN16MinimalPublisher14timer_callbackEv]+0xa2): undefined reference to dccl::Codec::Codec(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)' /usr/bin/ld: publisher_member_function.cpp:(.text._ZN16MinimalPublisher14timer_callbackEv[_ZN16MinimalPublisher14timer_callbackEv]+0xed): undefined reference to testdccl::NavigationReport::NavigationReport()' /usr/bin/ld: publisher_member_function.cpp:(.text._ZN16MinimalPublisher14timer_callbackEv[_ZN16MinimalPublisher14timer_callbackEv]+0x1d5): undefined reference to dccl::Codec::encode(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >*, google::protobuf::Message const&, bool, int)' /usr/bin/ld: publisher_member_function.cpp:(.text._ZN16MinimalPublisher14timer_callbackEv[_ZN16MinimalPublisher14timer_callbackEv]+0x3b7): undefined reference to testdccl::NavigationReport::~NavigationReport()' /usr/bin/ld: publisher_member_function.cpp:(.text._ZN16MinimalPublisher14timer_callbackEv[_ZN16MinimalPublisher14timer_callbackEv]+0x3c6): undefined reference to dccl::Codec::~Codec()' /usr/bin/ld: publisher_member_function.cpp:(.text._ZN16MinimalPublisher14timer_callbackEv[_ZN16MinimalPublisher14timer_callbackEv]+0x48b): undefined reference to testdccl::NavigationReport::~NavigationReport()' /usr/bin/ld: publisher_member_function.cpp:(.text._ZN16MinimalPublisher14timer_callbackEv[_ZN16MinimalPublisher14timer_callbackEv]+0x4a3): undefined reference to dccl::Codec::~Codec()' /usr/bin/ld: CMakeFiles/talker.dir/src/publisher_member_function.cpp.o: in function void dccl::Codec::load<testdccl::NavigationReport>()': publisher_member_function.cpp:(.text._ZN4dccl5Codec4loadIN8testdccl16NavigationReportEEEvv[_ZN4dccl5Codec4loadIN8testdccl16NavigationReportEEEvv]+0x11): undefined reference to testdccl::NavigationReport::descriptor()' /usr/bin/ld: publisher_member_function.cpp:(.text._ZN4dccl5Codec4loadIN8testdccl16NavigationReportEEEvv[_ZN4dccl5Codec4loadIN8testdccl16NavigationReportEEEvv]+0x28): undefined reference to dccl::Codec::load(google::protobuf::Descriptor const*, int)' collect2: error: ld returned 1 exit status make[2]: *** [CMakeFiles/talker.dir/build.make:132: talker] Error 1 make[1]: *** [CMakeFiles/Makefile2:82: CMakeFiles/talker.dir/all] Error 2 make: *** [Makefile:141: all] Error 2 --- Failed <<< cpp_pubsub [0.97s, exited with code 2] Summary: 0 packages finished [1.16s] 1 package failed: cpp_pubsub 1 package had stderr output: cpp_pubsub  Except for the addition of the proto directory and the protobuf message definition file in it, I think that the only relevant changes are in the CMakeLists.txt and publisher_member_function.cpp, which I'm including below, but if I've missed something or anyone wants all the code for some reason, the whole package is on my Dropbox here. CMakeLists.txt: cmake_minimum_required(VERSION 3.5) project(cpp_pubsub) # Default to C99 if(NOT CMAKE_C_STANDARD) set(CMAKE_C_STANDARD 99) endif() # Default to C++14 if(NOT CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) endif() if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") add_compile_options(-Wall -Wextra -Wpedantic) endif() # find dependencies find_package(ament_cmake REQUIRED) find_package(rclcpp REQUIRED) find_package(std_msgs REQUIRED) find_package(dccl REQUIRED) message(STATUS "Using DCCL in${DCCL_DIR}")
find_package(Protobuf REQUIRED)

if(NOT DEFINED DCCL_INCLUDE_DIR)
get_target_property(DCCL_INCLUDE_DIR dccl INTERFACE_INCLUDE_DIRECTORIES)
endif()

if(DCCL_INCLUDE_DIR)
message ...
edit retag close merge delete

Sort by » oldest newest most voted

TLDR, these are the lines you've got to change in your CMakeLists.txt:

add_executable(talker src/publisher_member_function.cpp)
ament_target_dependencies(talker rclcpp std_msgs)  # Remove dccl and Protobuf


In more detail:

There seems to be two issues in the error log you posted:

1. Not linking against dccl correctly

and they are both related to linking, as you suspected.

In regards to not linking against dccl correctly - dccl is a pure CMake package (doesn't follow ament guidelines), and so you have to use target_link_libraries instead of ament_target_dependencies. There is no issue calling one after the other on the same target (ie. talker).

In regards to not linking against your proto file correctly - you have to use target_link_libraries to link against the target (ie. proto) you generate from the proto file in the line - add_library(proto.... Note that you already have Protobuf linked to the proto target, so if you link the talker to the proto` target, you don't need to link Protobuf.

more

1

Thank you so much! Not only did this fix the immediate problem, but your explanation was excellent and helped me understand the context a lot better as well!

( 2022-05-08 14:02:56 -0500 )edit