使用CMAKE添加仅汇编依赖项
Adding header-only dependencies with CMake
我有一个简单的项目,该项目需要三个仅标题库才能编译:websocketpp,spdlog和nlohmann/json。
项目结构看起来像这样:
└── src
├── app
│ ├── CMakeLists.txt
│ ├── src
│ └── test
├── CMakeLists.txt
├── core
│ ├── CMakeLists.txt
│ ├── include
│ ├── src
│ └── test
└── vendor
├── install.cmake
├── nlohmann_json
├── spdlog
└── websocketpp
root cmakelists.txt如下:
cmake_minimum_required(VERSION 3.6.1 FATAL_ERROR)
..
# External 3rd party libs that we include
include(vendor/install.cmake)
add_subdirectory(core)
add_subdirectory(app)
基本上,每个子目录都是一个库(例如 core
),而 app
"汇总"全部。每个库(例如core
)都是这样构建的(core/CMakeLists.txt
):
project(foo-core VERSION 0.1 LANGUAGES CXX)
add_library(foo-core
src/foobar/foobar.cc
src/foobaz/baz.cc)
target_include_directories(foo-core PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
PRIVATE src)
target_link_libraries(foo-core websocketpp spdlog) # <- see here, using spdlog & websocketpp
# 'make install' to the correct location
install(TARGETS foo-core EXPORT FooCoreConfig
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib
RUNTIME DESTINATION bin)
install(DIRECTORY include/ DESTINATION include)
install(EXPORT FooCoreConfig DESTINATION share/FooCore/cmake)
export(TARGETS foo-core FILE FooCoreConfig.cmake)
注意我如何链接依赖项(仅标题库!)。这就是我获取他们的方式(vendor/install.cmake
):
# spdlog
if((NOT SPDLOG_INCLUDE_DIR) OR (NOT EXISTS ${SPDLOG_INCLUDE_DIR}))
message("Unable to find spdlog, cloning...")
execute_process(COMMAND git submodule update --init -- vendor/spdlog
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
set(SPDLOG_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/spdlog/include/
CACHE PATH "spdlog include directory")
install(DIRECTORY ${SPDLOG_INCLUDE_DIR}/spdlog DESTINATION include)
# Setup a target
add_library(spdlog INTERFACE)
target_include_directories(spdlog INTERFACE
$<BUILD_INTERFACE:${SPDLOG_INCLUDE_DIR}>
$<INSTALL_INTERFACE:include>)
install(TARGETS spdlog EXPORT spdlog DESTINATION include)
endif()
# websocketpp
if((NOT WEBSOCKETPP_INCLUDE_DIR) OR (NOT EXISTS ${WEBSOCKETPP_INCLUDE_DIR}))
message("Unable to find websocketpp, cloning...")
execute_process(COMMAND git submodule update --init -- vendor/websocketpp
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
set(WEBSOCKETPP_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/vendor/websocketpp/
CACHE PATH "websocketpp include directory")
install(DIRECTORY ${WEBSOCKETPP_INCLUDE_DIR}/websocketpp DESTINATION include)
# Setup a target
add_library(websocketpp INTERFACE)
target_include_directories(websocketpp INTERFACE
$<BUILD_INTERFACE:${WEBSOCKETPP_INCLUDE_DIR}>
$<INSTALL_INTERFACE:include>)
install(TARGETS websocketpp EXPORT websocketpp DESTINATION include)
endif()
# nlohmann/json
if((NOT NLOHMANN_JSON_INCLUDE_DIR) OR (NOT EXISTS ${NLOHMANN_JSON_INCLUDE_DIR}))
message("Unable to find nlohmann/json, cloning...")
execute_process(COMMAND git submodule update --init -- vendor/nlohmann_json
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
set(NLOHMANN_JSON_INCLUDE_DIR
${CMAKE_CURRENT_SOURCE_DIR}/vendor/nlohmann_json/src/
CACHE PATH "nlohmann/json include directory")
install(FILES ${NLOHMANN_JSON_INCLUDE_DIR}/json.hpp DESTINATION include)
# Setup a target
add_library(nlohmann_json INTERFACE )
target_include_directories(nlohmann_json INTERFACE
$<BUILD_INTERFACE:${NLOHMANN_JSON_INCLUDE_DIR}>
$<INSTALL_INTERFACE:include>)
install(TARGETS nlohmann_json EXPORT nlohmann_json DESTINATION include)
endif()
到目前为止很好:您可以看到依赖项被以git子模型为单位,值得庆幸的是,这使管理它们更容易。但是,当我用mkdir build && cd build && cmake ../src
编译项目时,我会有以下错误:
cmake错误:安装(导出foocoreconfig ...)包括目标 需要不在导出中的目标WebSocketpp的foo-core 设置。
cmake错误:安装(导出foocoreconfig ...)包括目标 foo-core需要不在导出集中的目标spdlog。
包括标题,例如#include <spdlog/spdlog.h>
或#include <nlohmann/json.hpp>
产生错误,说找不到标题。
说实话,我对Cmake不太满意,并且在过去的两天里,我一直在调试。这可能很简单,但是我不知道如何实现它。实际上,一个人只会通过-i作为编译器标志来使用我想要的图书馆,但是cmake抽象似乎使我感到困惑。如果有人能够解释为什么这不起作用,我会很高兴,希望将这些图书馆纳入我的项目的正确方法是什么。预先感谢!
正如您所说的那样:您没有在导出集中安装目标。换句话说,您错过了仅针对标题目标的install(EXPORT ...
行。例如,考虑您的仅标题库websocketpp
,您应该有:
add_library(websocketpp INTERFACE)
target_include_directories(websocketpp INTERFACE
$<BUILD_INTERFACE:${WEBSOCKETPP_INCLUDE_DIR}>
$<INSTALL_INTERFACE:include>)
install(TARGETS websocketpp EXPORT websocketpp-config DESTINATION include)
# here is the missing line:
install(EXPORT websocketpp-config DESTINATION share/websocketpp/cmake)
其他库也是如此。
- 如何从C++中的依赖类型中获得它所依赖的类型
- 将--whole archive链接器选项与CMake和具有其他库依赖项的库一起使用
- 将依赖名称显式标记为类型名和模板的奇怪之处
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- C++GTKMM gui循环依赖关系
- 通过ccmake在cmake中缓存依赖选项
- 当基类是依赖类型时,这是一个缺陷吗
- 从不同的附加依赖项中识别等同命名的函数
- 为什么我的C++程序的程序集输出充满了 .ascii,没有汇编代码?
- 如何在 CMake 中对目标依赖项进行分组?
- 是否可以依赖函数范围的静态变量来执行程序关闭期间调用的方法?
- 为什么构建目录中新构建的共享库与安装目录中的副本具有不同的依赖项集?
- VS 2015 链接错误 无法构建依赖于 libcurl 的项目
- 通过依赖类型使用非类型模板参数的单类型模板参数类模板的部分专用化
- 为什么内存屏障依赖于变量?
- node-gyp 的先有鸡还是先有蛋的问题:指向依赖项中的头文件
- 在 emscripten 网页汇编正在运行期间更新进度条?
- 在Visual Studio中相互依赖的项目的并行汇编
- 使用CMAKE添加仅汇编依赖项
- 文件和丘疹成语之间的汇编依赖关系