CMake - 如何组织依赖项

Ale*_*tev 5 c++ cmake

所以我试图了解我的一个 C++ 项目出了什么问题。基本上,项目 1 工作正常,一切都很好。在项目的主头文件中,我有

#include "spdlog/spdlog.h"
Run Code Online (Sandbox Code Playgroud)

我在项目 1 中将 spdlog 作为子项目。此外,在我的项目 1 的 CMake 中,我有include_directories(spdlog/include). 现在,我正在构建项目 2,它依赖于项目 1 并将其作为子项目。但是,当我尝试包含spdlog它时,它不允许我并希望我将完整的../project1/spdlog/include/spdlog.h. 组织这种依赖关系并包含标题的正确方法是什么?

小智 1

您应该寻找现代 cmake 资源。在现代 cmake 风格中,您可以为 spdlog 创建一个导入目标,然后您可以在其他地方使用它。

让我们假设以下结构

external/spdlog
external/CMakeLists.txt
project1/CMakeLists.txt
project2/CMakeLists.txt
CMakeLists.txt
Run Code Online (Sandbox Code Playgroud)

在external/CMakeLists.txt你写的

## add the imported library which is 
##   an INTERFACE (ie header only)
##   IMPORTED (ie third party - no compilation necessary)
##   GLOBAL (you can reference it from everywhere 
##           even if the target is not in the same scope
##           which is the case for project1 and project2 because 
##           the spdlog  target is not in their parent folder)
add_library(spdlog INTERFACE IMPORTED GLOBAL)
## set the include directory which is to be associated with this target
## and which will be inherited by all targets which use 
## target_link_libraries(<target> spdlog)
target_include_directories(spdlog INTERFACE spdlog/include)
Run Code Online (Sandbox Code Playgroud)

在根目录中CMakeLists.txt编写解决方案配置(示例)

project(mysolution)
add_subdirectory(external)
add_subdirectory(project1)
add_subdirectory(project2)
Run Code Online (Sandbox Code Playgroud)

在您的项目中,CMakeLists.txt您现在可以使用您在中创建的目标external

项目1/CMakeLists.txt

add_library(project1 ${Sources})
## this will set the include directories configured in the spdlog target (library) 
## and also ensure that targets depending on target1 will have access to spdlog  
## (if PUBLIC were changed to PRIVATE then you could only use spdlog in 
## project1 and dependeing targets like project2 would not 
## inherit the include directories from spdlog it wouldn't 
target_link_libraries(project1 PUBLIC spdlog)
Run Code Online (Sandbox Code Playgroud)

项目2/CMakeLists.txt

add_library(project2 ${Sources})
## this will link project1 which in return also links spdlog
## so that now project2 also has the include directories (because it was inherited)
## also targets depending on project2 will inherit everything from project1 
## and spdlog because of the PUBLIC option
target_link_libraries(project2 PUBLIC project1)
Run Code Online (Sandbox Code Playgroud)

来源:

[0] https://cmake.org/cmake/help/v3.9/command/add_library.html

[1] https://cmake.org/cmake/help/v3.9/command/target_link_libraries.html?highlight=target_link_libraries

[2] http://thetoeb.de/2016/08/30/modern-cmake-presentation/ (参见从幻灯片 20 开始的演示)