答案很简单:
cmake 二进制文件当然需要在您每次更改任何构建设置时重新运行,但您不需要按设计这样做;因此,对于您必须发出的命令,“从不”是正确的。
cmake 创建的构建目标自动包含检查随后 [=从主 CMakeLists.txt 文件开始] 涉及或包含生成当前 Makefiles/VS 项目/任何文件集的每个文件。当调用make(假设这里是unix)时,如果需要,这会自动触发cmake的先前执行;因此您生成的项目包含调用 cmake 本身的逻辑!由于最初传递的所有命令行参数(例如cmake -DCMAKE_BUILD_TYPE=RELEASE .. 将存储在CMakeCache.txt 中,您不需要在后续调用中重新指定任何这些参数,这就是为什么项目也可以只运行cmake 并知道它仍然按照您的意愿行事。
更多细节:
CMake 生成簿记文件,其中包含 Makefile/Project 生成中涉及的所有文件,参见例如我的<binary-dir>/CMakeFiles/Makefile.cmake 文件的这些示例内容使用 MSYS 生成文件:
# The top level Makefile was generated from the following files:
set(CMAKE_MAKEFILE_DEPENDS
"CMakeCache.txt"
"C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/CMakeCCompiler.cmake.in"
"C:/Program Files (x86)/CMake/share/cmake-3.1/Modules/RepositoryInfo.txt.in"
"<my external project bin dir>/release/ep_tmp/IRON-cfgcmd.txt.in"
"../CMakeFindModuleWrappers/FindBLAS.cmake"
"../CMakeFindModuleWrappers/FindLAPACK.cmake"
"../CMakeLists.txt"
"../CMakeScripts/CreateLocalConfig.cmake"
"../Config/Variables.cmake"
"../Dependencies.cmake"
"CMakeFiles/3.1.0/CMakeCCompiler.cmake"
"CMakeFiles/3.1.0/CMakeRCCompiler.cmake")
对任何这些文件的任何修改都会触发另一个 cmake 运行只要您选择开始构建目标。老实说,我不知道这些依赖项跟踪在 CMake 中的精细程度如何,即如果其他地方的任何更改不会影响目标的编译,是否只会构建目标。我没想到它会很快变得混乱,而且重复的 CMake 运行(正确使用缓存功能)无论如何都非常快。
唯一需要重新运行cmake 的情况是在启动project(MyProject) 后更改编译器;但即使这种情况现在也由较新的 CMake 版本自动处理(有些大喊大叫:-))。
回复 cmets 的附加评论:
在某些情况下,您需要手动重新运行 cmake,也就是说,每当您编写配置脚本时,cmake 可能无法检测到您正在创建的文件/依赖项。一个典型的场景是您的第一次 cmake 运行使用例如创建文件。 execute_process 然后您将使用file(GLOB ..) 将它们包括在内。这是糟糕的风格,CMake Docs for file 明确表示
注意:我们不建议使用 GLOB 从源代码树中收集源文件列表。如果在添加或删除源时没有 CMakeLists.txt 文件发生更改,则生成的构建系统无法知道何时要求 CMake 重新生成。
顺便说一句,这条评论也阐明了上面解释的生成的构建系统的自我调用:-)
处理在配置期间创建源文件的这种情况的“正确”方法是使用add_custom_command(OUTPUT ...),以便 CMake 能够“感知”正在生成的文件并正确跟踪更改。如果由于某种原因您不能/不会使用add_custom_command,您仍然可以使用源文件属性GENERATED 让CMake 知道您的文件生成。任何带有此标志集的源文件都可以硬编码到目标源文件中,并且 CMake 不会在配置时抱怨缺少文件(并希望在(第一次!)cmake 运行期间生成该文件。