如何在CMake Release模式下启用断言?

Ash*_*ppa 13 assert cmake ndebug

CMake用于编译一些C++文件.assert代码中有调用.在CMake的发布模式下禁用这些调用.NDEBUG我猜它在发布模式中定义.

如果我对在CMake的发布模式下断言感兴趣,我该如何启用它?

sak*_*kra 8

请在CMake常见问题解答中查看此答案,即:

通过更改缓存变量CMAKE_C_FLAGS_RELEASE和的定义手动修复它CMAKE_CXX_FLAGS_RELEASE。每次设置新的构建目录时,都必须执行此操作。

要永久修复它,请在源文件夹中创建一个自定义CMake规则文件,并为释放标志设置所​​需的设置(忽略该选项/D NDEBUG)。然后在最外层的CMakeLists.txt中,将变量CMAKE_USER_MAKE_RULES_OVERRIDE指向自定义CMake规则文件。


use*_*610 7

以下是 LLVM 的做法。LLVM_ENABLE_ASSERTIONS他们向项目添加一个选项(更改LLVM为项目的前缀),然后检查它并过滤编译标志。MSVC 有一个特殊情况。

总的来说,这对我来说似乎比定义构建配置更明智。启用断言是 IMO 与整体构建配置正交的关注点。

# 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()
Run Code Online (Sandbox Code Playgroud)

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


小智 6

1

如果您assert只对自己的代码中的功能感兴趣,那么简单的一种解决方案是提供自定义断言。例如:

#if (MY_DEBUG)
# define MY_ASSERT(A) ... checks here ...
#else
# define MY_ASSERT(A) ... ignore A ...
#endif
Run Code Online (Sandbox Code Playgroud)

使用option启用/禁用断言:

# 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()
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您可以完全控制您的检查,您可以验证一个组件并忽略其他组件:

... FOO_DEBUG=0 BOO_DEBUG=1 BAR_DEBUG=0 ...
Run Code Online (Sandbox Code Playgroud)

2

添加自定义CMAKE_BUILD_TYPE(另见CMAKE_CONFIGURATION_TYPES):

cmake_minimum_required(VERSION 2.8.12)
project(foo)

set(CMAKE_CXX_FLAGS_MYREL "-O3")

add_library(foo foo.cpp)
Run Code Online (Sandbox Code Playgroud)

输出:

# Debug
# ... -g ...

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

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

# MyRel
# ... -O3 ...
Run Code Online (Sandbox Code Playgroud)


let*_*aik 6

这将是MSVC编译器的解决方案:

string( REPLACE "/DNDEBUG" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
Run Code Online (Sandbox Code Playgroud)

更好的选择可能是启用不在释放模式但在RelWithDebInfo模式下的断言:

string( REPLACE "/DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
Run Code Online (Sandbox Code Playgroud)

但这取决于您的项目和偏好当然.