I am struggling again and again with linker problems since one has to specify all libraries within TARGET_LINK_LIBRARIES in the correct order. But how can I determine this order? Example:
I have the following libraries
libA depends on boost
libB depends on postgresql and libA (and therefore on boost)
myTarget uses libA, libB and boost directly (and through libB depends on postgresql)
Since all required libaries are only linked if an executable is created I have to specifiy all libraries when linking myTarget (the final executable):
TARGET_LINK_LIBRARIES(${ApplicationName}
libboost_program_options.a
libboost_system.a
libboost_filesystem.a
libboost_date_time.a
libboost_regex.a
# Should include all boost libraries but strangely some libs (the ones above)
# need to be specified "by hand"???
${Boost_LIBRARIES}
# PostgreSQL stuff
libpq.a
libsoci_core.a
libsoci_postgresql.a
libpq.so
# My libs
libB.a
libA.a
${CMAKE_THREAD_LIBS_INIT} # pthreads, needed by boost
${CMAKE_DL_LIBS} # For libdl.so etc.
)
Since I am linking boost static my CMakeLists.txt also contains
SET(Boost_USE_STATIC_LIBS ON)
However, I still get linking errors such as "undefined references to boost::re_detail::perl_matcher or boost::date_time::month_formatter"
This is really annoying, I am changing the lib ordering and some undefined references disappear but new undefined references appear.
How can I identify the correct ordering?!
EDIT:
I solved the problem above by drawing respectively identifying all dependencies between the libs and ordering them appropriately (therefore libboost_log.a has been added):
TARGET_LINK_LIBRARIES(${ApplicationName}
libB.a
libA.a
# PostgreSQL stuff
libpq.a
libsoci_core.a
libsoci_postgresql.a
libpq.so
# Boost
libboost_program_options.a
libboost_system.a
libboost_log.a
libboost_filesystem.a
libboost_date_time.a
libboost_regex.a
# Should include all boost libraries but strangely some libs (the ones above)
# need to be specified "by hand"???
${Boost_LIBRARIES}
# Lowlevel needed by boost
${CMAKE_THREAD_LIBS_INIT} # pthreads, needed by boost
${CMAKE_DL_LIBS} # For libdl.so etc.
)
So the ordering is top down. Top is the executable, followed by directly used libraries. Further dependencies follow and finally at the end one has to add low level dependencies (used by boost).
In my case, when I want to respect the order to link my libraries, I use add_dependencies cmake command. I mean:
find_package(Boost COMPONENTS date_time filesystem system ...)
find_package(PostgreSQL REQUIRED)
IF(Boost_FOUND AND PostgreSQL_FOUND)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
INCLUDE_DIRECTORIES(${PostgreSQL_INCLUDE_DIRS})
# ApplicationName -> your_application
# LIB_A_TARGET -> libA
# LIB_B_TARGET -> libB
SET(LIB_A_ALL_DEPS ${Boost_LIBRARIES})
SET(LIB_B_ALL_DEPS ${LIB_A_ALL_DEPS} ${PostgreSQL_LIBRARIES})
SET(EXTRA_APP_DEPS ) # here all your extra libs that they aren't in boost or postgre
SET(YOUR_APP_ALL_DEPS ${LIB_A_ALL_DEPS} ${LIB_B_ALL_DEPS} ${EXTRA_APP_DEPS})
# Here'll be all your ADD_EXECUTABLE, ADD_LIBRARY code
TARGET_LINK_LIBRARIES(${LIB_A_TARGET} ${LIB_A_ALL_DEPS})
ADD_DEPENDENCIES(${LIB_A_TARGET} ${LIB_A_ALL_DEPS})
TARGET_LINK_LIBRARIES(${LIB_B_TARGET} ${LIB_B_ALL_DEPS})
ADD_DEPENDENCIES(${LIB_B_TARGET} ${LIB_B_ALL_DEPS})
TARGET_LINK_LIBRARIES(${ApplicationName} ${YOUR_APP_ALL_DEPS})
ADD_DEPENDENCIES(${ApplicationName} ${YOUR_APP_ALL_DEPS})
ENDIF()
I've not tested this code but I'll do it more or less. I know this example is only a part of the possible CMakeLists.txt so I would need see your code for writing it entirely.
I hope it helps you!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With