buildmakefilecmakebuild-process

Is there a way to perform atomic CMake build?


I'm considering reimplementing our build system (currently based on GNU Make) in CMake.

Disclaimer: this is more of a theoretical and "best practices" question. I don't know CMake in-depth. Also, please feel free to migrate the question to programmers if it's more on-topic there.

As far as I understand, the standard workflow for CMake is

cmake .
make

I suspect there may be problems of de-synchronization of CMake files and Makefiles.

So, during usual development process you're supposed to run make to avoid unnecessary rebuilds of CMakeCache and Makefiles and generally make the process more straight-forward. But then, if you add, say, a new source file to CMakeLists and run make, it'll be using old CMakeCache and Makefiles and will not regenerate them automatically. I think it may cause major problems when used at scale, since in case something is not building as it should, you'll have to try to perform make clean, then, if it doesn't help, you'll need to remove CMakeCache and regenerate everything (manually!).

If I'm not right about something of the above, please correct me.

I'd like to just do

awesome-cmake

and have it update everything what needs updating and build the project.

So, the question: is there a way to make "atomic build" with CMake so that it tracks all the required information and abstracts away the usage of make?


Solution

  • I think you have a couple of incorrect ideas here:

    I suspect there may be problems of de-synchronization of CMake files and Makefiles.

    Ultimately, CMake is all about producing correct Makefiles (or Visual Studio solution files, or XCode project files, or whatever). Unless you modify a generated Makefile by hand, there can be no synchronisation issue between CMake and the Makefile since CMake generates the Makefile.


    But then, if you add, say, a new source file to CMakeLists and run make, it'll be using old CMakeCache and Makefiles and will not regenerate them automatically.

    Actually, the opposite is true: if you modify the CMakeLists.txt (e.g. adding a new source, changing a compiler flag, adding a new dependency) then running make will trigger a rerun of CMake automatically. CMake will read in its previously cached values (which includes any command line args previously given to CMake) and generate an updated Makefile.


    in case something is not building as it should, you'll have to try to perform make clean, then, if it doesn't help, you'll need to remove CMakeCache and regenerate everything (manually!).

    Yes, this would be a pretty normal workflow if something has gone wrong. However, things don't often get that bad in my experience.


    So, the question: is there a way to make "atomic build" with CMake so that it tracks all the required information and abstracts away the usage of make?

    Given that running make will cause CMake to "do the right thing", i.e. rerun if required, I guess that using make is as close to an "atomic build" as possible.

    One thing to beware of here is the use of file(GLOB ...) or similar to generate a list of source files. From the docs:

    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.

    In other words, if you do use file(GLOB ...) to gather a list of sources, you need to get into the habit of rerunning CMake after adding/removing a file from your source tree; running make won't trigger a rerun of CMake in this situation.