I am new to CMake and would like to ask if somebody can help in the following problem.
I have C++ source and header files in their respective folders and now, I wan
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.
Just to further clarify one point in Fraser's answer:
Headers should not be passed to ADD_EXECUTABLE
.
The reason is that the intended compilation command on Linux for example is just:
gcc main.c mylib.c
and not:
gcc main.c mylib.c mylib.h
The C pre-processor then parses mylib.c
, and sees a #include "mylib.h"
, and uses it's search path for those files.
By using include_directories
instead, we modify the cpp preprocessor search path instead, which is the correct approach. In GCC, this translates to adding the -I
flag to the command line:
gcc -Inew/path/to/search/for/headers main.c mylib.c