首页 > 解决方案 > 为什么 Unix Makefiles 的 CMake 生成器会删除文件?

问题描述

我有一个相当复杂的 CMake 配置,其中包含几个execute_process在配置阶段创建文件的命令。有时在 CMake 配置中进行一些更改后,生成阶段会删除这些文件。我可以重现那个。

我已经检查了这些文件在配置阶段之后是否存在,但在 Makefile 生成之后和实际调用make.

在某些情况下,这些文件是${CMAKE_COMMAND} -E copy通过调用脚本创建的,在其他情况下,通过调用${CMAKE_COMMAND} -P包含configure_file替换模板中某些占位符的调用的脚本。

这些文件是在源代码树中创建的。他们的目的是为开发人员提供一些初始代码。当开发人员编辑了文件后,它们应该被提交给版本控制并且除非它们丢失,否则不要再次重新创建它们。如果文件丢失,我必须add_custom_command重新创建文件,但这些不是罪魁祸首。

我知道,您更喜欢一个简单的测试示例,但不幸的是,这并不容易创建,所以我的问题是:

可能是什么原因,我该如何调试?

不幸的是,--trace选项cmake不提供有关生成阶段的任何日志数据。

版本

更新

我已经用当前的主提交(696b2d4)编译了 CMake 本身,并且行为仍然相同。

通过在调试器下运行 CMake,我发现该行

cmSystemTools::RemoveFile(fname);

in 函数cmGlobalGenerator::CheckRuleHashes(std::string const& pfile, std::string const& home)实际上删除了文件。它是从 调用的cmGlobalGenerator::Generate()

标签: linuxcmakegenerator

解决方案


通过进一步调试(请参阅问题中的更新),我找到了问题的原因。

CMake 的行为

CMake 的全局生成器创建文件${CMAKE_BINARY_DIR}/CMakeFiles/CMakeRuleHashes.txt。它包含每个带有输出的自定义命令的行。每行包含一个哈希和自定义命令第一个输出的路径。

哈希是在自定义命令的当前二进制目录COMMANDadd_custom_command.

在生成时,CMake 会执行cmGlobalGenerator::CheckRuleHashes以检查哈希是否仍然是最新的。如果哈希不是最新的,则相应的输出文件将被删除,显然是在构建阶段触发自定义命令的重新执行。

我的问题的原因

execute_process如问题中所述,我在配置期间执行文件创建命令,并add_custom_command使用相同的文件创建命令调用以触发文件的重新创建,以防文件丢失。

CMakeRuleHashes.txt因此,CMake 在其中为要创建的文件创建了一个哈希行。

我的一些add_custom_command调用包含在一个 CMake 文件中,该文件包含CMakeLists.txt在源的不同子目录中。根据我的实际配置,只有特定的子目录会添加add_subdirectory.

因此,因为子目录是自定义命令的散列的一部分,所以散列会根据添加的包含自定义命令的子目录而改变。然后更改的哈希会导致输出文件的删除。

结论

我必须重新设计我的 CMake 配置以解决自定义命令对 CMake 二进制目录的依赖性。

调试生成阶段

这可以通过将 CMake 本身编译为Debug构建类型并在调试器下运行来完成。


推荐阅读