19

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

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

4

4 回答 4

12

请参阅CMake 常见问题解答中的此答案,即:

通过更改缓存变量的定义CMAKE_C_FLAGS_RELEASECMAKE_CXX_FLAGS_RELEASE. 每次设置新的构建目录时都必须这样做。

要永久修复它,请在源文件夹中创建一个自定义 CMake 规则文件,其中包含所需的发布标志设置(省略选项/D NDEBUG)。然后在最外面的 CMakeLists.txt 中将变量CMAKE_USER_MAKE_RULES_OVERRIDE指向自定义 CMake 规则文件。

于 2014-03-03T12:44:31.877 回答
9

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

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

更好的选择可能是不在 Release 模式下启用断言,而是在 RelWithDebInfo 模式下启用:

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

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

于 2017-02-08T17:35:52.547 回答
6

1

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

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

用于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()

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

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

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)

输出:

# Debug
# ... -g ...

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

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

# MyRel
# ... -O3 ...
于 2014-03-05T05:21:00.160 回答
1

以下是 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()

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

于 2021-01-29T12:56:37.587 回答