使用make和ninja在cmake中正确文件通配

时间:2018-01-02 16:22:50

标签: cmake

很多博客和关于CMake的讨论告诉你使用文件通配来建立你的资源。也就是说,这很糟糕:

file(GLOB SOURCES *.cxx)

虽然这很好:

set(SOURCES a.cxx b.cxx c.cxx d.cxx e.cxx [...])

我的理解是,其根本原因在于,虽然某些构建系统支持通配,但其他构建系统不支持通配,而CMake正试图在这种情况下构建系统不可知。这看似合理。

但是,在我个人的情况下,我将使用的所有构建系统(例如make和ninja)支持globbing。无论如何在CMake中总是将globbing转发到构建中,以获得两个世界中最好的 - 缩写的globbing,自动获取新文件而不必重新运行CMake?

3 个答案:

答案 0 :(得分:3)

  

我的理解是,其根本原因在于,虽然某些构建系统支持通配,但其他构建系统不支持通配,而CMake正试图在这种情况下构建系统不可知。

主要原因在manual

中说明
  

注意:我们不建议使用GLOB从源树中收集源文件列表。如果没有CMakeLists.txt文件更改时   添加或删除源,然后生成的构建系统无法知道   何时要求CMake重新生成。

这是事实。如果添加新的源文件,则需要重新运行CMake。因此建议手动列出源文件的方法,因为你不能忘记这样做;忘记重新运行CMake会导致沮丧。如果有CMake集成,IDE会自动为您执行此操作。

  

但是,在我个人的情况下,我将使用的所有构建系统(例如make和ninja)都支持globbing。无论如何在CMake中总是将globbing转发到构建中,以获得两个世界中最好的 - 缩写的globbing,自动获取新文件而不必重新运行CMake?

不,没有。如果有,IDE的/插件将不需要实现此功能。所以你需要朝这个方向看。

答案 1 :(得分:1)

CMake 3.12 向 file(GLOB) 添加了一个新的参数,它就是这样做的:

file(GLOB SOURCES CONFIGURE_DEPENDS *.cxx)
<块引用>

如果指定了 CONFIGURE_DEPENDS 标志,CMake 将向主构建系统检查目标添加逻辑,以在构建时重新运行标记的 GLOB 命令。如果任何输出发生变化,CMake 将重新生成构建系统。

附注:

<块引用>

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

但是有了这些警告,功能就在那里。

答案 2 :(得分:0)

你不应该像你展示的那样创建一个变量来添加源文件。

您应该改用 target_sources。

target_sources(foobar PRIVATE
    main.cpp
    ...
)

target_sources 对于 3.13+ 用户的另一个好处是您可以如何使用它。

Craig Scott 写了一篇关于它的好文章:

https://crascit.com/2016/01/31/enhanced-source-file-handling-with-target_sources/

==========================

但是,CMake 3.12 向 file(GLOB) 添加了一个新参数,它正是这样做的:

文件(GLOB SOURCES CONFIGURE_DEPENDS *.cxx)

关于 CONFIGURE_DEPENDS 我会看到这个 cmake 讨论: https://discourse.cmake.org/t/is-glob-still-considered-harmful-with-configure-depends/808

来自 Ben Boerkel(CMake 开发人员):

“检查成本取决于平台(可能还有生成器)。我不知道性能成本,但那是因为我个人发现即使它是高性能的,我也至少遇到了一个问题往往足以让它不值得。

我仍然强烈反对通配符,因为文件可能会出现在您不打算构建的源代码树中。我遇到的主要情况是,在 git 中解决冲突期间,冲突中文件的其他版本被命名为 ${base}${origin}${pid}.$ {ext},所以如果你试图在冲突中构建,你将把这些文件放在一起。

另一个原因是现在您的构建系统差异中不存在文件的添加/删除,因此跟踪“您更改了什么?”调试报告的问题可能会更难,因为没有证据表明在正常的 ${vcs} 差异输出中意外添加/删除了文件。”

================================