Cmake generators for Visual Studio do not set CMAK

2020-02-02 00:14发布

问题:

The Cmake FAQ and other places recommend to check CMAKE_CONFIGURATION_TYPES to recognize a multi-configuration generator. I have found several questions where this did not work (for example this one). The issue seems to be that the variable is not set the first time cmake is called.

I tested with the following file

cmake_minimum_required(VERSION 2.6)

if(CMAKE_CONFIGURATION_TYPES)
    message("Multi-configuration generator")
else()
    message("Single-configuration generator")
endif()

project(foo)

and called it like this

mkdir build
cd build
cmake -G "Visual Studio 12 2013" ..

and got Single-configuration generator.

How should I distinguish whether the current generator supports multiple configurations?

回答1:

EDITED: Added information on checking and changing CMAKE_CONFIGURATION_TYPES

Check and Changing CMAKE_CONFIGURATION_TYPES

Taking the suggestions from this question you could check and change CMAKE_CONFIGURATION_TYPES, but be aware that there was a bug 0015577: The 'project' command overwrites CMAKE_CONFIGURATION_TYPES in CMake 3.2.2 that did break this behaviour for the initial VS solution generation (fixed with CMake 3.3.0):

cmake_minimum_required(VERSION 3.3)

project(foo NONE)

if(CMAKE_CONFIGURATION_TYPES)
    message("Multi-configuration generator")
    set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "My multi config types" FORCE)
else()
    message("Single-configuration generator")
endif()

enable_language(C CXX)

Preset CMAKE_CONFIGURATION_TYPES

If you just need a certain set of configurations for multi-configuration environments you can do (thanks to @Tsyvarev for the suggestion):

cmake_minimum_required(VERSION 2.8)

# NOTE: Only used in multi-configuration environments
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "My multi config types" FORCE)

project(foo)

None multi-configuration environments will just ignore it. But be aware that other CMake modules like findBoost.cmake, findCUDA.cmake may rely on CMAKE_CONFIGURATION_TYPES being empty for single-configuration environments (thanks again @Tsyvarev for the hint).

So a better solution would be adding toolchain files for all your supported generators. They are generally useful, because there you can handle all the toolchain/generator specific parts.

Here is an extract of my VSToolchain.txt:

# Reduce the config types to only Debug and Release
SET(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE)

# Standard is a console app. If you need a windows app, use WIN32 define in add_executable
set(CMAKE_WIN32_EXECUTABLE 0 CACHE INTERNAL "")

CMAKE_WIN32_EXECUTABLE is just there to show what kind of settings I have put in my Visual Studio toolchain file.

Another CMake command line solution is suggested here: How to create cmake build configuration without debug symbols and without optimizations?

Only Checking CMAKE_CONFIGURATION_TYPES

If you only want do check what CMake does set in CMAKE_CONFIGURATION_TYPES:

I just tested your above code with Visual Studio 2013 and MinGW/GCC (both with empty build directories). You just need one small change and move the check after the project() command:

project(foo)

message("CMAKE_CONFIGURATION_TYPES ${CMAKE_CONFIGURATION_TYPES}")

if(CMAKE_CONFIGURATION_TYPES)
    message("Multi-configuration generator")
else()
    message("Single-configuration generator")
endif()

And I get for VS2013:

CMAKE_CONFIGURATION_TYPES Debug;Release;MinSizeRel;RelWithDebInfo
Multi-configuration generator

And for GCC:

CMAKE_CONFIGURATION_TYPES
Single-configuration generator

For more details about what CMake does see:

  • CMAKE_CONFIGURATION_TYPES set by EnableLanguage() in cmGlobalVisualStudio7Generator.cxx
  • CMake: In which Order are Files parsed (Cache, Toolchain, …)?