2016-12-27 18 views
5

Tôi có một dự án đơn giản yêu cầu ba thư viện chỉ tiêu đề để biên dịch: websocketpp, spdlognlohmann/json.Thêm phụ thuộc chỉ tiêu đề với CMake

Cấu trúc dự án trông như thế này:

└── src 
    ├── app 
    │   ├── CMakeLists.txt 
    │   ├── src 
    │   └── test 
    ├── CMakeLists.txt 
    ├── core 
    │   ├── CMakeLists.txt 
    │   ├── include 
    │   ├── src 
    │   └── test 
    └── vendor 
     ├── install.cmake 
     ├── nlohmann_json 
     ├── spdlog 
     └── websocketpp 

Các CMakeLists.txt gốc như sau:

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) 

Ý tưởng cơ bản là mỗi thư mục con là một thư viện (ví dụ core), và app "tổng hợp" tất cả chúng. Mỗi thư viện (ví dụ core) được xây dựng như thế này (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) 

Thông báo như thế nào để tôi liên kết phụ thuộc (trong đó có tiêu đề chỉ thư viện!). Đây là cách tôi lấy họ (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() 

Cho đến nay rất tốt: bạn sẽ nhìn thấy phụ thuộc được lấy như submodules git, mà may mắn làm cho nó dễ dàng hơn để quản lý chúng. Tuy nhiên, khi tôi biên soạn dự án của mình với mkdir build && cd build && cmake ../src, tôi có các lỗi sau:

CMake Error: install(EXPORT FooCoreConfig ...) includes target foo-core which requires target websocketpp that is not in the export set.

CMake Error: install(EXPORT FooCoreConfig ...) includes target foo-core which requires target spdlog that is not in the export set.

Bao gồm các tiêu đề, ví dụ: #include <spdlog/spdlog.h> hoặc #include <nlohmann/json.hpp> sản xuất lỗi nói rằng không tìm thấy tiêu đề.

Thật ra, tôi không thoải mái với CMake và tôi đã dành hai ngày qua để gỡ lỗi này. Nó có thể là một cái gì đó thực sự đơn giản, nhưng tôi không thể tìm ra cách để đạt được nó. Trong thực tế, một người sẽ chỉ chuyển qua -I như một lá cờ trình biên dịch để sử dụng các thư viện như tôi muốn, nhưng sự trừu tượng CMake dường như làm tôi bối rối. Tôi sẽ rất vui nếu có ai đó có thể giải thích tại sao điều này không hiệu quả và hy vọng, cách chính xác để đưa những thư viện này vào dự án của tôi là gì. Cảm ơn trước!

Trả lời

1

Giống như bạn đã nói: bạn không cài đặt các mục tiêu của mình trong bộ xuất. Nói cách khác, bạn thiếu dòng install(EXPORT ... cho các mục tiêu chỉ tiêu đề của mình. Ví dụ: xem xét thư viện chỉ tiêu đề của bạn websocketpp, bạn phải có:

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) 

Tương tự với các thư viện khác.

+0

Cảm ơn, tôi đã thêm nó, tuy nhiên, tôi nhận được cùng một thông báo cho thư viện 'websocketpp':" Lỗi CMake trong lõi/CMakeLists.txt: xuất được gọi với đích foo-core yêu cầu target websocketpp không có trong bộ xuất "và" Nếu mục tiêu được yêu cầu không dễ tham khảo trong cuộc gọi này, hãy xem xét bằng tùy chọn PHỤ LỤC với nhiều cuộc gọi riêng biệt ". Rất lạ, tệp có vẻ nằm trong 'build/CMakeFiles/Export/share/websocketpp/cmake/websocketpp.cmake', tại sao nó không tìm thấy nó? – arnaudoff

+0

@arnaudoff có thể đến từ tên của tệp, phải theo một mẫu nhất định. Tôi đã chỉnh sửa câu trả lời của mình, hãy thử với tên đã sửa đổi 'websocketpp-config' – wasthishelpful

+0

Đã thử rằng quá, không hoạt động tốt – arnaudoff

Các vấn đề liên quan