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

发布于 2024-08-18 15:16:29 字数 264 浏览 2 评论 0原文

我想找到一个目录下的所有.c文件并将它们全部添加到src文件中以在cmake中编译。我如何在 CMakeList.txt 中执行此操作。

对于常规 makefile,我可以创建

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

,但我不知道如何在 CMakeList.txt 中执行类似的操作。

I want to find all .c files under a directory and add them all to SRC files to compile in cmake. How can I do this in CMakeList.txt.

for regular makefiles I can create

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

but I couldn't get how to do something like this in CMakeList.txt.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

倾城泪 2024-08-25 15:16:29

那个古老的通配符怎么样?

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

How about the good old globbing?

FILE(GLOB MyCSources *.c)
ADD_EXECUTABLE(MyExecutable ${MyCSources})
你的笑 2024-08-25 15:16:29

试试这个:

AUX_SOURCE_DIRECTORY

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

AUX_SOURCE_DIRECTORY(目录变量) 

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

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

Try this:

AUX_SOURCE_DIRECTORY

Find all source files in a directory.

AUX_SOURCE_DIRECTORY(dir VARIABLE) 

Collects the names of all the source files in the specified directory
and stores the list in the variable provided. This command is intended
to be used by projects that use explicit template instantiation.
Template instantiation files can be stored in a "Templates"
subdirectory and collected automatically using this command to avoid
manually listing all instantiations.

It is tempting to use this command to avoid writing the list of source
files for a library or executable target. While this seems to work,
there is no way for CMake to generate a build system that knows when a
new source file has been added. Normally the generated build system
knows when it needs to rerun CMake because the CMakeLists.txt file is
modified to add a new source. When the source is just added to the
directory without modifying this file, one would have to manually
rerun CMake to generate a build system incorporating the new file.

遮了一弯 2024-08-25 15:16:29

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/ah"ac 使用#include "ah"

在 CMake 顶层使用 GLOB_RECURSE(即 "*.c" 而不是 "src/*.c")可能是一个坏主意,因为它可以拾取由 CMake 本身生成的位于 build/ 下的 .c 文件。

GitHub 上的可运​​行示例

GLOB_RECURSE recursive example

It basically makes the * also go into subdirectories:

cmake_minimum_required(VERSION 3.0)
file(GLOB_RECURSE SOURCES RELATIVE ${CMAKE_SOURCE_DIR} "src/*.c")
add_executable(main ${SOURCES})

And then our sources could be located for example as:

src/main.c
src/d/a.c
src/d/a.h

And main.c uses #include "d/a.h" and a.c uses #include "a.h".

Using GLOB_RECURSE on the CMake toplevel (i.e. "*.c" instead of "src/*.c") is likely a bad idea, as it can pick up .c files generated by CMake itself which are placed under build/.

Runnable example on GitHub.

巷雨优美回忆 2024-08-25 15:16:29

唯一正确答案是不要这样做多个对此进行了详细说明答案在这里。我将在这里总结一下,按重要性降序排列。

  1. 开发人员明确声明1 这样做是错误的。这应该让你停下来。如果您遇到问题,开发人员可能不会愿意为您解决问题,而是会告诉您列出来源。
  2. aux_source_directory 函数完全不正确,因为它无法检测文件系统中的更改。出于同样的原因,在没有 CONFIGURE_DEPENDS 的情况下使用 file(GLOBfile(GLOB_RECURSE) 是完全不正确的。
  3. CONFIGURE_DEPENDS 不是保证有效(见第 1 点)。
    1. 事实上,之前在 Windows 上它就存在错误忍者1.10.2。
    2. 它还会破坏空运行工作流程,因为全局检查在父构建中运行,而子(真实)构建会递归调用。
  4. 如果通配失败,您将很难确定添加或删除了哪个额外的源文件。
  5. 通配符,尤其是递归通配符,可能会很慢,并且文件越多,情况就会变得更糟。 Ext4 的性能通常可以接受,但 NTFS 的性能较差,尤其是通过 Linux 驱动程序。请参阅:https://github.com/alexreinking/cmake-glob-performance/
  6. 在执行 git bisects、切换分支或执行其他将文件时间戳向后移动的源代码控制操作时,通配符特别可能会失败。

相反,明确列出您的来源。


1 以下是 CMake 开发人员对此的评价:

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

The only correct answer is to not do this. This has been detailed in multiple answers here on SO. I will summarize here, in decreasing order of importance.

  1. The developers have explicitly stated1 that it is wrong to do this. That should give you pause. If you encounter an issue, the developers will likely not be receptive to fixing it for you, but will rather tell you to list your sources.
  2. The aux_source_directory function is outright incorrect since it cannot detect changes in the filesystem. For the same reason, using file(GLOB or file(GLOB_RECURSE without CONFIGURE_DEPENDS is outright incorrect.
  3. CONFIGURE_DEPENDS is not guaranteed to work. (See point 1)
    1. In fact, it was buggy on Windows before Ninja 1.10.2.
    2. It also breaks dry-run workflows since the glob checks run in a parent build and the child (real) build is invoked recursively.
  4. If globbing fails, you will have a difficult time figuring out which extra source file got added or removed.
  5. Globbing, especially recursive globbing, can be slow and gets worse the more files you have. Ext4's performance is typically acceptable, but NTFS's is bad, especially through Linux drivers. See: https://github.com/alexreinking/cmake-glob-performance/
  6. Globbing is particularly likely to fail when doing git bisects, switching branches, or performing other source control operations that move file timestamps backward.

Explicitly list your sources instead.


1 Here's what the CMake developers have to say about it:

Note: We do not recommend using GLOB to collect a list of source files from your source tree. If no CMakeLists.txt file changes when a source is added or removed then the generated build system cannot know when to ask CMake to regenerate. The CONFIGURE_DEPENDS flag may not work reliably on all generators, or if a new generator is added in the future that cannot support it, projects using it will be stuck. Even if CONFIGURE_DEPENDS works reliably, there is still a cost to perform the check on every rebuild.

水中月 2024-08-25 15:16:29

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

├── 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})

Yes, you have two options. Let's assume you the folder structure something similar to this.

├── autopilot
            │   ├── _AutoPilot.cpp
            │   ├── _AutoPilot.h
            │   └── action
            │       ├── ActionBase.cpp
            │       ├── ActionBase.h
            │       ├── APcopter
            │       │   ├── APcopter_avoid.cpp
            │       │   ├── APcopter_avoid.h

If you are to use AUX_SOURCE_DIRECTORY you have to add CMakeLists.txt each one of sub directories. Then you have to include and link all those subdirectories. This is quite a difficult task. So you can you GLOB and do the job very easily. This is how it is done.

  file(GLOB autopilot_sources ./**.cpp ./**.c)
  SET( autopilot ${autopilot_sources})  

If you want to create a library using above source code this is the command:

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

If you want to create an executable file using above source code this is the command:

 ADD_EXECUTABLE(autopilot ${autopilot_sources})
这个俗人 2024-08-25 15:16:29

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

You can use AUX_SOURCE_DIRECTORY as @whitequark described, but it won't really work as you expect, as CMake will be unable to determine when new files are added (which is kind of the whole point with using a wildcard).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文