Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cmake: In which order do I have to specify TARGET_LINK_LIBRARIES

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).

like image 980
Anonymous Avatar asked Nov 10 '22 22:11

Anonymous


1 Answers

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!

like image 187
fenix688 Avatar answered Nov 14 '22 23:11

fenix688