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

时间:2013-12-17 16:04:50

标签: visual-studio visual-studio-2012 cmake

上下文

我将项目从普通的Makefile迁移到CMake,以添加对多个编译器(gfortran + ifort)和操作系统(Windows + Linux)的支持。在我完成整个事情的过程中,我试图简化CMake行为并为用户提供一些额外的功能。

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


问题:

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

根据CMake-Wiki - How can I extend the build modes with a custom made one?我按如下方式设置我的构建类型:

# 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()

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

这种行为似乎也出现在旧的cmake和Visual Studio版本中,如this answer"How to create a new configuration with CMake"中所示。这也会导致可能导致此行为的cmake错误报告0005811: Creating new configurations for MSVC

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


问题:

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



当前解决方法:

我找到了一种解决方法 - here - 我只将我的用户定义的构建类型附加到现有的配置中。注意&#34; CMAKE_CONFIGURATION_TYPES&#34;的位置。设置&#34;项目&#34;之间的if语句和&#34;语言&#34;!

# 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()

通过这个解决方案&#34; DEBUGVERBOSE&#34;第一次cmake-configure + generate运行后,配置将添加到现有配置中,并在Visual Studio中显示。似乎不可能改变配置列表以省略cmake生成的构建类型&#34; MinSizeRel&#34;和&#34; RelWithDebInfo&#34; (即使经过几次cmake运行)。

使用cmake讨论组中的above mentioned post,是否可以改进我的解决方法,以便只有配置&#34; Release,Debug,DebugVerbose&#34;会出现在Visual Studio中吗?



编辑:


正如彼得在this回答中所指出的,我的实施中存在错误。遗憾的是,修复此问题并未改变Visual Studio 2012的行为。

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

...

# Set Source Language
enable_language (Fortran C)

...

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

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

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

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

  3. CMAKE_CONFIGURATION_TYPES 介于 PROJECT(s4)和enable_language(Fortran C)之间:
    通过CMakeCache.txt和Visual Studio中的第一次传递识别设置。随后的cmake传递不会改变缓存。因此,我认为这种方法是充分的。

  4. 似乎无法删除某些构建类型或重写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)
    

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


    结果:

    从这些调查结果可以看出实施的当前代码。

    # 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)
    
    ...
    

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


    OPEN QUESTIONS:

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

    最初的问题仍然存在:

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

2 个答案:

答案 0 :(得分:1)

在你提到cmake-discussion的帖子中,声明你应该

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

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

project (s4 Fortran C)

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

cmake ..... -DCMAKE_CONFIGURATION_TYPES:STRING=Debug ...

答案 1 :(得分:0)

如果你想调用&#39; project&#39;没有语言,您必须使用以下语法:

project(s4 LANGUAGES NONE)

否则

project(s4)

将使用两种默认语言CXX和C调用项目。