linux - 为什么 Unix Makefiles 的 CMake 生成器会删除文件?

标签 linux cmake generator

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

我检查过这些文件在配置阶段之后存在,但在 Makefile 生成之后和实际调用 make 之前就消失了。

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

文件是在源代码树中创建的。它们的目的是为开发人员提供一些初始代码。开发人员编辑完文件后,应提交给版本控制,除非丢失,否则不得重新创建。如果文件丢失,我有 add_custom_command 来重新创建文件,但这些不是罪魁祸首。

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

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

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

版本

  • 操作系统:Ubuntu 16.04
  • CMake 3.5.1(属于Ubuntu 16.04)

更新

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

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

cmSystemTools::RemoveFile(fname);

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

最佳答案

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

CMake 的行为

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

散列是在自定义命令的当前二进制目录和 add_custom_commandCOMMAND 参数的全部内容上生成的。

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

我的问题的原因

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

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

我的一些 add_custom_command 调用包含在一个 CMake 文件中,该文件来自属于源代码不同子目录的不同 CMakeLists.txt。根据我的实际配置,仅使用 add_subdirectory 添加特定的子目录。

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

结论

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

调试生成阶段

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

关于linux - 为什么 Unix Makefiles 的 CMake 生成器会删除文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58338076/

相关文章:

linux - 将具有相似文件名的文件重命名为相同文件名但不同文件夹

linux - Linux服务器同时最大用户数限制

linux - 从 cvs 中删除具有特定模式的文件

c++ - 使用 libfreenect2 构建

Python:如何访问生成器对象中的元素并将它们放入 Pandas 数据框或字典中?

swift - Swift中的角色游戏效果/药水生成器

linux终端网络浏览器

c++ - Windows 上的 KDE 框架部署

c++ - 如何有选择地启用或禁用项目中整个(外部项目)目录的 -Werror 参数?

python - python 如何知道何时返回生成器?