How do I set define based on current build type?

I want to ensure that a particular compiler definition is set/not set based on the build type. I thought that this would work but it’s not:

  if($ENV{CMAKE_BUILD_TYPE} MATCHES "[Dd][Ee][Bb][Uu][Gg]")
    # In case it was added
    remove_definitions("-DNDEBUG")
  else()
    # In case it wasn't added
    add_compile_definitions("NDEBUG")
  endif()

I also tried:

  if($<CONFIG:Debug>)

and

  if(${CMAKE_BUILD_TYPE} MATCHES "[Dd][Ee][Bb][Uu][Gg]")

What am I doing wrong?

Hmmm, I did a message(STATUS "NON DEBUG FOUND '${CMAKE_BUILD_TYPE}'") command in the else() branch and it turns out that variable wasn’t set. :frowning:

But how about the generator function?

I would just always remove it and then do something like this:

add_compile_definitions("$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")

Ooo! That’s great. However, I need to be able to remove it and it would seem that remove_definitions doesn’t expand generator expressions. That’s unfortunate. :frowning:

It’s really unclear where generator expressions can work correctly.

Thx.

Why would you need to remove this definition? You can make the genex more complicated if you have more intricate logic…

The general rule is that if the documentation doesn’t explicitly say generator expressions are supported, then they are not supported for that documented thing.

To help you more generally, generator expressions cannot be evaluated during the configure phase. What that means is that you cannot switch logic in your CMakeLists.txt files based on a value that may contain generator expressions. That’s why something like if($<CONFIG:Debug>) can’t work. The if() command is logic evaluated at configure time. The $<CONFIG:Debug> generator expression can only be evaluated at generation time (which is after the configure phase is finished, i.e. after processing all the CMakeLists.txt files has finished).

1 Like

The reason is legacy. I just came on to the project and I’m not going to disrupt their current workflow until I understand it.

Though, if I understand the cmake system correctly, I can explicitly remove the define with this:

remove_definitions("-DNDEBUG")

and use your:

code without affecting the rest of the project, as this stuff percolates up into the directory tree. Everything below that doesn’t see anything. Is that right?

It’d only be seen by the directory that does this and any children. There’s no mechanism to affect parent scopes beyond one level with PARENT_SCOPE, the cache, or setting DIRECTORY properties on specific directories.

1 Like

I would recommend using target_compile_definitions instead, to just add the compile definitions to the targets that need them.

There shouldn’t be a need to remove definitions at any point, you can just not add them.

As I said before, I’m new here and they have this defined in the root CMakeLists.txt file as:

if (DEBUG_MODE OR SANITIZER_ENABLED)
else (DEBUG_MODE OR SANITIZER_ENABLED)
    add_compile_definitions("NDEBUG")
endif(DEBUG_MODE OR SANITIZER_ENABLED)

And until I can explain why this is, I can’t/won’t change it as it may break something else. Something very bad on a RT motor controller. My code isn’t run on the controller. It’s just a Windows app, that takes the data that the controller generates and spits it out in human readable form.

Something like that if can only work with single-configuration generators (e.g. makefiles) where separate build trees are used for debug and release builds. For these single-config generators you can use the value of CMAKE_BUILD_TYPE to determine the build type that is being generated (see here for info on this variable).

For multi-config generators such as visual studio CMAKE_BUILD_TYPE is not set/defined.
The way your if is written makes me think you are using a single-config generator. It would help if we knew what toolchain you are using (for both your RT motor controller project and your windows app project).

Also: find out where the variables DEBUG_MODE and SANITIZER_ENABLED are set. Are they set on the command line when CMake is called?

To support multi-config generators, the genex I posted before would be the most useful.