我有一个相当复杂的 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_command
的 COMMAND
参数的全部内容上生成的。
生成时 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/