Philip Lowman | 4 Sep 07:10 2008

Re: Understanding why CMAKE_BUILD_TYPE cannot be set

On Wed, Sep 3, 2008 at 2:01 PM, Convey, Christian J CIV NUWC NWPT <christian.convey-JoQm+pnW5+g@public.gmane.org> wrote:
From the mail archives and personal experience, it looks to me like
commands of the form:
  SET(CMAKE_BUILD_TYPE Debug)

aren't effective.  I don't think I fully understood the explanations of
why, though.

Christian,

Ok, CMAKE_BUILD_TYPE is a bit weird principally because it typically gets created as what's called a cache variable on an initial configure.

Regarding the cache...  First, to clear up any confusion you should understand that what you said above is not entirely true.  If you specify CMAKE_BUILD_TYPE like so, for example:

PROJECT(foo)
SET(CMAKE_BUILD_TYPE RelWithDebInfo)
ADD_EXECUTABLE(foo foo.cc)

No matter what your users set CMAKE_BUILD_TYPE in the CMake cache editor it will *always* be RelWithDebInfo when cmake is run (even though it may appear to be set differently with the cmake gui).  You can verify this by doing a "make VERBOSE=1" and examining the compile flags.  The reason this is so is because local variables always trump cache variables in scope.  "ccmake" and friends can only show you cache variables, not variables created when CMake executes your scripts.  If you define a local variable like CMAKE_BUILD_TYPE with the same name as a cache variable, it will override the cache in scope.

So you could simply set CMAKE_BUILD_TYPE to whatever, but this is a bad idea as you probably realize because it leaves your users no choice in choosing their build type.  What you probably want to do is create a cache variable which will allow you to define a default value and type for the variable that the user can then edit, e.g:

SET(CMAKE_BUILD_TYPE Debug CACHE STRING "documentation for this variable")

One of the side effects of the SET(...CACHE) command, however, is only to create a cache variable if one doesn't already exist with that name.  (This is to prevent users from overwriting existing cache variables, if you need to do that you should use the FORCE option on the SET() command).

The timing of setting CMAKE_BUILD_TYPE is, therefore, kinda tricky because as I mentioned earlier, CMake itself defines this on an initial configure.  It turns out that this definition of CMAKE_BUILD_TYPE occurs in the PROJECT() command so to answer your original question, the best way to assign CMAKE_BUILD_TYPE a default option is to do something similar to the following:


#
# If the user specifies -DCMAKE_BUILD_TYPE on the command line, take their definition
# and dump it in the cache along with proper documentation, otherwise set CMAKE_BUILD_TYPE
# to Debug prior to calling PROJECT()
#
IF(DEFINED CMAKE_BUILD_TYPE)
   SET(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
ELSE()
   SET(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel.")
ENDIF()

PROJECT(foo)
ADD_EXECUTABLE(foo foo.cc)
#


Hope this helps.  Also, be aware it will not work on multiple solution generators like for Visual Studio.

--
Philip Lowman
_______________________________________________
CMake mailing list
CMake@...
http://www.cmake.org/mailman/listinfo/cmake

Gmane