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

Build 头文件和源文件的递归CMake搜索,build,cmake,build-process,build-automation,Build,Cmake,Build Process,Build Automation,我是CMake的新手,想问一下是否有人可以帮助解决以下问题 我在他们的文件夹中有C++源文件和头文件,现在我想制作一个递归的CMAGE文本文件。 目前,我是这样做的: CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(CarDetectorDAISY) file(GLOB_RECURSE SRCS *.cpp) file(GLOB_RECURSE HDRS *.h) ADD_EXECUTABLE(stereo_framework ${SRCS} ${H

我是CMake的新手,想问一下是否有人可以帮助解决以下问题

我在他们的文件夹中有C++源文件和头文件,现在我想制作一个递归的CMAGE文本文件。 目前,我是这样做的:

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解决方案文件,当我尝试构建它时,它会显示 未找到头文件的错误(没有此类文件或目录)


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

您可能错过了一个或多个电话。在
add\u 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)

我应该提到的是,这不是收集源代码列表的推荐方法-您应该在CMakeLists.txt中明确添加每个文件。通过这样做,如果以后添加或删除源文件,则会修改CMakeLists.txt,并且下次尝试构建时,CMake会自动重新运行。从
文件的文档中

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


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

标题不应传递给
添加可执行文件

原因是,例如,Linux上的预期编译命令是:

gcc main.c mylib.c
而不是:

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

通过使用
include\u目录
,我们修改了cpp预处理器搜索路径,这是正确的方法。在GCC中,这转化为将
-I
标志添加到命令行:

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

我的答案主要是一个黑客,但如果您不想手动添加所有目录,我发现它很有用

此宏将递归扫描所有子目录(及其子目录等…)。如果目录包含头(.h)文件,它会将其路径附加到
返回\u列表
。然后,此列表可用于
目标\u包含\u目录

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进行测试

我对此持怀疑态度。我同意你的观点,但相反的论点通常是,很容易通过
ls
dir
获得原始源列表,然后通常一次只添加一两个文件。如果你自己工作的话,环球旅行是相当安全的。如果您是团队的一员,您必须“培训”团队在添加文件或从远程VCS更新文件后始终运行CMake,以防其他团队成员添加文件。最好使用
target\u include\u目录
,而不是
include\u目录
,因为后者是全局性的,现代CMake实践不鼓励使用。在
target_sources()
命令中列出标题可能会很方便,因为作为源代码列出的标题本身不会直接编译,但添加它们将在IDE中的项目文件中列出这些标题,即使没有直接包含它们的源文件。注意:显然,这只是对使用
include\u directories()
commandCheckout这个答案的补充,这是金色的。朋友,你为我节省了很多时间,谢谢你!