5

If you don't set the CMAKE_BUILD_TYPE, then, by default, it doesn't get cached. Should I cache it? e.g. should I have:

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE "Release" )
  set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Type of build (Debug, Release etc." FORCE)
endif()

or just:

if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE "Release" )
endif()

Or does it not really matter?

einpoklum
  • 118,144
  • 57
  • 340
  • 684

2 Answers2

5

Caching of CMAKE_BUILD_TYPE is usefull for cmake-gui: user of your project would able to change a build type in a nice manner.

There is a good template for setting default CMAKE_BUILD_TYPE from developers:

# Set a default build type if none was specified
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
  message(STATUS "Setting build type to 'Debug' as none was specified.")
  set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE)
  # Set the possible values of build type for cmake-gui
  set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release"
    "MinSizeRel" "RelWithDebInfo")
endif()
Tsyvarev
  • 60,011
  • 17
  • 110
  • 153
  • If there are 'configuration types', why would there not be a 'build type'? – einpoklum Mar 08 '18 at 21:37
  • 1
    Having `CMAKE_CONFIGURATION_TYPES` variable defined means that built tool is *multiconfiguration* - it can configure several build types *at once*. For such tool (e.g. Visual Studio) concrete build type isn't known at configuration time, so `CMAKE_BUILD_TYPE` variable is meaningless. – Tsyvarev Mar 08 '18 at 22:10
2

CMAKE_BUILD_TYPE in CMake's Cache

The user would normally define CMAKE_BUILD_TYPE via the command line with cmake -D .... So this does generate a cached entry.

And even when you don't give a CMAKE_BUILD_TYPE for single configuration makefile generators, CMake will automatically create an empty cache entry (so the user can choose in e.g. cmake-gui):

//Choose the type of build, options are: None(CMAKE_CXX_FLAGS or
// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.
CMAKE_BUILD_TYPE:STRING=

If no default for CMAKE_BUILD_TYPE is given by the CMake's Platform/Compiler definitions via CMAKE_BUILD_TYPE_INIT like for Windows-MSVC:

# default to Debug builds
set(CMAKE_BUILD_TYPE_INIT Debug)

Settings a Default for CMAKE_BUILD_TYPE

So yes, if you want to force a default that is visible in the GUI then set the cached variable (see @Tsyvarev answer).

I don't normally force the cached defaults, I just set a temporary value if none is given. This allows e.g. my project to be used as a sub-project.

But that's more a matter of your personal taste.

In my project's those default CMAKE_BUILD_TYPE checks look a little more complex, since I allow more use cases:

# Make RelWithDebInfo the default (it does e.g. add '-O2 -g -DNDEBUG' for GNU)
#   If not in multi-configuration environments, no explicit build type 
#   is set by the user and if we are the root CMakeLists.txt file.
if (NOT CMAKE_CONFIGURATION_TYPES AND 
    NOT CMAKE_NO_BUILD_TYPE AND
    NOT CMAKE_BUILD_TYPE AND
    CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
    set(CMAKE_BUILD_TYPE RelWithDebInfo)
endif()

if (CMAKE_BUILD_TYPE)
    string(TOUPPER "_${CMAKE_BUILD_TYPE}" MY_PROJECT_BUILD_TYPE_EXT)
endif() 

# Choose a configuration for our compiler tests
if (NOT CMAKE_CONFIGURATION_TYPES AND 
    NOT CMAKE_NO_BUILD_TYPE)
    set(CMAKE_TRY_COMPILE_CONFIGURATION "${CMAKE_BUILD_TYPE}")
else()
    set(CMAKE_TRY_COMPILE_CONFIGURATION RelWithDebInfo)
endif()

But probably I should update this code to take the new GENERATOR_IS_MULTI_CONFIG global property into account (instead of checking for CMAKE_NO_BUILD_TYPE).

References

Florian
  • 39,996
  • 9
  • 133
  • 149
  • I'm actually not quite following, especially w.r.t. sub-projects and the com "compile configuration vs the "build type". – einpoklum Mar 06 '18 at 11:43
  • @einpoklum If my project is used as a sub-project via `add_subdirectory()` it should not set/force global properties. So if your parent project doesn't give a default, you shouldn't either. But I as said this is more a matter of taste and the important part here is the `CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR` check. – Florian Mar 08 '18 at 21:09