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 monthsMy 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.hppMy 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_cppdoes 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 thattarget_include_directoriesis not needed? I am curious how you have managed to compile even single library withoutinclude_directoriesortarget_include_directories. -
voddan over 5 years@Tsyvarev I may be totally wrong on this. Could you explain how I can useINTERFACE_INCLUDE_DIRECTORIESof 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 inbase_cpp? Currentlyfind_libraryreturnsBASEC-NOTFOUND -
Anedar over 5 yearsyou dont need find_library in the same project. just usetarget_link_libraries(base_cpp base_c) -
voddan over 5 yearsOk, I did that, but it can't resolve the headers. Maybe I needtarget_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 :(