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.

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.