CMake行为:使用Visual Studio的自定义配置类型需要多次cmake运行才能正确显示.这是有意的吗?

Max*_*ser 6 cmake visual-studio visual-studio-2012

语境:

我正在将一个项目从简单的Makefiles迁移到CMake,以添加对多个编译器(gfortran + ifort)和操作系统(Windows + Linux)的支持.当我完成整个过程时,我正在尝试简化CMake行为并为用户提供一些额外的功能.

在对可能的操作系统和使用的编译器组合进行规范化和调整编译器选项之后,添加用户定义的构建类型"DEBUGVERBOSE"并启用所有检查和警告似乎是合理的.因为我们正在处理非常古老的Fortran 77代码,所以这些设置会生成> 3000个警告,这就是为什么我不想在标准的Debug构建类型中包含所有警告的原因.对于将来的代码清理和调试,它似乎是合适的.


问题:

我想将这个用户定义的构建类型"DEBUGVERBOSE"添加到Visual Studio 2012中的可用配置列表中.同时我想摆脱cmake生成的构建类型"MinSizeRel"和"RelWithDebInfo"来简化用户界面(因为我们从不使用这些配置).

根据CMake-Wiki - 如何使用定制的扩展构建模式?我按如下方式设置我的构建类型:

# Set Project Name and supported Languages(optional)
project (s4 Fortran C)
# Set Version Number
set (S4_VERSION_MAJOR 1)
set (s4_VERSION_MINOR 0)

# Set Source Language
enable_language (Fortran)

...

if(WIN32)
  # Release flags
  set(CMAKE_Fortran_FLAGS_RELEASE " ${CMAKE_Fortran_FLAGS_RELEASE} /D__WIN_intel__ /assume:byterecl")
  # Debug Flags
  set(CMAKE_Fortran_FLAGS_DEBUG " ${CMAKE_Fortran_FLAGS_DEBUG} /D__WIN_intel__ /assume:byterecl /Od /warn:all /check:all
                                                              /warn:notruncated_source /warn:nodeclarations /warn:nounused") 
  # verbose Debug flags (user-defined build type)
  set(CMAKE_Fortran_FLAGS_DEBUGVERBOSE  " /debug:full /dbglibs /D__WIN_intel__ /assume:byterecl /Od /warn:all /check:all"
                                      CACHE STRING  "Extended Debug Flags used by the Fortran compiler during verbose Debug builds.") 
  set(CMAKE_CXX_FLAGS_DEBUGVERBOSE      " ${CMAKE_CXX_FLAGS_DEBUG}"
                                      CACHE STRING "Flags used by the C++ compiler during verbose Debug builds."  FORCE )
  set(CMAKE_C_FLAGS_DEBUGVERBOSE        " ${CMAKE_C_FLAGS_DEBUG}"
                                      CACHE STRING "Flags used by the C compiler during verbose Debug builds."    FORCE )
  set(CMAKE_EXE_LINKER_FLAGS_DEBUGVERBOSE "${CMAKE_EXE_LINKER_FLAGS_DEBUG}"
                                      CACHE STRING "Flags used for linking binaries during verbose Debug builds." FORCE )
  set(CMAKE_SHARED_LINKER_FLAGS_DEBUGVERBOSE "${CMAKE_SHARED_LINKER_FLAGS_DEBUG}"
                                      CACHE STRING "Flags used by the shared libraries linker during verbose Debug builds." FORCE )
elseif(UNIX)
   ...<definition of Release, Debug, DebugVerbose Compiler Options>
endif()

# Edit available Configrations to make them available in IDE that support multiple-configuration (for example Visual Studio)
if(CMAKE_CONFIGURATION_TYPES)
  set(CMAKE_CONFIGURATION_TYPES Release, Debug, Debugverbose)
  set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING
      "Reset the configurations to what we need" FORCE)
endif()

...<definition of lots of source files and build targets>...

# Visual Studio Userfile (set the debugging environment):
CreateUserfile()
Run Code Online (Sandbox Code Playgroud)

这在第一个cmake-configure + generate运行中设置(根据cmake-gui和CMakeCache.txt)相应的变量.但是在第二次cmake-configure + generate之后,它们才会出现在Visual Studio解决方案中.我还在命令行中对此进行了测试,在那里我还需要两次运行才能将设置导入Visual Studio.

这种行为也似乎存在于年长的CMake和Visual Studio版本,如中可以看到这个答案,以"如何创建CMake的新配置".这也会导致cmake错误报告0005811:为MSVC创建可能导致此行为的新配置.

我们使用的每个其他生成器(代码:Blocks + MinGW; UNIX Makefiles)都没有此行为,并通过第一次运行完成工作.我知道Visual Studio很特别,因为它是我们设置中唯一的多配置IDE,但我通常不赞成行为不一致,因为它会让用户感到困惑.


问题:

我的方法有什么问题,或者这个cmake行为( - >需要多次运行)目前是否有意/不可更改?



目前的解决方法:

我找到了一个解决方法 - 这里 - 我只将我的用户定义的构建类型附加到现有的配置.注意在设置"project"和"language"之间放置"CMAKE_CONFIGURATION_TYPES"if语句!

# Set Project Name and supported Languages(optional)
project (s4 Fortran C)
# Set Version Number
set (S4_VERSION_MAJOR 1)
set (s4_VERSION_MINOR 0)

# Edit available Configrations to make them available in IDE that support multiple-configuration (for example Visual Studio)
if(CMAKE_CONFIGURATION_TYPES)
 set(CMAKE_CONFIGURATION_TYPES Debugverbose)
 set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING
     "Append user-defined configuration to list of configurations to make it usable in Visual Studio" FORCE)
endif()

# Set Source Language
enable_language (Fortran)

