Recursive CMake search for header and source files

后端 未结 3 1165
臣服心动
臣服心动 2020-12-03 03:14

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

相关标签:
3条回答
  • 2020-12-03 03:38

    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

    0 讨论(0)
  • 2020-12-03 03:54

    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.

    0 讨论(0)
  • 2020-12-03 03:55

    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
    
    0 讨论(0)
提交回复
热议问题