arn*_*off 10 c++ cmake spdlog nlohmann-json
我有一个简单的项目,需要三个只有头的库才能编译: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
Run Code Online (Sandbox Code Playgroud)
根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)
Run Code Online (Sandbox Code Playgroud)
这个想法基本上是每个子目录都是一个库(例如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)
Run Code Online (Sandbox Code Playgroud)
请注意我如何链接依赖项(它们是仅限标头的库!).这是我获取它们的方式(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()
Run Code Online (Sandbox Code Playgroud)
到目前为止一切都那么好:你可以看到依赖项被作为git子模块获取,值得庆幸的是它更容易管理它们.但是,当我编译我的项目时mkdir build && cd build && cmake ../src
,我有以下错误:
CMake错误:安装(EXPORT FooCoreConfig ...)包括目标foo-core,它需要不在导出集中的目标websocketpp.
CMake错误:安装(EXPORT 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)
Run Code Online (Sandbox Code Playgroud)
其他图书馆也是如此。
归档时间: |
|
查看次数: |
4290 次 |
最近记录: |