title: Adding header-only dependencies with CMake
body: <p>I have a simple project which requires three header-only libraries in order to compile: <a href="https://github.com/zaphoyd/websocketpp" rel="noreferrer">websocketpp</a>, <a href="https://github.com/gabime/spdlog" rel="noreferrer">spdlog</a> and <a href="https://github.com/nlohmann/json" rel="noreferrer">nlohmann/json</a>.</p>
  
  <p>The project structure looks like this:</p>
  
  <pre><code>└── src
      ├── app
      │   ├── CMakeLists.txt
      │   ├── src
      │   └── test
      ├── CMakeLists.txt
      ├── core
      │   ├── CMakeLists.txt
      │   ├── include
      │   ├── src
      │   └── test
      └── vendor
          ├── install.cmake
          ├── nlohmann_json
          ├── spdlog
          └── websocketpp
  </code></pre>
  
  <p>The root CMakeLists.txt is as follows:</p>
  
  <pre><code>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)
  </code></pre>
  
  <p>The idea is basically that each subdirectory is a library (e.g. <code>core</code>), and <code>app</code> "aggregates" all of them. Each library (e.g. <code>core</code>) is built like this (<code>core/CMakeLists.txt</code>):</p>
  
  <pre><code>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
    $&lt;BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include&gt;
    $&lt;INSTALL_INTERFACE:include&gt;
    PRIVATE src)
  
  target_link_libraries(foo-core websocketpp spdlog) # &lt;- see here, using spdlog &amp; 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)
  </code></pre>
  
  <p>Notice how I link the dependencies (which are header-only libraries!). This is how I fetch them (<code>vendor/install.cmake</code>):</p>
  
  <pre><code># 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
      $&lt;BUILD_INTERFACE:${SPDLOG_INCLUDE_DIR}&gt;
      $&lt;INSTALL_INTERFACE:include&gt;)
  
    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
      $&lt;BUILD_INTERFACE:${WEBSOCKETPP_INCLUDE_DIR}&gt;
      $&lt;INSTALL_INTERFACE:include&gt;)
  
    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
      $&lt;BUILD_INTERFACE:${NLOHMANN_JSON_INCLUDE_DIR}&gt;
      $&lt;INSTALL_INTERFACE:include&gt;)
  
    install(TARGETS nlohmann_json EXPORT nlohmann_json DESTINATION include)
  endif()
  </code></pre>
  
  <p>So far so good: you can see the dependencies are fetched as git submodules, which thankfully makes it easier to manage them. However, when I compile my project with <code>mkdir build &amp;&amp; cd build &amp;&amp; cmake ../src</code>, I have the following errors:</p>
  
  <blockquote>
    <p>CMake Error: install(EXPORT FooCoreConfig ...) includes target
    foo-core which requires target websocketpp that is not in the export
    set.</p>
    
    <p>CMake Error: install(EXPORT FooCoreConfig ...) includes target
    foo-core which requires target spdlog that is not in the export set.</p>
  </blockquote>
  
  <p>Including the headers e.g. <code>#include &lt;spdlog/spdlog.h&gt;</code> or <code>#include &lt;nlohmann/json.hpp&gt;</code> produces error saying that the header is not found.</p>
  
  <p>Truth be told, I am not so comfortable with CMake and I have spent the past two days debugging this. It might be something really simple, but I can't figure how to achieve it. In reality, one would just pass -I as a compiler flag to use the libraries like I want, but the CMake abstraction seems to confuse me. I would be very glad if someone could explain why this doesn't work and, hopefully, what's the correct way of including these libraries to my project. Thanks in advance!</p>