19
votes

CMake is being used to compile some C++ files. There are assert calls in the code. These calls are disabled in Release mode of CMake. It defines NDEBUG in Release mode, I guess.

If I'm interested in having assert in Release mode of CMake, how do I enable it?

4
Remove this definition from CMAKE_CXX_RELEASE_FLAGS, obviously.arrowd
Note that if you find yourself in need to do the checks in Release, assert might be the wrong tool for the job (although there are still valid use cases for your question, for instance debugging a problem that only occurs in Release). Consider introducing additional diagnostic macros that have weaker semantics than assert (which de facto specifies a condition that must never fail) that but can still be enabled selectively (for instance, a condition that can fail if the user passes invalid arguments to a function).ComicSansMS

4 Answers

12
votes

See this answer in the CMake FAQ, i.e.:

Fix it manually by changing the definition of the cache variables CMAKE_C_FLAGS_RELEASE and CMAKE_CXX_FLAGS_RELEASE. This has to be done every time you set up a new build directory.

To fix it permanently, create a custom CMake rules file in your source folder with the desired settings for the release flags (omit the option /D NDEBUG). Then in your outermost CMakeLists.txt point the variable CMAKE_USER_MAKE_RULES_OVERRIDE to the custom CMake rules file.

9
votes

This would be a solution for the MSVC compiler:

string( REPLACE "/DNDEBUG" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")

A better option may be to enable asserts not in Release mode but in RelWithDebInfo mode instead:

string( REPLACE "/DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")

But this depends on your project and preferences of course.

6
votes

1

If you interested in assert functionality only in your own code then the simple one solution is to provide custom assert. For instance:

#if (MY_DEBUG)
# define MY_ASSERT(A) ... checks here ...
#else
# define MY_ASSERT(A) ... ignore A ...
#endif

Use option to enable/disable assert:

# CMakeLists.txt
option(ENABLE_MY_ASSERT "Turn on MY_ASSERT checks" OFF)
if(ENABLE_MY_ASSERT)
  add_definitions(-DMY_DEBUG=1)
else()
  add_definitions(-DMY_DEBUG=0)
endif()

In this case you have full control over your checks, you can verify one component and ignore others:

... FOO_DEBUG=0 BOO_DEBUG=1 BAR_DEBUG=0 ...

2

Add custom CMAKE_BUILD_TYPE (also see CMAKE_CONFIGURATION_TYPES):

cmake_minimum_required(VERSION 2.8.12)
project(foo)

set(CMAKE_CXX_FLAGS_MYREL "-O3")

add_library(foo foo.cpp)

output:

# Debug
# ... -g ...

# Release
# ... -O3 -DNDEBUG ...

# RelWithDebInfo
# ... -O2 -g -DNDEBUG ...

# MyRel
# ... -O3 ...
1
votes

Here's how LLVM does it. They add a LLVM_ENABLE_ASSERTIONS option to the project (change LLVM to your project's prefix), then check for it and filter the compile flags. There is a special case for MSVC.

Overall, this seems more sensible to me than defining a build configuration. Enabling assertions is IMO orthogonal concern to the overall build configuration.

# This is commonly needed so define it before we include anything else.
string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE)

[...]

if(uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG" )
    option(QD_ENABLE_ASSERTIONS "Enable assertions" ON)
else()
    option(QD_ENABLE_ASSERTIONS "Enable assertions" OFF)
endif()

[...]

if(QD_ENABLE_ASSERTIONS)
    if(NOT MSVC)
        add_definitions(-D_DEBUG)
    endif()
    # On non-Debug builds cmake automatically defines NDEBUG, so we explicitly undefine it:
    if(NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG")
        # NOTE: use `add_compile_options` rather than `add_definitions` since
        # `add_definitions` does not support generator expressions.
        add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-UNDEBUG>)

        # Also remove /D NDEBUG to avoid MSVC warnings about conflicting defines.
        foreach (flags_var_to_scrub
                CMAKE_CXX_FLAGS_RELEASE
                CMAKE_CXX_FLAGS_RELWITHDEBINFO
                CMAKE_CXX_FLAGS_MINSIZEREL
                CMAKE_C_FLAGS_RELEASE
                CMAKE_C_FLAGS_RELWITHDEBINFO
                CMAKE_C_FLAGS_MINSIZEREL)
            string (REGEX REPLACE "(^| )[/-]D *NDEBUG($| )" " "
                    "${flags_var_to_scrub}" "${${flags_var_to_scrub}}")
        endforeach()
    endif()
endif()

Source: https://opensource.apple.com/source/llvmCore/llvmCore-2358.3/CMakeLists.txt.auto.html