So I'm trying to understand what goes wrong with one of my C++ projects. Essentially, project 1 works ok, everything is great. In the main header file of the project I have
#include "spdlog/spdlog.h"
And I have spdlog as a subproject in project 1. Additionally in my CMake for project 1 I have include_directories(spdlog/include)
. Now, I'm building project 2, which depends on project 1 and has it as subproject. However, when I try to include spdlog
it does not allow me and wants me to make the full ../project1/spdlog/include/spdlog.h
. What is the correct way to organize this dependency and to have the header included?
You should look for modern cmake resources. In the modern cmake style you can create an Imported target for spdlog which you can then use everywhere else.
lets assume the following structure
external/spdlog
external/CMakeLists.txt
project1/CMakeLists.txt
project2/CMakeLists.txt
CMakeLists.txt
in the external/CMakeLists.txt
you write
## add the imported library which is
## an INTERFACE (ie header only)
## IMPORTED (ie third party - no compilation necessary)
## GLOBAL (you can reference it from everywhere
## even if the target is not in the same scope
## which is the case for project1 and project2 because
## the spdlog target is not in their parent folder)
add_library(spdlog INTERFACE IMPORTED GLOBAL)
## set the include directory which is to be associated with this target
## and which will be inherited by all targets which use
## target_link_libraries(<target> spdlog)
target_include_directories(spdlog INTERFACE spdlog/include)
in the root CMakeLists.txt
you write your solution configuration (example)
project(mysolution)
add_subdirectory(external)
add_subdirectory(project1)
add_subdirectory(project2)
in your project CMakeLists.txt
s you can now use the target that you created in external
project1/CMakeLists.txt
add_library(project1 ${Sources})
## this will set the include directories configured in the spdlog target (library)
## and also ensure that targets depending on target1 will have access to spdlog
## (if PUBLIC were changed to PRIVATE then you could only use spdlog in
## project1 and dependeing targets like project2 would not
## inherit the include directories from spdlog it wouldn't
target_link_libraries(project1 PUBLIC spdlog)
project2/CMakeLists.txt
add_library(project2 ${Sources})
## this will link project1 which in return also links spdlog
## so that now project2 also has the include directories (because it was inherited)
## also targets depending on project2 will inherit everything from project1
## and spdlog because of the PUBLIC option
target_link_libraries(project2 PUBLIC project1)
sources:
[0] https://cmake.org/cmake/help/v3.9/command/add_library.html
[1] https://cmake.org/cmake/help/v3.9/command/target_link_libraries.html?highlight=target_link_libraries
[2] http://thetoeb.de/2016/08/30/modern-cmake-presentation/ (see presentation starting at slide 20)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With