我想找到一个目录下的所有.c文件,并将它们全部添加到src文件中,以便在cmake中编译。我怎样才能在 CMakeList.txt 中做到这一点。
对于常规 makefile,我可以创建
SPECIFIED_SRC_FILE = $(foreach d,$(SPECIFIED_SRC_DIRS),$(wildcard $(addprefix $(d)/*,*.c)))
但我不知道如何在 CMakeList.txt 中执行类似的操作。
那古老的通配符怎么样?
FILE(GLOB MyCSources *.c)
ADD_EXECUTABLE(MyExecutable ${MyCSources})
试试这个:
AUX_SOURCE_DIRECTORY
查找目录中的所有源文件。
AUX_SOURCE_DIRECTORY(dir VARIABLE)
收集指定目录下所有源文件的名称 并将列表存储在提供的变量中。该命令的目的是 由使用显式模板实例化的项目使用。 模板实例化文件可以存储在“Templates”中 子目录并使用此命令自动收集以避免 手动列出所有实例。
使用此命令来避免编写源列表是很诱人的 库或可执行目标的文件。虽然这似乎有效, CMake 无法生成一个构建系统来知道何时 添加了新的源文件。通常生成的构建系统 知道何时需要重新运行 CMake,因为 CMakeLists.txt 文件是 修改以添加新源。当源刚刚添加到 目录而不修改此文件,则必须手动 重新运行 CMake 以生成包含新文件的构建系统。
GLOB_RECURSE
递归示例
它基本上使
*
也进入子目录:
cmake_minimum_required(VERSION 3.0)
file(GLOB_RECURSE SOURCES RELATIVE ${CMAKE_SOURCE_DIR} "src/*.c")
add_executable(main ${SOURCES})
然后我们的来源可以位于例如:
src/main.c
src/d/a.c
src/d/a.h
并且
main.c
使用 #include "d/a.h"
并且 a.c
使用 #include "a.h"
。
在 CMake 顶层使用
GLOB_RECURSE
(即 "*.c"
而不是 "src/*.c"
)可能是一个坏主意,因为它可以拾取 CMake 本身生成的 .c
文件,这些文件放置在 build/
下。
可运行示例在 GitHub 上。
唯一正确答案是不这样做。这已在 multiple answers 中详细介绍。我将在这里总结,按重要性降序排列。
aux_source_directory
函数完全不正确,因为它无法检测文件系统中的更改。出于同样的原因,使用 file(GLOB
或 file(GLOB_RECURSE
而不使用 CONFIGURE_DEPENDS
是完全错误的。CONFIGURE_DEPENDS
不保证有效。 (见第1点)
明确列出您的来源。
1 以下是 CMake 开发人员对此的评价:
注意: 我们不建议使用 GLOB 从源代码树中收集源文件列表。如果添加或删除源时 CMakeLists.txt 文件没有更改,则生成的构建系统无法知道何时要求 CMake 重新生成。
标志可能无法在所有生成器上可靠地工作,或者如果将来添加不支持它的新生成器,则使用它的项目将被卡住。即使CONFIGURE_DEPENDS
工作可靠,每次重建时仍然需要执行检查。CONFIGURE_DEPENDS
是的,您有两个选择。让我们假设您的文件夹结构与此类似。
├── autopilot
│ ├── _AutoPilot.cpp
│ ├── _AutoPilot.h
│ └── action
│ ├── ActionBase.cpp
│ ├── ActionBase.h
│ ├── APcopter
│ │ ├── APcopter_avoid.cpp
│ │ ├── APcopter_avoid.h
如果您要使用
AUX_SOURCE_DIRECTORY
,您必须在每个子目录中添加CMakeLists.txt。然后您必须包含并链接所有这些子目录。这是一项相当艰巨的任务。因此您可以通过 GLOB 轻松完成工作。就是这样完成的。
file(GLOB autopilot_sources ./**.cpp ./**.c)
SET( autopilot ${autopilot_sources})
如果您想使用上述源代码创建库,请使用以下命令:
ADD_LIBRARY ( autopilot ${autopilot_sources})
TARGET_LINK_LIBRARIES ( autopilot)
如果您想使用上面的源代码创建可执行文件,请使用以下命令:
ADD_EXECUTABLE(autopilot ${autopilot_sources})
您可以按照 @whitequark 的描述使用
AUX_SOURCE_DIRECTORY
,但它不会真正按照您的预期工作,因为 CMake 将无法确定何时添加新文件(这就是使用通配符的全部要点)。