【问题标题】:Proper file globbing in cmake with make and ninja使用 make 和 ninja 在 cmake 中进行正确的文件通配
【发布时间】:2018-01-02 16:22:50
【问题描述】:

很多关于 CMake 的博客和讨论告诉您不要使用文件通配符来构建您的源代码。也就是说,这很糟糕:

file(GLOB SOURCES *.cxx)

虽然这很好:

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

我的理解是,造成这种情况的根本原因是,虽然一些构建系统支持通配符,但另一些不支持,并且 CMake 在这种情况下试图与构建系统无关。这似乎是合理的。

但是,就我个人而言,我将使用的所有构建系统(例如 make 和 ninja)确实支持 globbing。无论如何,在 CMake 中是否有将 globbing 转发到构建中,以获得两全其美 - 无需重新运行 CMake 即可自动获取新文件的缩写 globbing?

【问题讨论】:

    标签: cmake


    【解决方案1】:

    我的理解是,造成这种情况的根本原因是,虽然一些构建系统支持通配符,但另一些不支持,并且 CMake 在这种情况下试图与构建系统无关。

    主要原因在manual中说明:

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

    这是真的。如果添加新的源文件,则需要重新运行 CMake。所以推荐手动列出源文件的方法,因为你不能忘记这样做;而忘记重新运行 CMake 可能会导致挫败感。如果集成了 CMake,有些 IDE 会自动为您执行此操作。

    但是,就我个人而言,我将使用的所有构建系统(例如 make 和 ninja)都支持 globbing。无论如何,在 CMake 中是否有将 globbing 转发到构建中,以获得两全其美 - 无需重新运行 CMake 即可自动获取新文件的缩写 globbing?

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

    【讨论】:

      【解决方案2】:

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

      file(GLOB SOURCES CONFIGURE_DEPENDS *.cxx)
      

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

      附注:

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

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

      【讨论】:

        【解决方案3】:

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

        您应该改用 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} 差异输出中没有意外添加/删除文件的证据。”

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

        【讨论】:

        • 对于它的价值,我非常不同意这一点。该论点甚至没有意义(如果您正在通配 *.cxx,那么将您不想构建的文件重命名为与 glob 不匹配是非常简单的,那么这是一个避免通配的激励论据。另外我可以看到从我的正常差异中删除的文件,我不需要 additional 差异来查看它们)。弄清楚为什么没有构建新文件所浪费的时间比任何所谓的通配成本都要大得多。
        • 嗯。我不介意手动添加源文件。但我会尝试你的方法一段时间,看看我的想法。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-01-24
        • 2018-04-15
        • 2020-12-11
        • 2021-12-19
        • 1970-01-01
        • 2018-03-15
        • 1970-01-01
        相关资源
        最近更新 更多