...

if(WIN32)
  ...<definition of Release, Debug, DebugVerbose Compiler Options>
elseif(UNIX)
  ...<definition of Release, Debug, DebugVerbose Compiler Options>
endif

...<definition of lots of source files and build targets>...

# Visual Studio Userfile (set the debugging environment):
CreateUserfile()
Run Code Online (Sandbox Code Playgroud)

使用此解决方案,在第一次cmake-configure + generate运行后,"DEBUGVERBOSE"配置将添加到现有配置中,并在Visual Studio中显示.似乎不可能改变配置列表以省略cmake生成的构建类型"MinSizeRel"和"RelWithDebInfo"(即使在几次cmake运行之后).

使用cmake讨论组中的上述帖子,是否可以改进我的解决方法,以便只在Visual Studio中出现"Release,Debug,DebugVerbose"配置?



编辑:


正如彼得在这个答案中指出的那样,我的实施中存在错误.不幸的是,修复此问题并未改变Visual Studio 2012的行为.

# Set Project Name and supported Languages(optional)
project (s4)

...

# Set Source Language
enable_language (Fortran C)

...
Run Code Online (Sandbox Code Playgroud)

我在修改过程中遇到的唯一区别是将新的CMakeCache.txt与前一个CMakeCache.txt进行比较:CMake为"CXX"添加了Compiler Flags.我认为这意味着C++,C#等编译标志?

从此开始构建并在重新阅读cmake讨论组的相应帖子后,我开始尝试.使用PROJECT,enable_language和CMAKE_CONFIGURATION_TYPES相对于彼此的几种组合进行测试我想分享我的发现.

  1. PROJECT 之后的 CMAKE_CONFIGURATION_TYPE (s4 Fortran C),例如省略enable_language:
    如果没有enable_language,代码需要2次CMake传递,以使Visual Studio识别新设置,同时使用第一次传递更新Cache.因此,似乎enable_language将设置传播到Visual Studio*.sln文件.

  2. PROJECT(s4)语句之前的 CMAKE_CONFIGURATION_TYPES :
    需要第二次cmake传递才能将设置传播到CMakeCache.txt.但Visual Studio无法识别设置.使用此设置,似乎可以更改可用的构建类型,但因为Visual Studio无法识别它们并且需要第二个cmake传递来传播它们,所以此选项对我的情况不可行.

  3. CMAKE_CONFIGURATION_TYPES 之间 PROJECT(S4)和enable_language(Fortran的C):
    设置被识别与所述第一通无论在CMakeCache.txt和Visual Studio.后续的cmake传递不会改变缓存.因此,我认为这种方法是合适的

虽然删除某些构建类型或重写CMAKE_CONFIGURATION_TYPES似乎不可能.我测试了上述讨论组的建议,例如,明确地将新的构建类型附加了LIST(APPEND ...)并检查/删除重复项.虽然这些措施在配置例程中隐式实现,但因为添加(或省略)这些措施并未改变行为或缓存文件(无论是使用语句LIST(APPEND ...)还是SET(...)) ).

我注意到的另一个行为是用户定义的字符串

   set(CMAKE_CONFIGURATION_TYPES ${CMAKE_CONFIGURATION_TYPES}
                                 CACHE STRING "Append user-defined configuration to list of configurations to make it usable in Visual Studio" FORCE)
Run Code Online (Sandbox Code Playgroud)

仅在2.案例中被认可.使用3. Case似乎被忽略,并且似乎在Cache中设置了标准CMake字符串.


结果:

根据这些发现,遵循当前实施的代码.

# Set Project Name
project (s4)
# Set Version Number
set (S4_VERSION_MAJOR 1)
set (s4_VERSION_MINOR 0)

# Edit available Configrations to make them available in IDE that support multiple-configuration (for example Visual Studio)
# has to be between "project" and "enable_language" to work as intended!
if(CMAKE_CONFIGURATION_TYPES)
   list(APPEND CMAKE_CONFIGURATION_TYPES Debugverbose)
   set(CMAKE_CONFIGURATION_TYPES ${CMAKE_CONFIGURATION_TYPES}
                                 CACHE STRING"Append user-defined configuration to list of configurations to make it usable in Visual Studio" FORCE)
endif()

# Set Source Language
enable_language (Fortran C)

...
Run Code Online (Sandbox Code Playgroud)

我采用了LIST(APPEND ...)语句,因为它提高了可读性并明确说明了代码正在做什么.如上所述,它不会改变CMake的行为,例如自动检查重复项.


开放式问题:

我的实验有没有错误的结论?也许有人知道内部的CMake程序是否足以详细阐述上述行为?例如,为什么集合中的字符串(CMAKE_CONFIGURATION_TYPES ...)语句无法识别?

最初的问题仍然存在:

有没有办法将CMAKE_CONFIGURATION_TYPES重置为用户定义的列表,并将这些设置传递给Cache和Visual Studio只有1个CMake传递?

Pet*_*ter 1

在您提到的帖子中cmake-discussion,据说您应该

  • 在 PROJECT() 之前设置 CMAKE_CONFIGURATION_TYPES
  • 在 PROJECT() 之后附加到 CMAKE_CONFIGURATION_TYPES -在不使用语言的情况下调用- 但在 ENABLE_LANGUAGE() 之前

在您的解决方法中,您可以在 CMAKE_CONFIGURATION_TYPES 之前设置语言:

project (s4 Fortran C)
Run Code Online (Sandbox Code Playgroud)

最好的方法是将 CMAKE_CONFIGURATION_TYPES 设置为 cmake 命令的参数

cmake ..... -DCMAKE_CONFIGURATION_TYPES:STRING=Debug ...
Run Code Online (Sandbox Code Playgroud)