Recursive CMake search for header and source files
My answer is mostly a hack, but I find it useful if you don't want to add all dir manually.
This macro will recursively scan all sub-directories (and their sub-directories, etc ...). If a directory contains a header (.h) file, it will append its path to the return_list
. This list can then be used with target_include_directories
.
MACRO(HEADER_DIRECTORIES return_list)
FILE(GLOB_RECURSE new_list *.h)
SET(dir_list "")
FOREACH(file_path ${new_list})
GET_FILENAME_COMPONENT(dir_path ${file_path} PATH)
SET(dir_list ${dir_list} ${dir_path})
ENDFOREACH()
LIST(REMOVE_DUPLICATES dir_list)
SET(${return_list} ${dir_list})
ENDMACRO()
Usage:
HEADER_DIRECTORIES(header_dir_list)
list(LENGTH header_dir_list header_dir_list_count)
message(STATUS "[INFO] Found ${header_dir_list_count} header directories.")
target_include_directories(
my_program
PUBLIC
${header_dir_list} # Recursive
)
Macro credit: Christoph
Tested with Cmake 3.10
You're probably missing one or more include_directories
calls. Adding headers to the list of files in the add_executable
call doesn't actually add then to the compiler's search path - it's a convenience feature whereby they are only added to the project's folder structure in IDEs.
So, in your root, say you have /my_lib/foo.h, and you want to include that in a source file as
#include "my_lib/foo.h"
Then in your CMakeLists.txt, you need to do:
include_directories(${CMAKE_SOURCE_DIR})
If, instead you just want to do
#include "foo.h"
then in the CMakeLists.txt, do
include_directories(${CMAKE_SOURCE_DIR}/my_lib)
I should mention that file(GLOB...)
is not the recommended way to gather your list of sources - you should really just add each file explicitly in the CMakeLists.txt. By doing this, if you add or remove a source file later, the CMakeLists.txt is modified, and CMake automatically reruns the next time you try and build. From the docs for file
:
We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate.