51

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?

4
  • What about if your new code requires a new library to be linked with? I think then you should have to rerun cmake. Commented Jan 31, 2015 at 9:40
  • 1
    @GuyL Actually, in that case I think you're good to go. Commented Jan 31, 2015 at 9:48
  • because of the changes detected in CMakeLists.txt? I'm not an expert in cMake (I've only used it for cLion projects) Commented Jan 31, 2015 at 9:53
  • 1
    Yes, the generated build systems are aware of the CMakeLists.txt files and can refer back to them to check for changes and modify the build accordingly. Commented Jan 31, 2015 at 9:56

2 Answers 2

41

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 :-)).

additional comment responding to comments:

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.

Sign up to request clarification or add additional context in comments.

9 Comments

you change the compiler after you started a project(MyProject) simply don't do it :) set compiler before project/in toolchain/explicitly as a cmake '-D' parameters
please consider the context of that question. i hope it is clear to everyone that you should not change the compiler that way! even cmake will yell at you when you do that.
Well yes, I'm not sure I understand the last part correctly. By 're-run cmake' I mean invoking it with the old build directory. So when you change the compiler you must create new build directory. So I don't agree that it's 're-run' - you're running new project from scratch. tl;dr You never need to re-run cmake, no exceptions :)
This answer would be improved by addressing file globbing and similar cases. If you think those are things that shouldn't be done feel free to suggest against them, but they are nonetheless part of a complete answer. It is clear to me when use of file globbing would require manually rerunning cmake. It is not clear to me when other external commands would cause manually rerunning cmake to be necessary.
@ruslo yes if you use cmake correctly that is exactly what you should do. however if you code badly and issue compiler-changing commands from within your configure script (after project() command), that will have cmake automatically re-run.
|
1

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).

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.