【问题标题】:Debug vs Release in CMakeCMake 中的调试与发布
【发布时间】:2011-12-05 04:35:10
【问题描述】:

在 GCC 编译的项目中,

  • 如何为每种目标类型(调试/发布)运行 CMake?
  • 如何使用 CMake 指定调试和发布 C/C++ 标志?
  • 如何表示主可执行文件将使用g++ 编译,而一个嵌套库使用gcc

【问题讨论】:

    标签: c++ c gcc cmake


    【解决方案1】:

    使用 CMake,通常建议使用 "out of source" build。在项目的根目录中创建 CMakeLists.txt。然后从项目的根目录:

    mkdir Release
    cd Release
    cmake -DCMAKE_BUILD_TYPE=Release ..
    make
    

    对于Debug(同样来自项目的根目录):

    mkdir Debug
    cd Debug
    cmake -DCMAKE_BUILD_TYPE=Debug ..
    make
    

    Release / Debug 将为您的编译器添加适当的标志。还有RelWithDebInfoMinSizeRel构建配置。


    您可以通过指定toolchain file 来修改/添加标志,您可以在其中添加CMAKE_<LANG>_FLAGS_<CONFIG>_INIT 变量,例如:

    set(CMAKE_CXX_FLAGS_DEBUG_INIT "-Wall")
    set(CMAKE_CXX_FLAGS_RELEASE_INIT "-Wall")
    

    更多详情请见CMAKE_BUILD_TYPE


    至于你的第三个问题,我不确定你到底在问什么。 CMake 应该自动检测并使用适合您不同源文件的编译器。

    【讨论】:

    • 您也可以改为使用cmake -i ..,因此 cmake 将以交互方式运行,询问您想要哪种类型的构建(None、Release、Debug、MinSizeRel、RelWithDebInfo)。
    • @thiagowfx -i 选项会导致此错误消息:The "cmake -i" wizard mode is no longer supported.。我正在使用 cmake 3.7.1
    • 不错的观察。自版本 3.0.0 以来,它似乎已被弃用。 Reference.
    • 如果您正在创建子目录,这不是源代码外构建!建议在源目录之外/之上创建构建目录。
    • 注意如果CMAKE_BUILD_TYPE没有设置,cmake不会选择任何默认的构建类型,因此生成的编译器命令行不会匹配任何构建配置。
    【解决方案2】:

    这里的很多答案都已过时/不好。因此,我将尝试更好地回答它。当然,我会在 2020 年回答这个问题,所以预计情况会发生变化。


    如何为每种目标类型(调试/发布)运行 CMake?

    首先调试/发布在 cmake (nitpick) 中称为配置。

    如果您使用单个配置生成器(Ninja/Unix-Makefiles)

    那么你需要为每个配置创建一个构建文件夹。

    像这样:

    # Configure the build
    cmake -S . -B build/Debug -D CMAKE_BUILD_TYPE=Release
    
    # Actually build the binaries
    cmake --build build/Debug
    

    对于多配置生成器,它略有不同(Ninja Multi-Config、Visual Studio)

    # Configure the build
    cmake -S . -B build
    
    # Actually build the binaries
    cmake --build build --config Debug
    

    如果您想知道为什么这是必要的,那是因为 cmake 不是构建系统。它是一个元构建系统(即构建构建系统的构建系统)。这基本上是处理在 1 个构建中支持多种配置的构建系统的结果。如果您想更深入地了解,我建议您阅读 Craig Scott 的《Professional CMake: A Practical Guide》一书中有关 cmake 的一些内容


    如何使用 CMake 指定调试和发布 C/C++ 标志?

    现代实践是使用目标和属性。

    这是一个例子:

    add_library(foobar)
    
    # Add this compile definition for debug builds, this same logic works for
    # target_compile_options, target_link_options, etc.
    target_compile_definitions(foobar PRIVATE
        $<$<CONFIG:Debug>:
            FOOBAR_DEBUG=1
        >
    )
    

    注意:我如何使用生成器表达式来指定配置! 使用 CMAKE_BUILD_TYPE 将导致任何多配置生成器的构建错误!

    此外,有时您需要全局设置,而不仅仅是针对一个目标。 使用 add_compile_definitions、add_compile_options 等。这些函数支持生成器表达式。除非必须,否则不要使用旧式 cmake(那条路是噩梦之地)


    我如何表达主可执行文件将使用 g++ 编译和一个嵌套库使用 gcc?

    你最后一个问题真的没有意义。

    【讨论】:

      【解决方案3】:

      有关调试/发布标志,请参阅CMAKE_BUILD_TYPE 变量(您将其作为cmake -DCMAKE_BUILD_TYPE=value 传递)。它采用 ReleaseDebug 等值。

      https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/Useful-Variables#compilers-and-tools

      cmake 使用扩展名来选择编译器,因此只需将文件命名为 .c。

      您可以使用各种设置覆盖它:

      例如:

      set_source_files_properties(yourfile.c LANGUAGE CXX) 
      

      会用 g++ 编译 .c 文件。上面的链接还显示了如何为 C/C++ 选择特定的编译器。

      【讨论】:

        【解决方案4】:

        您可以使用add_compile_options,而不是直接操作CMAKE_CXX_FLAGS 字符串(使用string(APPEND CMAKE_CXX_FLAGS_DEBUG " -g3") btw 可以做得更好):

        add_compile_options(
          "-Wall" "-Wpedantic" "-Wextra" "-fexceptions"
          "$<$<CONFIG:DEBUG>:-O0;-g3;-ggdb>"
        )
        

        这会将指定的警告添加到所有构建类型,但只会将给定的调试标志添加到 DEBUG 构建。请注意,编译选项存储为 CMake 列表,它只是一个用分号 ; 分隔其元素的字符串。

        【讨论】:

        • 不会 list(APPEND CMAKE_CXX_FLAGS_DEBUG "-g3") 在 -g3 终止命令并启动新命令之前添加分号 -g3 肯定会失败吗?
        • 你说得对CMAKE_CXX_FLAGS 不是一个 cmake 列表,而是一串以空格分隔的命令行标志。我发现这种行为不一致......
        • add_compile_options() 很简洁。当您还需要向链接器添加选项时,它由 add_link_options() 补充,例如 -fsanitize=address。
        • 2020/cmake 3.17这还是合适的方式吗?最后一行看起来很讨厌
        • @Jay 有点。使用生成器表达式是正确的。但是分号不是必需的,而且真的很难阅读。看我的回答。另外 add_compile_options 并不总是你的意思。这是一把大锤子。
        【解决方案5】:

        如果你想构建一个不同的配置而不重新生成,如果使用你也可以运行cmake --build {$PWD} --config &lt;cfg&gt; 对于多配置工具,选择&lt;cfg&gt; ex。调试、发布、MinSizeRel、RelWithDebInfo

        https://cmake.org/cmake/help/v2.8.11/cmake.html#opt%3a--builddir

        【讨论】:

        • 我尝试使用--config 选项,但没有任何结果。它不会像 -DCMAKE_BUILD_TYPE= 那样影响 $&lt;CONFIG&gt; 变量。
        • 你的意思是cmake --build $PWD --config &lt;cfg&gt;,顺便说一句。
        • CMake 版本 3.20.1:cmake --help 没有表明 --config 是一个有效的参数。也许它已被弃用?当我使用--config cmake 返回CMake Error: Unknown argument --config
        【解决方案6】:

        // CMakeLists.txt : 发布

        set(CMAKE_CONFIGURATION_TYPES "Release" CACHE STRING "" FORCE)
        

        // CMakeLists.txt : 调试

        set(CMAKE_CONFIGURATION_TYPES "Debug" CACHE STRING "" FORCE)
        

        【讨论】:

        • 我不明白为什么这会被否决,这是生产中使用的真实代码,顺便说一句我不在乎。
        • 可能是因为根据 CMake 文档CMAKE_CONFIGURATION_TYPES 包含CMAKE_BUILD_TYPE 的可能值。因此,您应该按照其他答案的建议设置后者。也许您的解决方案有效,因为它将可能的选择限制在您想要的范围内。
        • 赞成,因为这会起作用。我爱我一些 CMake,但有一些怪癖,有时您需要使用大锤子才能使事情正常进行。我有一些项目出于某种原因会拒绝命令行标志。
        • 以下是有关设置可能不起作用的一些附加信息:stackoverflow.com/a/24470998/3196753
        猜你喜欢
        • 1970-01-01
        • 2016-12-14
        • 2018-11-13
        • 2012-01-10
        • 2011-03-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多