提问者:小点点

头文件和源文件的递归CMake搜索


我是CMake的新手,想问一下是否有人能在下面的问题上提供帮助。

我有C++源文件和头文件在它们各自的文件夹中,现在,我想做一个CMake文本文件递归搜索它们。

目前我是这样做的:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(CarDetectorDAISY)

file(GLOB_RECURSE SRCS *.cpp)
file(GLOB_RECURSE HDRS *.h)

ADD_EXECUTABLE(stereo_framework  ${SRCS} ${HDRS})
TARGET_LINK_LIBRARIES(stereo_framework) 

这创建了我的CarDetectorDaisy.sln解决方案文件,当我尝试构建它时,它显示了一个错误,即找不到头文件(没有这样的文件或目录)。

如果有人能帮帮我,我将不胜感激。 谢了。


共3个答案

匿名用户

您可能缺少一个或多个include_directories调用。 将头添加到add_executable调用中的文件列表中实际上并不会添加到编译器的搜索路径中--这是一个方便的特性,因此它们只添加到IDE中项目的文件夹结构中。

因此,在根中,假设您有/my_lib/foo.h,并且您希望将其包含在源文件中,作为

#include "my_lib/foo.h"

然后在您的cmakelists.txt中,您需要执行以下操作:

include_directories(${CMAKE_SOURCE_DIR})

如果,相反你只想做

#include "foo.h"

然后在cmakelists.txt中,执行以下操作

include_directories(${CMAKE_SOURCE_DIR}/my_lib)


我应该提到的是,file(glob.。。)不是收集源代码列表的推荐方式-您实际上应该只在cmakelists.txt中显式添加每个文件。 通过这样做,如果以后添加或删除源文件,将修改cmakelists.txt,并且在下次尝试构建时,CMake将自动重新运行。 从文件的文档中:

我们不建议使用GLOB从源树中收集源文件列表。 如果在添加或删除源时没有Cmakelists.txt文件更改,则生成的生成系统无法知道何时要求CMake重新生成。

匿名用户

我的答案大部分是一个hack,但我发现如果您不想手动添加所有dir,它很有用。

这个宏将递归扫描所有子目录(以及它们的子目录,等等……)。 如果一个目录包含头文件(。h),它将把它的路径追加到return_list中。 然后,该列表可以与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()

用法:

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
)

宏观信贷:克里斯托弗

使用Cmake 3.10进行测试

匿名用户

只是为了进一步澄清弗雷泽回答中的一点:

标头不应传递给add_executable

原因是Linux上的预期编译命令只是:

gcc main.c mylib.c

而不是:

gcc main.c mylib.c mylib.h

然后,C预处理器解析mylib.C,看到一个#include“mylib.h”,并使用它的搜索路径查找这些文件。

通过使用include_directories,我们改为修改cpp预处理器搜索路径,这是正确的方法。 在GCC中,这转换为向命令行添加-i标志:

gcc -Inew/path/to/search/for/headers main.c mylib.c