After running the cmake
command once to generate a build system, when, if ever, should I rerun the cmake
command?
The generated build systems can detect changes in the associated CMakeLists.txt
files and behave accordingly. You can see the logic for doing so in generated Makefiles. The exact rules for when this will happen successfully are mysterious to me.
When should I rerun cmake
? Does the answer depend on the generator used?
This blog post (under heading: "Invoking CMake multiple times") points out the confusion over this issue and states that the answer is actually 'never', regardless of generator, but I find that surprising. Is it true?
Make (or rather a Makefile) is a buildsystem - it drives the compiler and other build tools to build your code. CMake is a generator of buildsystems. It can produce Makefiles, it can produce Ninja build files, it can produce KDEvelop or Xcode projects, it can produce Visual Studio solutions.
After you've run cmake , keep the build directory around and you should be able to just run make (it'll detect if a CMakeLists. txt file changed and cmake needs to be invoked again).
Simply delete the CMakeFiles/ directory inside your build directory. rm -rf CMakeFiles/ cmake --build . This causes CMake to rerun, and build system files are regenerated. Your build will also start from scratch.
The answer is simple: The cmake
binary of course needs to re-run each time you make changes to any build setting, but you wont need to do it by design; hence "never" is correct regarding commands you have to issue.
The build targets created by cmake automatically include checks for each file subsequently [=starting from the main CMakeLists.txt file] involved or included generating the current set of Makefiles/VS projects/whatever. When invoking make
(assuming unix here) this automatically triggers a previous execution of cmake
if necessary; so your generated projects include logic to invoke cmake itself! As all command-line parameters initially passed (e.g. cmake -DCMAKE_BUILD_TYPE=RELEASE ..
will be stored in the CMakeCache.txt
, you dont need to re-specify any of those on subsequent invocations, which is why the projects also can just run cmake
and know it still does what you intended.
Some more detail: CMake generates book-keeping files containing all files that were involved in Makefile/Project generation, see e.g. these sample contents of my <binary-dir>/CMakeFiles/Makefile.cmake
file using MSYS makefiles:
# 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")
Any modification to any of these files will trigger another cmake run whenever you choose to start a build of a target. I honestly dont know how fine-grained those dependencies tracking goes in CMake, i.e. if a target will just be build if any changes somewhere else wont affect the target's compilation. I wouldn't expect it as this can get messy quite quickly, and repeated CMake runs (correctly using the Cache capabilities) are very fast anyways.
The only case where you need to re-run cmake
is when you change the compiler after you started a project(MyProject)
; but even this case is handled by newer CMake versions automatically now (with some yelling :-)).
There are cases where you will need to manually re-run cmake, and that is whenever you write your configure scripts so badly that cmake cannot possibly detect files/dependencies you're creating. A typical scenario would be that your first cmake run creates files using e.g. execute_process
and you would then include them using file(GLOB ..)
. This is BAD style and the CMake Docs for file explicitly say
Note: 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.
Btw this comment also sheds light on the above explained self-invocation by the generated build system :-)
The "proper" way to treat this kind of situations where you create source files during configure time is to use add_custom_command(OUTPUT ...)
, so that CMake is "aware" of a file being generated and tracks changes correctly. If for some reason you can't/won't use add_custom_command
, you can still let CMake know of your file generation using the source file property GENERATED. Any source file with this flag set can be hard-coded into target source files and CMake wont complain about missing files at configure time (and expects this file to be generated some time during the (first!) cmake run.
Looking into this topic for reading the version information from a debian/changelog file (generation phase), I ran in the topic that cmake execution should be triggered as debian/changelog is modified. So I had the need to add debian/changelog to CMAKE_MAKEFILE_DEPENDS.
In my case, debian/changelog is read through execute_process. Execute_process unfortunately gives no possibility to add files processed to CMAKE_MAKEFILE_DEPENDS. But I found that running configure_file will do it. Actually I am really missing something like DEPENDENCIES in execute_process.
However, as I had the need to configure the debian/changelog file for my needs, the solution came implicitly to me.
I actually also found a hint about this in the official documentation of configure_file:
"If the input file is modified the build system will re-run CMake to re-configure the file and generate the build system again."
So using configure_file should be a safe to trigger the re-run of cmake.
From a user perspective, I would expect other commands to extend CMAKE_MAKEFILE_DEPENDS, too. E.g. execute_process (on demand) but also file(READ) (implicitly like configure_file). Perhaps there are others. Each read file is likely to influence the generation phase. As an alternative it would be nice to have a command to just extend the dependency list (hint for the cmake developers, perhaps one comes along).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With