CMAKE_BUILD_TYPE is not being used in CMakeLists.txt
Asked Answered
P

3

114

I'm having trouble setting my default build configuration to Release. In my CMakeLists.txt file, I set CMAKE_BUILD_TYPE at the top of the file with:

#enable Release ALWAYS, configure vars
set(CMAKE_BUILD_TYPE Release)
set(EXECUTABLE_NAME "ParticleSimulator")
set(VERSION_MAJOR 0)
set(VERSION_MINOR 2)

But upon building my project and opening the solution, I'm always presented with Debug mode, contrary to what I specified in my CMakeLists file. What am I doing wrong?

I've looked at some of the other question on there, but I didn't see anything that was specific to this question.

A gist of the CMakeLists.txt.

Pestilence answered 27/6, 2014 at 20:43 Comment(6)
Have you cleared your CMake cache? cmake.org/pipermail/cmake/2008-September/023808.htmlCunha
@Cunha Yes, and I've also read though that file. I must be doing something stupid that is blocking CMAKE_BUILD_TYPE from working...Pestilence
@Cunha Still no luck... Also tried set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Configuration type" FORCE) which didn't workPestilence
3rd time for last 2 days)) set(CMAKE_BUILD_TYPE Release) This is not how it's working. Accidentally this will work for Makefile generator, for IDE's like Xcode and Visual Studio this line will be ignored because Release/Debug switched internally. Documentation is pretty clear about that. If you want to limit your build variants you need to set CMAKE_CONFIGURATION_TYPESVivanvivarium
@ruslo Post your comment as an answer, please.Cunha
Aside: Setting the default for CMAKE_BUILD_TYPE is give in this post. Once set giving make VERBOSE=1 shows the complete command sent to the compiler which can be used to verify if it did work.Cobol
V
283

There are two types of generators: single-configurations and multi-configurations.

Single configurations

Make-like generators: Unix Makefiles, NMake Makefiles, MinGW Makefiles, ...

You set the configuration type in the generate step:

cmake -H. -B_builds/Debug -DCMAKE_BUILD_TYPE=Debug "-GUnix Makefiles"

In this case, the build step is always Debug:

> cmake --build _builds/Debug
/usr/bin/c++ -g ...
> cmake --build _builds/Debug --config Debug # `--config` ignored
/usr/bin/c++ -g ...
> cmake --build _builds/Debug --config Release # yep, ignored
/usr/bin/c++ -g ...

Multi-configuration

IDE generators: Visual Studio, Xcode

CMAKE_BUILD_TYPE on generate step is ignored, both:

> cmake -H. -B_builds -DCMAKE_BUILD_TYPE=Debug "-GVisual Studio 12 2013 Win64"

and

> cmake -H. -B_builds -DCMAKE_BUILD_TYPE=Release "-GVisual Studio 12 2013 Win64"

will have the same effect:

Enter image description here

This is because all the configurations is internal (i.e., _builds/msvc-opaque/Release and _builds/msvc-opaque/Debug or something, doesn't matter). You can use --config options to switch:

> cmake --build _builds --config Release
cl /O2 ...
> cmake --build _builds --config Debug
cl /Od ...

Control (?)

Yes, you can. Just define CMAKE_CONFIGURATION_TYPES:

# Somewhere in CMakeLists.txt
message("Generated with config types: ${CMAKE_CONFIGURATION_TYPES}")

Default output:

-- Detecting CXX compiler ABI info - done
Generated with config types: Debug;Release;MinSizeRel;RelWithDebInfo
-- Configuring done

Rewrite it:

> cmake -H. -B_builds -DCMAKE_CONFIGURATION_TYPES="Debug;Release" "-GVisual Studio 12 2013 Win64"
-- Detecting CXX compiler ABI info - done
Generated with config types: Debug;Release
-- Configuring done

Enter image description here

You can even define your own configuration type:

> cmake -H. -B_builds -DCMAKE_CONFIGURATION_TYPES="Debug;MyRelease" -DCMAKE_CXX_FLAGS_MYRELEASE="/My-Rel-flag" -DCMAKE_EXE_LINKER_FLAGS_MYRELEASE="/My-Linker-flags" "-GVisual Studio 12 2013 Win64"

Enter image description here

And build:

cmake --build _builds --config MyRelease

Messy (?)

Not at all if you know the trick :) This is how to build/test configuration in a script/CI server/documentation's build instructions, etc.:

> CONFIG=Debug
> cmake -H. -B_builds "-DCMAKE_BUILD_TYPE=${CONFIG}" # Set Debug to Makefile, ignored by IDE
> cmake --build _builds --config "${CONFIG}" # Build Debug in IDE, ignored by Makefile
> (cd _builds && ctest -VV -C "${CONFIG}") # Test Debug in IDE, ignored by Makefile

