CMake and the Default Build Type

One thing that can be a little confusing when you first start using CMake to build your project is the default build type – specified in the CMAKE_BUILD_TYPE variable. CMake has several default build types, but if nothing is specified when configuring your project it defaults to an empty string and no optimization flags are used. A few years ago I wrote some CMake code to set a default if one was not specified, and also populate a list of available options so that it would show up in cmake-gui as a drop down list.

# Set a default build type if none was specified
set(default_build_type "Release")
  set(default_build_type "Debug")

  message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
  set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE
      STRING "Choose the type of build." FORCE)
  # Set the possible values of build type for cmake-gui
    "Debug" "Release" "MinSizeRel" "RelWithDebInfo")

The code snippet above shows a slightly modified version, that I put in a file called BuildType.cmake, and use it to ensure the build type defaults to something reasonable for generators that use it. If you add the directory containing this file to the CMAKE_MODULE_PATH in your project you can then include it somewhere near the top of your CMakeLists.txt. It will now default to using a debug build if the source directory is a git clone, or a release build if not. It is also quite easy to customize its behavior according to the preferences of your project.

If a build type is supplied on the command line that will be respected, and for multi configuration generators (such as Visual Studio) this doesn’t apply (indicated by the presence of the CMAKE_CONFIGURATION_TYPES variable). I have found it useful to develop a few files like this that can easily be dropped into a CMake-based project to provide default settings.

8 Responses to CMake and the Default Build Type

  1. Francois Budin says:

    Great idea. Thanks for sharing these lines of code. I think other projects (such as Slicer) have a similar approach. Maybe it would make sense to consolidate everything into one file (directly included in CMake?)

    • Marcus D. Hanwell says:

      Yeah, there is similar stuff in several projects. I wanted something easy to add across several distinct projects, and thought this would be easy to drop in independently of anything else. What else would you want to do for setting the default build type, I thought this was about as fancy as it needed to get 🙂

      • Francois Budin says:

        My idea was not on improving the code you wrote but where it could be shared and if it should directly be included in CMake since many projects such as Slicer ( use it or something similar.

        • Marcus D. Hanwell says:

          Good point, I am not sure how they would feel about it. On the one hand it is a simple snippet, and I would never mark that variable as advanced, and some people want to change the default for source check outs whereas others would not.

          Happy to see it adopted, I said to a colleague that I would try and write some posts documenting some of what I did as best practice in CMake projects at a recent meeting. This was hopefully my first in a series as I find time – if there is interest in integrating any code snippets that would be great.

  2. Jean-Christophe Fillion-Robin says:

    Well done.

    The version found in Slicer was copied from you did few year ago 🙂 And yes, it would be great to add it as a CMake module.

    (and I am not particularly attached to advanced vs non-advanced variable.)

  3. Why the FORCE is needed?

    • Marcus D. Hanwell says:

      In case the cache variable already exists, but is set to empty, the use of FORCE ensures the new setting will show up in ccmake/cmake-gui. Otherwise it could confuse, it is possible it is not strictly necessary but if we are setting the build type I wanted to ensure we did it in a way that was visible in the GUIs.

  4. Joe says:

    Shouldn’t you use CMAKE_BUILD_TYPE_INIT before project instead of overriding CMAKE_BUILD_TYPE

Questions or comments are always welcome!