Undefined Reference to Symbol '<Symbol>' ... Error Adding Symbols: DSO Missing From Command Line (With CMake)

Viewed 1452

Quick overview of the problem:

I am writing a project and was able to get the code I had written (so far) to compile, so I thought to myself I should start writing an example executable to make sure everything is working as I intended. I am a novice at C++ and even more of a novice at CMake (so forgive me if the code doesn't look well). After creating the ground work for the executable file I decided to make it and I ended up getting the error:

/usr/bin/ld: CMakeFiles/oneLinkAdaptive.dir/oneLinkAdaptiveExample.cpp.o: undefined reference to symbol '_ZN5robot12configurator16initializeParamsEPKc'
/usr/bin/ld: //home/pi/Desktop/cfucr/build/src/configurator/libconfigurator-libs.so: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make[2]: *** [src/examples/CMakeFiles/oneLinkAdaptive.dir/build.make:86: src/examples/oneLinkAdaptive] Error 1
make[1]: *** [CMakeFiles/Makefile2:46987: src/examples/CMakeFiles/oneLinkAdaptive.dir/all] Error 2
make: *** [Makefile:130: all] Error 2

From my understanding this is actually a CMake error and that I'm either failing to add a library or maybe I am failing to find a function in my C++ code I wrote(?):

namespace robot
{
namespace configurator
{

std::tuple<ParamsR, ParamsF, ParamsC> initializeParams(const char* configFile);
...

(I am less inclined to believe the C++ code is what's wrong, but honestly I have no idea at this point.) I have done some snooping around online and tried some things from other posts, i.e., moving the library around to make sure the libsconfigurator-libs library was being creating before adding the executable to CMake, checking to make sure I was actually including the libsconfigurator-libs library, changing things from PRIVATE to PUBLIC, etc.

The main src CMake file is written as:

# Add controller main files #
add_library(cfucr-libs
  controller.cpp
  controller.hpp
)

# Add the `src` directory to be included #
set(CFUCR_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})

include_directories(
  ${CFUCR_BASE_DIR}
)

# Add a list of subdirectories #
add_subdirectory(configurator)
add_subdirectory(control)
add_subdirectory(filter)
add_subdirectory(mathUtilities)
add_subdirectory(thirdParty)
add_subdirectory(types)

target_link_libraries(cfucr-libs PRIVATE
  configurator-libs
  control-libs
  filter-libs
  math-utilities-libs
  type-libs
  tinyxml2
  eigen
)

add_subdirectory(examples)

The executable file is located down in the examples sub-directory, so I moved that add_subdirectory to the bottom of the file. That way, I could make sure to add all of the other libraries I created to the main cfucr library. The examples CMake file is written as:

# Add controller example main files #
add_library(examples-libs
  oneLinkAdaptiveExample.cpp
)

# Make executable files for controller examples #
add_executable(oneLinkAdaptive
  oneLinkAdaptiveExample.cpp
)

target_link_libraries(oneLinkAdaptive PRIVATE
  cfucr-libs
  examples-libs
)

Basically, to just create the executable and add the main library to it. The configurator library is super simple and is given as:

# Add configurator files #
add_library(configurator-libs
  configurator.cpp
  configurator.hpp
)

I have been trying to fix this for a bit now but nothing seems to work/I don't fully understand how all of this works to really be able to fix the problem on my own. If anyone has any ideas on what I might be doing incorrectly I would love to hear it. Also, if I need to post anything else (any more CMake files or source files) to help make things clearer let me know and I will post them!

Thank you!

1 Answers

You should try changing this call to target_link_libraries:

target_link_libraries(cfucr-libs PRIVATE
  configurator-libs
  control-libs
  filter-libs
  math-utilities-libs
  type-libs
  tinyxml2
  eigen
)

to use PUBLIC instead:

target_link_libraries(cfucr-libs PUBLIC
  configurator-libs
  control-libs
  filter-libs
  math-utilities-libs
  type-libs
  tinyxml2
  eigen
)

With PRIVATE, the listed libraries (e.g. configurator-libs) are not made part of the link interface. So, consuming CMake targets (e.g. your executable) will not have visibility of these libraries and their definitions. With PUBLIC, the listed libraries are added to the link interface, so your executable oneLinkAdaptive consumes them also when you link cfucr-libs to it.

I encourage you to read through the target_link_libraries documentation, particularly the linked section describing the differences between the scoping keywords (i.e. PUBLIC, PRIVATE, etc).

Related