如何使用Cmake构建系统在目录中使用所有* .c文件?

时间:2010-01-21 13:51:23

标签: makefile cmake

我想在目录下找到所有.c文件,并将它们全部添加到SRC文件中,以便在cmake中编译。我怎么能在CMakeList.txt中执行此操作。

对于常规的makefile我可以创建

SPECIFIED_SRC_FILE  = $(foreach d,$(SPECIFIED_SRC_DIRS),$(wildcard $(addprefix $(d)/*,*.c)))

但是我无法在CMakeList.txt中做到这样的事情。

6 个答案:

答案 0 :(得分:54)

这个优秀的老式游戏怎么样?

FILE(GLOB MyCSources *.c)
ADD_EXECUTABLE(MyExecutable ${MyCSources})

答案 1 :(得分:44)

试试这个:

  

AUX_SOURCE_DIRECTORY

     

查找目录中的所有源文件。

AUX_SOURCE_DIRECTORY(dir VARIABLE) 
     

收集指定目录中所有源文件的名称   并将列表存储在提供的变量中。这个命令是有意的   由使用显式模板实例化的项目使用。   模板实例化文件可以存储在“模板”中   子目录并使用此命令自动收集以避免   手动列出所有实例。

     

使用此命令避免编写源列表很有诱惑力   库或可执行目标的文件。虽然这似乎有效,   CMake没有办法生成一个知道何时a的构建系统   新的源文件已添加。通常是生成的构建系统   知道何时需要重新运行CMake,因为CMakeLists.txt文件是   修改为添加新源。当源只是添加到   目录无需修改此文件,必须手动完成   重新运行CMake以生成包含新文件的构建系统。

答案 2 :(得分:2)

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/下。

可运行的示例on GitHub

答案 3 :(得分:1)

是的,您有两种选择。让我们假设您的文件夹结构类似于此。

├── 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 ./*/*.cpp ./*/*/*.cpp ./*/*/*/*.cpp ./*.c ./*/*.c ./*/*/*.c ./*/*/*/*.c)
  SET( autopilot ${autopilot_sources})  

如果您想使用上面的源代码创建一个库,这就是命令:

  ADD_LIBRARY ( autopilot  ${autopilot})
  TARGET_LINK_LIBRARIES ( autopilot)  

如果要使用上述源代码创建可执行文件,则命令为:

 ADD_EXECUTABLE(autopilot ${autopilot})

答案 4 :(得分:0)

您可以使用AUX_SOURCE_DIRECTORY作为@whitequark描述,但它不会像您期望的那样真正起作用,因为CMake将无法确定何时添加新文件(这是使用通配符)。

答案 5 :(得分:0)

的正确答案是 不这样做 。此处的multiple answers中对此进行了详细说明。我将在这里按照重要性从高到低的顺序进行总结。

  1. 开发人员有explicitly stated1这样做是错误的。那应该让你停顿一下。如果您遇到问题,开发人员可能不会愿意为您解决问题,而是会告诉您列出来源。
  2. aux_source_directory函数完全不正确,因为它无法检测文件系统中的更改。出于相同的原因,在没有file(GLOB的情况下使用file(GLOB_RECURSECONFIGURE_DEPENDS是完全错误的。
  3. CONFIGURE_DEPENDS不能保证正常工作。 (请参阅第1点)
  4. 如果遍历失败,您将很难确定添加或删除了哪些额外的源文件。
  5. 通配符,特别是递归通配符,速度很慢,而且文件越多,情况越糟。
  6. 执行git bisect,切换分支或执行其他向后移动文件时间戳记的源代码控制操作时,globation尤其有可能失败。

1 这是CMake开发人员必须说的:

注意:我们不建议您使用GLOB来从源代码树中收集源文件列表。如果在添加或删除源时没有CMakeLists.txt文件更改,则生成的生成系统无法知道何时要求CMake重新生成。 CONFIGURE_DEPENDS标志可能无法在所有生成器上可靠地工作,或者如果将来添加了不支持它的新生成器,则使用该生成器的项目将被卡住。即使CONFIGURE_DEPENDS可靠地工作,在每次重新构建时都要执行检查。