[CMake] Understanding why CMAKE_BUILD_TYPE cannot be set

Philip Lowman philip at yhbt.com
Thu Sep 4 01:10:11 EDT 2008


On Wed, Sep 3, 2008 at 2:01 PM, Convey, Christian J CIV NUWC NWPT <
christian.convey at navy.mil> 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.cmake.org/pipermail/cmake/attachments/20080904/34bac64c/attachment.htm>


More information about the CMake mailing list