在 CMake 中更改 CMAKE_CXX_FLAGS_DEBUG 和朋友的默认值

2021-12-26 00:00:00 compiler-optimization cmake c++

我想更改 CMake 中 CMAKE_CXX_FLAGS_RELEASECMAKE_CXX_FLAGS_DEBUG 的默认值.基本上,我有一些项目默认值与 CMake 的(例如发布版)略有不同,我不应该问自己哦,当使用 add_compile_options 添加时,他们的 -O3 还是我们的 -O2 优先."

I would like to change the default values for CMAKE_CXX_FLAGS_RELEASE or CMAKE_CXX_FLAGS_DEBUG in CMake. Basically, I have some project defaults that differ just slightly from CMake's (for release, for instance), and I shouldn't have to ask myself "Oh, does their -O3 or our -O2 take precedence when added with add_compile_options."

现在,我知道如何设置这些值,但我不知道如何通过两种常用方式让用户可以编辑它们:通过在命令行上使用 -DCMAKE_CXX_FLAGS_DEBUG=yourflags 或通过使用 ccmake 或 CMakeSetup 对其进行配置.

Now, I know how to set these values, but I don't know how to make them user editable in the two usual ways: by using -DCMAKE_CXX_FLAGS_DEBUG=yourflags on the command line or by configuring it with ccmake or CMakeSetup.

问题在于 CMAKE 为这些设置并缓存了自己的默认值,如果您尝试在不使用 FORCE 的情况下覆盖变量,则默认值"永远不会更改.如果我在我的 set 命令中使用 FORCE:set(CMAKE_CXX_FLAGS_DEBUG blah CACHE STRING "" FORCE),它会在每次运行脚本时覆盖它,从而消除用户根据需要更改它的可能性.

The problem being that CMAKE sets and caches its own defaults for these, and if you try to overwrite the variables without using FORCE, the "defaults" are never changed. If I use FORCE in my set command: set(CMAKE_CXX_FLAGS_DEBUG blah CACHE STRING "" FORCE), it will overwrite it every time the script is run, eliminating the possibility for the user to change it if he wishes.

我通过执行以下操作设法破解它以与 CCMAKE 一起使用,但这仍然不适用于 cmake -DCMAKE_CXX_FLAGS_DEBUG,因为它会在用户完成更改后覆盖:

I managed to hack it to work with CCMAKE by doing the following, but this still doesn't work with cmake -DCMAKE_CXX_FLAGS_DEBUG as it overwrites the user change AFTER he's done it:

set(DEFAULTS_SET FALSE CACHE BOOL "")
set(CMAKE_CXX_FLAGS_DEBUG "-this -that" CACHE STRING "" FORCE)
set(DEFAULTS_SET TRUE CACHE BOOL "" FORCE)

显然,这是一个令人讨厌的 hack 并且不能完全起作用(在 cmake -Dwhatever=thisorthat 的情况下).我也可以添加其他构建类型,但我真的不明白为什么仅仅为了改变一些简单的事情就需要这样做.

Obviously, this is a nasty hack and doesn't completely work(in the case of cmake -Dwhatever=thisorthat). I could add other build types as well, but I don't really see why that should be necessary just to change a few simple things.

编辑 2015 年 3 月 1 日:

我已经创建了一个有效的解决方案,但我仍然对我必须做的事情并不感到非常兴奋.我看到其他评论解决了设置 CMAKE_CXX_FLAGS_DEBUG 和朋友的问题,而不会让他们受到破坏,但这最初对我不起作用,因为我还试图根据编译器选择它们正在使用中.然而,编译器在它已经为我填充变量之前是不确定的.我使用的技巧如下.您必须在项目命令之前将标志变量设置为特殊".

I've created a solution that works, though I still am not super thrilled about what I have to do. I'd seen other comments that solve the problem of setting CMAKE_CXX_FLAGS_DEBUG and friends without having them get clobbered, but this originally didn't work for me because I was trying to also select them based on the compiler that was in use. The compiler isn't determined, however, until it has already filled the variables for me. The trick I used is as follows. You must set the flags variables to something 'special' before the project command.