Bad pattern

if(CMAKE_BUILD_TYPE STREQUAL Debug) # Burn it with fire!!!
set(CMAKE_BUILD_TYPE MySuperRelease) # Be ready to catch a bug from IDE user...

Good one

set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} --my-debug-flags")

Works nice.

target_compile_definitions(MyTarget PUBLIC "$<$<CONFIG:Debug>:MYDEBUG_MACRO>")

Thank you! :) You save a day for one programmer.

Works for me with Makefile, I'm happy ...

Some quote from a nice book of a nice guy you probably know (emphasis mine):

Why should you bother? People who program on a variety of systems or use a variety of compilers care a lot because if they don’t, they are forced to waste time finding and fixing obscure bugs. People who claim they don’t care about portability usually do so because they use only a single system and feel they can afford the attitude that ‘‘the language is what my compiler implements.’’ This is a narrow and shortsighted view. If your program is a success, it is likely to be ported, so someone will have to find and fix problems related to implementation dependent features. In addition, programs often need to be compiled with other compilers for the same system, and even a future release of your favorite compiler may do some things differently from the current one. It is far easier to know and limit the impact of implementation dependencies when a program is written than to try to untangle the mess afterwards.

Vivanvivarium answered 28/6, 2014 at 21:11 Comment(15)
Please forgive my ignorance... How, exactly, do we set the CMAKE_BUILD_TYPE to Release CmakeList.txt? I think its somewhere in the section Control (?), but I am having trouble parsing it because I'm too inexperienced. Also note we only want to set the default valu; its fine of the user overrides it from the command line.Basion
Thanks for a good answer, but I'm confused by one part. What is the -H. option for? As far as I can tell would print the help, but with . it searches for the CMakeLists.txt in the current directory and then doesn't print the help.Vaclava
I found an answer; -H. is an undocumented feature.Vaclava
I see you tried to fix the documentation issue. Thanks for trying. :) There is still no satisfying answer as to why this can't either be documented or removed (if there really is a risk).Vaclava
@Muscampester just for your info most interesting links and explanation can be found on this pageVivanvivarium
@ruslo Thank you. The linked page provides documentation and best practices that are lacking on the official site.Vaclava
@ruslo What would be the alternative to if(CMAKE_BUILD_TYPE STREQUAL Debug) for checking just that, if current config is "Debug" (without using string equality)? :)Classmate
@Classmate the whole answer was about that you can't do it correctly for all generators. You have to rethink your logic.Vivanvivarium
@ruslo Fair enough! Just swung by looking for my particular issue, and admittedly didn't read the full post! Anyways, thanks!Classmate
How to do config with Not Debug for macro NDEBUGNeoteric
set (DEFINES_JERRY "$<$<CONFIG:Release>:JERRY_NDEBUG>")Neoteric
cmake.org/cmake/help/v3.0/manual/…Neoteric
set (DEFINES_JERRY "$<$<NOT:$<CONFIG:Debug>>:JERRY_NDEBUG>")Neoteric
If you're writing a Makefile by hand, OF COURSE you can set Debug or Release mode at build time, e.g. make BUILD=Debug. I can't imagine why cmake decided to support this in Visual Studio and not Make.Despiteful
If you set a custom build type (instead of debug/release etc) how/where does CMake get the optimization level from?Myel
W
15

You can also use following snippet:

if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING
            "Default build type: RelWithDebInfo" FORCE)
endif()
Woodwaxen answered 13/1, 2020 at 21:31 Comment(2)
People, if you down-vote a submitted answer then, please find a few words to specify why you did it. Because out of all the suggested answers this simple one is the only thing that worked for me. And before that, I found the similar 'accepted' solution here: blog.kitware.com/cmake-and-the-default-build-typeOglethorpe
Does NOT work with Visual Studio generatorVincenzovincible
A
6

One possibility that occurs is that one of the sub-modules had set the CMAKE_BUILD_TYPE value in the cache, that is:

SET(CMAKE_BUILD_TYPE Debug CACHE) 

Meaning that that value will be updated permanently from that point to the end of the configuration run.

One great way to track the offending place where this value has changed is by using CMake's variable_watch. In your main CMakelists.txt file, add the following line

variable_watch(CMAKE_BUILD_TYPE)

This will print to the standard error every access to this variable. And to get it to log file, do something like:

cmake <your options> 2>variable_watch.log

You may see something like:

CMake Debug Log at <...>/CMakeLists.txt:184 (add_library): Variable "CMAKE_BUILD_TYPE" was accessed using READ_ACCESS with value "Debug".

Then you will likely see the point(s) where CMAKE_BUILD_TYPE was first changed. And from here you'll be much closer to trace the offending CMake line.

Alto answered 14/1, 2019 at 13:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.