CMake/Ninja 试图编译已删除的“.cpp”文件

Posted

技术标签:

【中文标题】CMake/Ninja 试图编译已删除的“.cpp”文件【英文标题】:CMake/Ninja attempting to compile deleted `.cpp` file 【发布时间】:2015-06-20 01:44:02 【问题描述】:

我发现,当我使用cmakeninja 从我的项目中删除cpp 文件时,如果不先完全删除我的构建目录并从头开始,我就无法轻松编译它。 CMake 和/或 Ninja 显然隐藏了对其编译的所有 cpp 文件的许多引用,即使在重新运行 CMake 之前删除 CMake 缓存也不会删除所有引用。

这是一个已知问题吗?有解决办法吗?我偶尔只是运行rm $(grep -R <filename> <builddir>),但这是一个可怕的组合。

编辑:看来我错了,因为我无法复制这个问题。手动重新运行 CMake 似乎总是生成正确的 .cpp 文件列表,即使使用 GLOB 生成源列表。

【问题讨论】:

您能否添加您的CMakeLists.txt 文件的示例?您是否列出了所有源文件,或者您是否提供file(GLOB ...)?后者是这种行为的一个可能原因。参见 CMake 的文档: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. @Florian 是的,我做 glob 文件,但我也会在必要时手动重新运行 CMake(当然,每当我删除 CMake 缓存时)。 Issue 0014820: warn users about removing only CMakeCache.txt 声称您还需要删除所有 CMakeFiles 目录。但我假设您没有缓存源文件列表,因此根据我的经验,重新触发 CMake 配置的最可靠方法是触摸项目 CMakeLists.txt 文件之一(例如使用CMake itselfcmake -E touch CMakeLists.txt)。跨度> @Florian 最可靠的方式:为什么不cmake <build-dir> 【参考方案1】:

把我的 cmets 变成答案

使用file(GLOB ...) 收集您的源文件

是的,在使用file(GLOB ...) 命令收集源文件时,CMake 不会知道新的或已删除的源文件。这是 CMake 的一个已知限制。因此,我已经更改了我的 CMake 项目以单独列出所有源文件。为方便起见,我仍在使用 file(GLOB ...) 命令收集头文件。

引用 CMake 的 file() 命令文档:

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

删除CMakeCache.txt重新触发配置

仅删除 CMakeCache.txt 可能不足以重新触发 CMake 配置。 Issue 0014820: warn users about removing only CMakeCache.txt 声称您还需要删除所有 CMakeFiles 目录。

根据我的经验,重新触发 CMake 配置的最可靠方法是触摸其中一个项目 CMakeLists.txt 文件。

注意:对于ninja,CMake 添加了一个rebuild_cache 目标,以便再次为您的项目方便地运行 CMake。

从源代码管理更新后重新触发

想一想:如果源文件被删除是因为它们已从您的源代码管理中删除,那么可能有一种解决方法仍然允许您在源文件上使用file(GLOB ...)

例如如果您使用 GIT,您可以将以下内容添加到您的主 CMakeLists.txt

configure_file($CMAKE_SOURCE_DIR/.git/index $PROJECT_BINARY_DIR/git_index.tmp) 

缺点:它会重新触发每个 GIT 操作(更新、提交、...)的配置。

一些参考资料

run cmake when adding file in eclipse CMake: Correct way to make an arbitrary file trigger

【讨论】:

这是很有价值的信息,但我确实说过我会在必要时手动重新运行 CMake;自动触发重新配置并不是我真正想要的。问题是,即使我手动重新运行 CMake,我似乎也看到了不正确的配置。不过,我需要进行更多调查,以仔细检查我是否可以复制该问题。 @KyleStrand 好的,我承认我以前从未遇到过ninja 的此类问题。我在 Windows 上使用 1.6 版。所以我再次检查了 CMake 的 Ninja 生成器,每次再次运行配置时它都会完全重新生成 rules.ninjabuild.ninja。但是.ninja_deps.ninja_log 文件确实存在。我建议 - 如果你想要一个干净的 ninja 环境 - 你添加类似 if ("$CMAKE_GENERATOR" MATCHES "Ninja") file(REMOVE "$CMAKE_BINARY_DIR/.ninja_deps") endif() 到你的主要 CMakeLists.txt 这是个好主意。如果我有空闲时间,我会玩这个并报告。 看来我无法重现该问题;重新运行 CMake 似乎会忽略以前的源文件条目。我想我上次遇到这个问题时可能忘记更改#include 声明。现在,我将投票关闭。

以上是关于CMake/Ninja 试图编译已删除的“.cpp”文件的主要内容,如果未能解决你的问题,请参考以下文章

C++学习(四四二)cmake ninja build.ninja rules.ninja

使用 WSL 和 VS2019 进行 Cmake

CMake / Ninja:当内容未知时递归“清理”输出目录......?

Cmake,Ninja,BATS,建立在 windows - Clion 风格

使用 CMake + Ninja 使用 GIT 下载依赖项

具有覆盖范围的 CMake ninja 将 gcno 文件放在根二进制目录中