我是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 解决方案文件,当我尝试构建它时,它会显示 找不到头文件的错误(没有这样的文件或目录)。
如果有人能帮助我,真的很感激。感谢。
答案 0 :(得分:23)
您可能错过了一个或多个include_directories
来电。将标题添加到add_executable
调用中的文件列表实际上并没有添加到编译器的搜索路径 - 这是一个方便的功能,它只会添加到IDE中项目的文件夹结构中。
所以,在你的root中,假设你有/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重新生成。
答案 1 :(得分:1)
我的回答主要是破解,但是如果您不想手动添加所有目录,我发现它很有用。
此宏将递归扫描所有子目录(及其子目录等)。如果目录包含头(.h)文件,则它将其路径附加到return_list
中。然后,该列表可以与target_include_directories
一起使用。
MARO(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
)
宏观信用:Christoph
通过Cmake 3.10测试
答案 2 :(得分:0)
进一步澄清弗雷泽答案中的一点:
标题不应传递给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