我是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解决方案文件,当我尝试构建它时,它显示了一个错误,即找不到头文件(没有这样的文件或目录)。
如果有人能帮帮我,我将不胜感激。 谢了。
您可能缺少一个或多个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