2016-12-27 13 views
5

Mam prosty projekt, który wymaga trzech bibliotek tylko nagłówka w celu kompilacji: websocketpp, spdlog i nlohmann/json.Dodawanie zależności tylko nagłówka z CMake

Struktura projektu wygląda następująco:

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

CMakeLists.txt korzeń jest następujący:

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) 

Chodzi o to, że w zasadzie każdy podkatalog jest biblioteką (np core), oraz app "agreguje" wszystkie z nich. Każda biblioteka (np core) jest zbudowany tak (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) 

zauważyć, jak połączyć zależności (które są tylko nagłówek biblioteki!). W ten sposób mogę pobrać je (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() 

tej pory tak dobrze: widać zależności są naciągane jak git submodules, które na szczęście łatwiej nimi zarządzać. Jednak, kiedy mogę skompilować mój projekt z mkdir build && cd build && cmake ../src, mam następujące błędy:

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.

w tym np nagłówkami #include <spdlog/spdlog.h> lub #include <nlohmann/json.hpp> powoduje błąd informujący, że nagłówek nie został znaleziony.

Prawdę mówiąc, nie czuję się dobrze z CMake i spędziłem ostatnie dwa dni na debugowaniu tego. To może być naprawdę proste, ale nie potrafię tego zrozumieć. W rzeczywistości można by po prostu przekazać -I jako flagę kompilatora używać bibliotek tak, jak chcę, ale abstrakcja CMake wydaje się wprowadzać w błąd. Byłbym bardzo zadowolony, gdyby ktoś mógł wyjaśnić, dlaczego to nie działa i, miejmy nadzieję, jaki jest poprawny sposób włączenia tych bibliotek do mojego projektu. Z góry dziękuję!

Odpowiedz

1

Tak jak powiedziałeś: nie instalowałeś celów w zestawie eksportu. Innymi słowy, brakuje linii install(EXPORT ... dla celów związanych tylko z nagłówkiem. Na przykład, biorąc pod uwagę nagłówka tylko bibliotekę websocketpp, trzeba mieć:

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) 

samo dotyczy innych bibliotek.

+0

Dzięki, dodałem go, jednak otrzymuję ten sam komunikat dla biblioteki 'websocketpp':" Błąd CMake w rdzeniu/CMakeLists.txt: eksportowany z docelowym foo-core, który wymaga docelowego websocketpp, którego nie ma w export set "i" Jeśli wymagany cel nie jest łatwy do przypisania w tym wywołaniu, rozważ używając opcji APPEND z wieloma oddzielnymi połączeniami. ". Co dziwne, plik wydaje się być pod 'build/CMakeFiles/Export/share/websocketpp/cmake/websocketpp.cmake', dlaczego go nie znalazł? – arnaudoff

+0

@arnaudoff, który może pochodzić od nazwy pliku, który powinien być zgodny z danym wzorcem. Edytowałem swoją odpowiedź, spróbuj zmodyfikowanej nazwy 'websocketpp-config' – wasthishelpful

+0

Próbowałem, że też nie działa tak dobrze – arnaudoff

Powiązane problemy