27

我是 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解决方案文件,当我尝试构建它时,它显示一个错误,即找不到头文件(没有这样的文件或目录)。

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

4

3 回答 3

27

您可能错过了一个或多个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 会在您下次尝试构建时自动重新运行。从文档中file

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

于 2013-07-15T13:16:05.897 回答
8

我的回答主要是 hack,但如果您不想手动添加所有目录,我发现它很有用。

该宏将递归扫描所有子目录(及其子目录等)。如果目录包含标头 (.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 测试

于 2019-09-13T18:49:31.570 回答
-1

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

标头不应传递给ADD_EXECUTABLE.

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

gcc main.c mylib.c

并不是:

gcc main.c mylib.c mylib.h

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

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

gcc -Inew/path/to/search/for/headers main.c mylib.c
于 2017-11-22T06:58:46.140 回答