Flogo
Flogo

Reputation: 1878

How to check if generator is a multi-config generator in a CMakeLists.txt

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?

Upvotes: 11

Views: 6901

Answers (2)

starball
starball

Reputation: 52175

I see you are on CMake v2.6, but for anyone who is on v3.9+, v3.9 introduced the global property called GENERATOR_IS_MULTI_CONFIG:

Read-only property that is true on multi-configuration generators.

You can load the value into a CMake variable like so:

get_property(is_multi_config GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)

This very approach is recommended in "Professional CMake" by Craig Scott, along with explanations of the shortcomings of other approaches- especially those involving CMAKE_CONFIGURATION_TYPES. The book is $30 but the section I'm referring to is in the sample chapters.

Upvotes: 7

Florian
Florian

Reputation: 43048

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:

Upvotes: 6

Related Questions