CMake nested libraries

CMake nested libraries

本文关键字:libraries nested CMake      更新时间:2023-10-16

我有一个 c++ 项目,其中我的executable取决于我的core library,而该库依赖于另一个外部库,libtorrent它是否有任何相关性。

问题是我无法弄清楚如何设置我的CMakeLists.txt,我已经搜索了几天,但无济于事。

主要思想是core libraryexecutable位于单独的 git 存储库上,因此该库不是可执行文件的子 git 模块。

最好我能够使用 ExternalProject_Add 将core library添加到executable但是当我这样做时,executable抱怨它对核心库再次使用的libtorrent一无所知。将libtorrent的标头添加到可执行文件中是不够的,我还需要将executable链接到libtorrent。但是我为什么要编译core library,因为我只需要再次将core library的所有依赖项添加到executable

如果有人可以指出如何设置一个使用具有其他依赖项的核心库和使用核心库的可执行文件的项目的正确方向。

通常,这用目标和它们之间的链接表示。

您的设置可能如下所示:

#  core cmake file
find_package(LibtorrentRasterbar REQUIRED)
add_library(core_lib file1.cpp file2.cpp file3.cpp ...)
target_link_libraries(core_lib PUBLIC LibtorrentRasterbar::torrent-rasterbar) # see below
# app cmake file
find_package(core_lib) # find it elsewhere
add_executable(app file1.cpp file2.cpp file3.cpp ...)
target_link_libraries(exec PRIVATE core_lib::core_lib)

如果核心需要在其标头中创建新库,则应将它们添加到core_lib的依赖项中。任何公共需求都会传递到用户,例如app目标。

与外部库或构建树的偏差使用find_library表示。它可以是安装在根目录中的库,安装在项目子目录中的用户目录中,也可以只是库的构建树。在您的情况下,查找构建树可能是您想要的。

然后,由于您的core_lib库位于另一个项目中,我建议查看如何从构建树或安装中导出目标,以便find_package(core_lib)工作。


不幸的是,Libtorrent似乎没有正确支持 CMake,因此找不到包Libtorrent,也不会定义目标Libtorrent::torrent-rasterbar

有一些方法可以通过尝试他们的FindLibtorrentRasterbar.cmake来解决。

看看他们的查找模块,很明显它并没有考虑到现代cmake。如果文件支持链接到其目标,则必须在末尾添加这些行:

if(LibtorrentRasterbar_FOUND)
set(LibtorrentRasterbar_LIBRARY_DEPS "${LibtorrentRasterbar_LIBRARIES}")
list(REMOVE_ITEM LibtorrentRasterbar_LIBRARY_DEPS ${LibtorrentRasterbar_LIBRARY})
if(LibtorrentRasterbar_USE_STATIC_LIBS)
add_library(LibtorrentRasterbar::torrent-rasterbar STATIC IMPORTED GLOBAL)
else()
add_library(LibtorrentRasterbar::torrent-rasterbar SHARED IMPORTED GLOBAL)
endif()
set_target_properties(LibtorrentRasterbar::torrent-rasterbar PROPERTIES
IMPORTED_LOCATION ${LibtorrentRasterbar_LIBRARY}
INTERFACE_LINK_LIBRARIES ${LibtorrentRasterbar_LIBRARY_DEPS}
INTERFACE_COMPILE_DEFINITIONS ${LibtorrentRasterbar_DEFINITIONS}
INTERFACE_INCLUDE_DIRECTORIES ${LibtorrentRasterbar_INCLUDE_DIRS}
)
endif()

我没有提到的一个细节是,find_package不会尝试找到依赖项的包。为此,请创建一个如下所示的自定义配置文件:

# cmake/core_lib-config.cmake.in
include(CMakeFindDependencyMacro)
# this line is just like a find_package
# but made for transitivity
find_dependency(LibtorrentRasterbar)
include("${CMAKE_CURRENT_LIST_DIR}/core_lib-targets.cmake")

然后将导出更改为输出core_lib-targets.cmake而不是通常的配置:

# this is the new config file with the add_dependency
configure_file(
cmake/core_lib-config.cmake.in
core_lib-config.cmake
@ONLY
)
# the new config file will include this target file
install(EXPORT core_lib_targets
NAMESPACE core_lib::
FILE core_lib-targets.cmake
DESTINATION lib/cmake/core_lib)
# export the current build tree
export(
EXPORT core_lib_targets
NAMESPACE core_lib::
FILE "${CMAKE_CURRENT_BINARY_DIR}/core_lib-targets.cmake"
)