如何使用 CMake 在不优化 -O0 的情况下进行编译

如何使用 CMake 在不优化 -O0 的情况下进行编译

我在用科学Linux(SL)。我正在尝试编译一个使用一堆 C++ (.cpp) 文件的项目。

在该目录中user/project/Build,我输入make编译并链接所有.cpp 文件。然后我必须去user/run/然后输入./run.sh values.txt

要使用 GDB 进行调试,我必须转到user/run,然后键入gdb ../project/Build/bin/Project并运行,我输入run -Project INPUT/inputfile.txt。但是,我正在尝试使用 打印出变量的值p variablename

不过,我收到了消息s1 = <value optimized out>。我在网上做了一些研究,似乎我需要在没有优化的情况下进行编译来-O0解决这个问题。但我该在哪里输入呢?在里面CMakeLists?如果是这样,哪个 CMakeLists?project/Build或中的一个project/src/project

答案1

在调用时,通常使用 CMake 进行调试构建所需的全部内容是:

cmake -DCMAKE_BUILD_TYPE=Debug ..

这样做会添加-g标志,可以通过以下方式确认:

make VERBOSE=1

其中显示了 GCC 构建命令,如下所述:https://stackoverflow.com/questions/5820303/how-do-i-force-make-gcc-to-show-me-the-commands

-O0默认情况下不会添加到Debug构建中,但-O0它是默认-O值,如下所述:https://stackoverflow.com/questions/1778538/how-many-gcc-optimization-levels-are-there等等man gcc,所以通常并不重要。

如果您确实想显式控制调试的构建标志,您也可以使用

cmake -DCMAKE_BUILD_TYPE=Debug
      -DCMAKE_C_FLAGS_DEBUG="-g -O0" \
      -DCMAKE_CXX_FLAGS_DEBUG="-g -O0" \
      ..

CMAKE_C_FLAGS_DEBUG和的默认值CMAKE_CXX_FLAGS_DEBUG可以在以下位置找到:https://stackoverflow.com/questions/16851084/how-to-list-all-cmake-build-options-and-their-default-values和:

cmake -LAH .

这使:

// Flags used by the CXX compiler during DEBUG builds.                                                   
CMAKE_CXX_FLAGS_DEBUG:STRING=-g                                                                          
                                                                                                                                                                                          
// Flags used by the C compiler during DEBUG builds.                                                     
CMAKE_C_FLAGS_DEBUG:STRING=-g

该命令还显示了其他感兴趣的值,这些值阐明了构建类型的默认行为:

// Flags used by the CXX compiler during all build types.                               
CMAKE_CXX_FLAGS:STRING=                

// Flags used by the CXX compiler during DEBUG builds.                                       
CMAKE_CXX_FLAGS_DEBUG:STRING=-g             

// Flags used by the CXX compiler during MINSIZEREL builds.                               
CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG

// Flags used by the CXX compiler during RELEASE builds.                                         
CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG     

// Flags used by the CXX compiler during RELWITHDEBINFO builds.
CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG

如果-DCMAKE_BUILD_TYPE=Debug没有通过,CMAKE_BUILD_TYPE则为空,并且不会添加任何额外的CMAKE_CXX_FLAGS_XXX值,因此我们以不带-g.

在 Ubuntu 22.10、CMake 3.24.2 上测试。

答案2

Chip 的答案很有帮助,但是由于该SET行覆盖了默认值,导致我的可执行文件在没有调试信息的情况下构建。我需要对项目源目录中的 CMakeLists.txt 进行一些小的额外修改,以获得使用调试信息构建的可执行文件CMAKE_CXX_FLAGS_DEBUG-g -O0优化(在 cmake 版本 2.8.12.2 上)。

我将以下内容添加到 CMakeLists.txt 以添加-O0并保持-g启用状态:

# Add -O0 to remove optimizations when using gcc
IF(CMAKE_COMPILER_IS_GNUCC)
    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0")
    set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0")
ENDIF(CMAKE_COMPILER_IS_GNUCC)

这会-O0为 CMake 已用于调试的标志添加优化,并且仅在您碰巧使用跨平台项目时才包含在 GCC 构建中。

答案3

将其添加到 CMakeLists.txt(项目源目录中的那个;不要触及构建目录中的任何内容):

SET(CMAKE_CXX_FLAGS_DEBUG "-O0")
SET(CMAKE_C_FLAGS_DEBUG "-O0")

进而

$ cmake -DCMAKE_BUILD_TYPE=Debug

将工作。或者只需将其添加到 CMakeLists.txt:

SET(CMAKE_CXX_FLAGS "-O0")
SET(CMAKE_C_FLAGS "-O0")

答案4

我发现在一些测试中我CMAKE_C_FLAGS默认包含一些优化选项(即-O2)。在这种情况下,上述建议执行类似操作set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0")不会"-O2 -g -O0"禁用优化。

相反,我成功地使用一个简单的正则表达式"-O#"在附加之前用空字符串替换"-O0"

我的正则表达式可能需要一些微调,但到目前为止它似乎工作得足够好:

option(OPTIMIZE "Allow compiler optimizations.  Set to OFF to disable" ON)

if(NOT OPTIMIZE)
    string(REGEX REPLACE "(\-O[011123456789])" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
    string(REGEX REPLACE "(\-O[011123456789])" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")

    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O0")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0")
endif()

相关内容