CMake:将第三方库链接到项目库

时间:2017-05-09 13:25:01

标签: c++ cmake static-libraries

我目前正在使用CMake作为其构建系统开发一个C ++项目。

项目由几个输出可执行文件组成,每个可执行文件具有相对较少的自定义代码,但利用了一些公共库:

programX
|
├── CMakeLists.txt (this contains the main executable targets)
|
├── Engine
│   ├── ...
│   ├── CMakeLists.txt
|
├── Utils
│   ├── third_party (this is what I added)
│   │   └── backward-cpp
│   |       └ CMakeLists.txt
│   ├── ...
│   └── CMakeLists.txt
|
└── etc.

项目的主要功能包含在Engine库中,该库使用类似target_link_libraries(programX Engine)的内容静态链接到主可执行文件。许多实用程序也包含在单独的Utils库中。

我已将CMake依赖项添加到其中一个项目库中(它是backward-cpp堆栈跟踪修饰符)。该项目也是使用CMake构建的。

为了模块化,我将backward-cpp项目作为依赖项添加到实际使用它的唯一项目库Utils。我这样做是为了不使用仅与项目的一小部分相关的指令“污染”主CMakeLists.txt文件。

我的Utils/CMakeLists.txt因此看起来像这样:

SET(UTILS_HEADERS ...)
set(UTILS_OBJECTS Dummy.cpp ${UTILS_HEADERS})

# This is the new dependency!
add_subdirectory(third_party/backward-cpp)

SOURCE_GROUP("" FILES ${UTILS_HEADERS})

# 'BACKWARD_ENABLE' and 'add_backward' are needed for linking.
add_library(Utils ${UTILS_OBJECTS} ${BACKWARD_ENABLE})
add_backward(Utils)

但是,这样做不起作用,项目最终没有链接(找不到backward-cpp库中的符号),除非我将输出可执行文件链接到第三方库直接位于根CMakeLists.txt文件(add_backward(MainExecutableA-Z))中。

我知道无法将静态库链接到其他静态库,但我有兴趣知道是否有一种很好的方法可以使用CMake实现静态库及其依赖项的模块化。

(或者,我总是可以直接将所有内容链接到主要目标,因为它始终有效。)

更新(2017年5月22日)

我已经设法让一切正常运行,backwards-cpp被“最窄”CMakeLists.txt文件100%控制,这要归功于我得到的有用答案。这是我最终得到的Utils/CMakeLists.txt文件(删除了非相关部分):

SET(UTILS_HEADERS ...)   
SET(UTILS_SOURCES ...)


# If enabled, enables sensible stack traces on Linux, complete with corresponding source
# code, where available. CUDA errors also produce complete stack traces when this is on.
# If disabled, the error messages degrade gracefully to file/line information.
OPTION(WITH_BACKWARDS_CPP "Build with backwards-cpp stack trace dumping library? (Linux-only)" TRUE)
message(STATUS "backwards-cpp-enhanced stack traces? " ${WITH_BACKWARDS_CPP})

if(WITH_BACKWARDS_CPP)
  # Support 'backward-cpp,' a lean stacktrace printing library for Linux.
  add_definitions(-DWITH_BACKWARDS_CPP)
  add_subdirectory(third_party/backward-cpp)
endif()

SOURCE_GROUP("" FILES ${UTILS_HEADERS} ${UTILS_SOURCES})
add_library(Utils ${UTILS_HEADERS} ${UTILS_SOURCES})

# ...unrelated CUDA stuff...

if(WITH_BACKWARDS_CPP)
  # Link agains libbfd to ensure backward-cpp can extract additional information from the binary,
  # such as source code mappings. The '-lbfd' dependency is optional, and if it is disabled, the
  # stack traces will still work, but won't show unmangled symbol names or source code snippets.
  # You may need to set BACKWARD_USE_BFD to 0 in its `hpp` and `cpp` files to avoid linker errors.
  target_link_libraries(Utils PUBLIC -lbfd)
  target_link_libraries(Utils PUBLIC backward)
endif()

2 个答案:

答案 0 :(得分:1)

阅读README of backward-cpp之后,我会尝试以下方法(只改变最后两行):

SET(UTILS_HEADERS ...)
set(UTILS_OBJECTS Dummy.cpp ${UTILS_HEADERS})

# This is the new dependency!
add_subdirectory(third_party/backward-cpp)

SOURCE_GROUP("" FILES ${UTILS_HEADERS})

add_library(Utils ${UTILS_OBJECTS})
target_link_libraries(Utils PUBLIC backward)

请注意,当您将其他目标与PUBLIC相关联时,最后一个语句中的Utils会设置包含目录和链接库。

答案 1 :(得分:1)

在查看BackwardConfig.cmake并阅读项目README后,我得出的结论是,将您的可执行文件与 Backward-cpp 链接起来的最简单方法是使用您在问题中提到的add_backward(target)宏。

README shuld作品中修改CMAKE_MODULE_PATH 字幕下描述的另一个选项,但我没有测试过。 Config 模式中的find_package将搜索名为<name>Config.cmake的文件,在这种情况下为BackwardConfig.cmake,因此您无需编写任何额外的CMake模块,例如FindBackward.cmake。试一试,我会做以下事情:

set(UTILS_HEADERS ...)
set(UTILS_OBJECTS Dummy.cpp ${UTILS_HEADERS})

source_group("" FILES ${UTILS_HEADERS})
add_library(Utils ${UTILS_OBJECTS})

list(APPEND CMAKE_MODULE_PATH /path/to/backward-cpp)
find_package(Backward)

target_link_libraries(Utils PUBLIC Backward::Backward)