set(CMAKE_CXX_FLAGS_DEBUG "_UNSET" CACHE STRING "")
project(your_project C CXX)

if(${CMAKE_CXX_FLAGS_DEBUG} STREQUAL "_UNSET")
    # Do some compiler switching here and then set your flags with FORCE.
    set(CMAKE_CXX_FLAGS_DEBUG "-ggdb3 -O0" CACHE STRING "" FORCE)
endif()

这现在允许我选择可以通过命令行使用 -D 或在 cmake-gui 中完全覆盖的默认值.

This now allows me to choose defaults that are completely override-able via command line with -D or in cmake-gui.

推荐答案

我只是想添加我看到的四种可能性:

I just wanted to add the four possibilities I see:

  1. 拥有自己的工具链文件,其中包含您支持的每个编译器的预设,例如:

  1. Having your own toolchain files containing the presets for each compiler you support like:

GNUToolchain.cmake

 set(CMAKE_CXX_FLAGS_DEBUG "-ggdb3 -O0" CACHE STRING "")

然后用它

 cmake -DCMAKE_TOOLCHAIN_FILE:string=GNUToolchain.cmake ...

  • 您可以通过检查CMAKE_GENERATOR(在 <代码>项目()命令):

    CMakeLists.txt

     if("${CMAKE_GENERATOR}" MATCHES "Makefiles" OR 
        ("${CMAKE_GENERATOR}" MATCHES "Ninja" AND NOT WIN32))
         set(CMAKE_CXX_FLAGS_DEBUG "-ggdb3 -O0" CACHE STRING "")
     endif()
    
     project(your_project C CXX)
    

  • 您可以使用CMAKE_USER_MAKE_RULES_OVERRIDE 用你自己的 ..._INIT 值给出一个脚本:

    它在 CMake 的内置编译器和平台信息模块加载之后但在使用信息之前加载.该文件可能会设置平台信息变量以覆盖 CMake 的默认值.

    It is loaded after CMake’s builtin compiler and platform information modules have been loaded but before the information is used. The file may set platform information variables to override CMake’s defaults.

    MyInitFlags.cmake

     # Overwrite the init values choosen by CMake
     if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
         set(CMAKE_CXX_FLAGS_DEBUG_INIT "-ggdb3 -O0")
     endif()
    

    CMakeLists.txt

     set(CMAKE_USER_MAKE_RULES_OVERRIDE "MyInitFlags.cmake")
    
     project(your_project C CXX)
    

  • 从 3 月 1 日起,您可以通过检查编译器标志变量的 ..._INIT 变体来简化您的解决方案:

  • You can simplify your solution from March 1st by checking against the ..._INIT variants of the compiler flag variables:

    CMakeLists.txt

     project(your_project C CXX)
    
     if (DEFINED CMAKE_CXX_FLAGS_DEBUG_INIT AND  
         "${CMAKE_CXX_FLAGS_DEBUG_INIT}" STREQUAL "${CMAKE_CXX_FLAGS_DEBUG}")
         # Overwrite the init values choosen by CMake
         if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
             set(CMAKE_CXX_FLAGS_DEBUG "-ggdb3 -O0" CACHE STRING "" FORCE)
         endif()
     endif()
    

  • 评论:

    我更喜欢并使用工具链变体.但我承认它的缺点是必须手动提供工具链文件(如果您不是通过脚本/批处理文件调用 cmake).

    I prefer and use the toolchain variant. But I admit it has the disadvantage of having to give the toolchain file manually (if you are not calling cmake via a script/batch file).

    参考文献:

    • CMake:文件解析的顺序(缓存、工具链等)?
    • cmake - 全局链接器标志设置(适用于所有目录中的目标)
    • 使用 CMake 在 GCC 和 Clang/LLVM 之间切换

    相关文章