Include headers with a library in CMake
Solution 1
As @Anedar mentioned, to resolve this situation one needs target_include_directories
with PUBLIC
or INTERFACE
options in the library CMakeLists.txt
. That populates INTERFACE_INCLUDE_DIRECTORIES
of the library target, which is used by target_link_libraries
on the consuming side.
My working configuration:
/my_project/CMakeLists.txt
cmake_minimum_requared(VERSION 3.8)
project(my_project)
add_subdirectory(utils)
add_executable(main main.c)
target_link_libraries(main utils base_c base_cpp)
/my_project/utils/CMakeLists.txt
add_subdirectory(base_c)
add_subdirectory(base_cpp)
add_library(utils)
target_sources(utils PUBLIC common.h)
target_include_directories(utils INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
/my_project/utils/base_c/CMakeLists.txt
add_library(base_c base_c.c)
target_sources(base_c PUBLIC base_c.h)
target_include_directories(base_c INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
/my_project/utils/base_cpp/CMakeLists.txt
add_library(base_cpp base_cpp.cpp)
target_sources(base_cpp PUBLIC base_cpp.hpp)
target_include_directories(base_cpp INTERFACE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(base_cpp base_c)
Solution 2
target_include_directories)
is what you are looking for, but not the PRIVATE
option.
According to the
target_include_directories() documentation the PRIVATE
option is for directories only used in that target, INTERFACE
is for directories only used by dependent targets and PUBLIC
is for both.
I suggest using in /my_project/utils/base_c/CMakeLists.txt
target_include_directories(base_c INTERFACE ${CMAKE_CURRENT_LIST_DIR})
This way you "link" the include directory to the target it belongs to and all targets dependent on it automatically include the directory.
Additionally you might want to move your public headers to their own subfolder /my_project/utils/base_c/base_c/
and then include them as #include "base_c/base_c.h"
. This introduces kind of a "namespace" to headers, preventing headers with the same name from different projects from beeing ambigous.
Related videos on Youtube

voddan
Updated on June 04, 2022Comments
-
voddan 7 months
My project has two utility library in it. I am looking for the best way to write CMake configurations for the libraries.
/my_project --> CMakeLists.txt --> main.cpp --> /utils --> CMakeLists.txt --> common.h --> /base_c --> CMakeLists.txt --> base_c.c --> base_c.h --> /base_cpp --> CMakeLists.txt --> base_cpp.cpp --> base_cpp.hpp
My current CMake files:
/my_project/CMakeLists.txt
cmake_minimum_requared(VERSION 3.8) project(my_project) add_subdirectory(utils) add_executable(main main.c) target_link_libraries(main utils base_c base_cpp)
/my_project/utils/CMakeLists.txt
add_subdirectory(base_c) add_subdirectory(base_cpp) add_library(utils) target_sources(utils PUBLIC common.h)
/my_project/utils/base_c/CMakeLists.txt
add_library(base_c base_c.c) target_sources(base_c PUBLIC base_c.h)
/my_project/utils/base_cpp/CMakeLists.txt
add_library(base_cpp base_cpp.cpp) target_sources(base_cpp PUBLIC base_cpp.hpp) find_library(BASEC base_c ../base_c) target_link_libraries(base_cpp BASEC)
The problem is that
base_cpp
does not find includes frombase_c
. How should I fix the configuration?I managed to make it work with
target_include_directories(base_cpp PRIVATE ../base_c)
, but that's ugly and shouldn't be necessary, according to INTERFACE_INCLUDE_DIRECTORIES documentation.-
Tsyvarev over 5 yearsHow documentation for INTERFACE_INCLUDE_DIRECTORIES implies that
target_include_directories
is not needed? I am curious how you have managed to compile even single library withoutinclude_directories
ortarget_include_directories
. -
voddan over 5 years@Tsyvarev I may be totally wrong on this. Could you explain how I can use
INTERFACE_INCLUDE_DIRECTORIES
of a library? -
Anedar over 5 yearsWhich build system do you use after CMake? Makefiles? Visual Studio projects? Can you examine those files which directories are actually passed as include-directories?
-
-
voddan over 5 yearsDo I need to do anything on the consuming side in
base_cpp
? Currentlyfind_library
returnsBASEC-NOTFOUND
-
Anedar over 5 yearsyou dont need find_library in the same project. just use
target_link_libraries(base_cpp base_c)
-
voddan over 5 yearsOk, I did that, but it can't resolve the headers. Maybe I need
target_include_directories(base_cpp <something>)
? -
Tsyvarev over 5 years@voddan:
it can't resolve the headers.
- Looks like your code includes headers in unexpected manner. Update your question post with new CMake code and actual error message. -
voddan over 5 yearsThis is a correct answer, but the explanation is off, so I didn't get it when I needed it :(