7

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?

1
  • The library target is wrong. It should be spdlog not extern_spdlog. I.e. the same as defined in the external project's CMake, not the name that you used in FetchContent. Commented Feb 5, 2021 at 20:31

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.