Tyrreus
Tyrreus

Reputation: 393

How to include external modules headers when FetchContent_Declare is used?

I want to use modern CMake project structure convention in my new project to follow good practices and to be consistent with many other projects, but I'm facing problem with include path.

My directories structure looks as follows:

.
├── build
├── CMakeLists.txt
├── extern
│   └── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    └── main.cpp

I want to use FetchContent_Declare instead of git submodules to manage the third-party libraries.

The root CMakeLists.txt:

cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
set(ProjectName "MyApp")

project(${ProjectName})

add_subdirectory(extern)
add_subdirectory(src)

The extern CMakeLists.txt:

cmake_minimum_required(VERSION 3.16 FATAL_ERROR)

include(FetchContent)
FetchContent_Declare(
  extern_spdlog

  GIT_REPOSITORY https://github.com/gabime/spdlog.git
  GIT_TAG        v1.8.2)

FetchContent_GetProperties(extern_spdlog)
if(NOT extern_spdlog_POPULATED)
  FetchContent_Populate(extern_spdlog)
  add_subdirectory(
    ${extern_spdlog_SOURCE_DIR}
    ${extern_spdlog_BINARY_DIR}
  )
endif()

The src CMakeLists.txt:

cmake_minimum_required(VERSION 3.16)

set(BINARY ${CMAKE_PROJECT_NAME})

file(GLOB_RECURSE SOURCES LIST_DIRECTORIES true *.h *.cpp)
set(SOURCES ${SOURCES})

add_executable(${BINARY}_run ${SOURCES})

add_library(${BINARY}_lib STATIC ${SOURCES})

target_link_libraries(${BINARY}_run extern_spdlog)

And the main.cpp:

#include <spdlog/spdlog.h>

int main(int argc, char* argv[]) {
    spdlog::info("Welcome to spdlog!");
    return 0;
}

CMake executes and the spdlog library is cloned properly and can be found in the build directory at: build/_deps/extern_spdlog-src.

If I call make in the build directory then I get fatal error: spdlog/spdlog.h: No such file or directory.

How to add include directories for the external libraries used in the application?

Upvotes: 6

Views: 3467

Answers (1)

Mathemaphysics
Mathemaphysics

Reputation: 41

I was initially confused about this as well. It doesn't help that the names of the FetchContent targets often match the names of the imported targets. What worked for me was similar (though not identical) to what the first comment states. I used target_link_libraries(target spdlog::spdlog) (if you want to use the pre-compiled library or spdlog::spdlog_header_only if you want to use the header source only version.

Upvotes: 3

Related Questions