【问题标题】:cmake: In which order do I have to specify TARGET_LINK_LIBRARIEScmake:我必须按哪个顺序指定 TARGET_LINK_LIBRARIES
【发布时间】:2015-01-26 01:07:17
【问题描述】:

由于必须以正确的顺序指定 TARGET_LINK_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)

由于只有在创建可执行文件时才链接所有必需的库,所以我必须在链接 myTarget(最终的可执行文件)时指定所有库:

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

由于我正在链接 boost static 我的 CMakeLists.txt 也包含

SET(Boost_USE_STATIC_LIBS ON) 

但是,我仍然遇到链接错误,例如“未定义对 boost::re_detail::perl_matcher 或 boost::date_time::month_formatter 的引用”

这真的很烦人,我正在更改库排序,一些未定义的引用消失了,但出现了新的未定义引用。

如何识别正确的顺序?!


编辑:

我通过分别绘制识别库之间的所有依赖关系并对其进行适当排序来解决上述问题(因此添加了 libboost_log.a):

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

所以排序是自上而下的。顶部是可执行文件,后面是直接使用的库。接下来是更多的依赖,最后必须添加低级依赖(由 boost 使用)。

【问题讨论】:

标签: c++ boost linker cmake


【解决方案1】:

就我而言,当我想尊重链接库的顺序时,我使用add_dependencies cmake 命令。我的意思是:

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

我没有测试过这段代码,但我会或多或少地测试它。我知道这个例子只是可能的 CMakeLists.txt 的一部分,所以我需要看到你的代码来完整地编写它。

希望对你有帮助!

【讨论】:

    猜你喜欢
    • 2018-02-16
    • 2012-01-26
    • 2011-10-22
    • 1970-01-01
    • 2017-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多