简体   繁体   English

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

[英]Recursive CMake search for header and source files

I am new to CMake and would like to ask if somebody can help in the following problem.我是 CMake 的新手,想问问是否有人可以帮助解决以下问题。

I have C++ source and header files in their respective folders and now, I want to make a CMake text file that recursively searches for them.我在各自的文件夹中有 C++ 源文件和头文件,现在,我想制作一个递归搜索它们的 CMake 文本文件。

Currently, I am doing it in this way:目前,我是这样做的:

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) 

This creates my CarDetectorDAISY.sln solution file and when I try to build it, it shows an error that header files are not found (No such file or directory).这会创建我的CarDetectorDAISY.sln解决方案文件,当我尝试构建它时,它显示找不到头文件的错误(没有这样的文件或目录)。

It would be really grateful if someone can please help me.如果有人可以帮助我,我将不胜感激。 Thanks.谢谢。

You're probably missing one or more include_directories calls.您可能错过了一个或多个include_directories调用。 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.add_executable调用add_executable头添加到文件列表中实际上并没有添加到编译器的搜索路径 - 这是一个方便的功能,因此它们只会添加到 IDE 中的项目文件夹结构中。

So, in your root, say you have /my_lib/foo.h, and you want to include that in a source file as因此,在您的根目录中,假设您有 /my_lib/foo.h,并且您希望将其作为源文件包含在

#include "my_lib/foo.h"

Then in your CMakeLists.txt, you need to do:然后在您的 CMakeLists.txt 中,您需要执行以下操作:

include_directories(${CMAKE_SOURCE_DIR})

If, instead you just want to do如果,相反,您只想做

#include "foo.h"

then in the CMakeLists.txt, do然后在 CMakeLists.txt 中,做

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.我应该提到file(GLOB...)不是收集源列表的推荐方法 - 您实际上应该在 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.通过这样做,如果您稍后添加或删除源文件,CMakeLists.txt 将被修改,并且 CMake 会在您下次尝试构建时自动重新运行。 From the docs for file :file的文档:

We do not recommend using GLOB to collect a list of source files from your source tree.我们不建议使用 GLOB 从源树中收集源文件列表。 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.如果在添加或删除源时没有 CMakeLists.txt 文件更改,则生成的构建系统无法知道何时要求 CMake 重新生成。

My answer is mostly a hack, but I find it useful if you don't want to add all dir manually.我的回答主要是一个 hack,但如果您不想手动添加所有目录,我发现它很有用。

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 .如果目录包含头 (.h) 文件,则它将其路径附加到return_list This list can then be used with target_include_directories .然后可以将此列表与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用 Cmake 3.10 测试

Just to further clarify one point in Fraser's answer:只是为了进一步澄清弗雷泽的回答中的一点:

Headers should not be passed to ADD_EXECUTABLE .不应将标头传递给ADD_EXECUTABLE

The reason is that the intended compilation command on Linux for example is just:原因是,例如,Linux 上的预期编译命令只是:

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. C 预处理器然后解析mylib.c ,并看到一个#include "mylib.h" ,并使用它的搜索路径来查找这些文件。

By using include_directories instead, we modify the cpp preprocessor search path instead, which is the correct approach.通过使用include_directories ,我们改为修改 cpp 预处理器搜索路径,这是正确的方法。 In GCC, this translates to adding the -I flag to the command line:在 GCC 中,这意味着将-I标志添加到命令行:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM