CMake Variants

CMake Tools introduces the concept of CMake Variants, a way to group together and combine a common set of build options and give them a useful name. The main interface for creating and building variants is cmake-variants.json, or cmake-variants.yaml.

The idea of “variants” are separate from the concept of toolchains/toolsets, which are handled via Kits.

By default, if no variants file is present, CMake Tools will load four variants, each corresponding to a default CMake build type: Release, Debug, MinSizeRel, and RelWithDebInfo. Selecting one of these variants will configure and build with that build type.

Note

CMake Tools does not presently respect CMAKE_CONFIGURATION_TYPES. Only the default four will be present. A custom variant file is required to load these build types.

For smaller or simple projects, providing a custom cmake-variants.yaml is unnecessary, and the default CMake build types will work just fine. Large projects with more complex configuration options may want to specify additional build variants.

The variants file can be placed in the root of the project directory, or in the .vscode subdirectory for the project.

Note

CMake Tools provides a YAML validation schema, which is only checked in the editor when using the YAML Support by Red Hat extension.

You can use either cmake-variants.json or cmake-variants.yaml. Both will have the same end result.

The examples in this page will use the YAML format, but everything can be done in the JSON format as well.

What does it look like?

A simple two-setting cmake-variants.yaml might look like this:

_images/variants_yaml.png

This file defines two variant settings: buildType and useOpenGL. They each have two options defined by the choices key. A combination of the options from a set of settings forms a variant.

In total, the number of possible variants is defined by the cartesian product of the possible choices. Two settings each with two options creates four variants. When we ask to change the build type, CMake Tools will present each possible combination in a quickpick:

_images/custom_variant_selector.png

When a cmake-variants.json or cmake-variants.yaml file is present, the options defined therein will replace the default set of variants CMake Tools would otherwise present. This allows a project owner to define their own set of common build configurations that can be distributed downstream.

The Variant Schema

The root of the variants must be an object, where each key represents a tweakable variant option. In the example above, we expose a buildType option for what kind of CMAKE_BUILD_TYPE we want. We also expose a useOpenGL that controls the ENABLE_OPENGL CMake option.

Variant Settings

Each setting in the variant is an object with only the following keys:

default
A string to set as the default choice for the variant option. The string here must correspond to an option from choices.
description
An optional string to describe what the option controls. CMake Tools ignores this string.
choices
A mapping of possible options for the setting. A variant setting can have an arbitrary number of possible options. See the section below on options.

Variant Options

Variant options appear under the choices key for a variant setting. Each is required to have an unique name, but the name itself is unimportant to CMake Tools.

A choice may specify any of the following options (the only requirement is the short):

short
A short human-readable string to describe the option.
long (Optional)
A lengthier human-readable string to describe the option.
buildType (Optional)
An optional string to set for CMAKE_BUILD_TYPE when the option is active.
linkage (Optional)
Either static or shared. Sets the value of CMAKE_BUILD_SHARED_LIBS. This value is optional.
settings (Optional)
A map of arbitrary CMake cache options to pass via the CMake command line with -D. Similar to the cmake.configureSettings in settings.json.
env (Optional)
A map of key-value string pairs specifying additional environment variables to set during CMake configure (not build). These environment variables take precedence over environment variables from settings.json, the currently set kit, and environment variables set by the system.

The above options are only valid under entries in the choices map.

How Variants Are Applied

A variant is a specific combination of one option from each of the defined settings. When CMake Tools executes the configure step, it will use the values from the currently active variant to determine the values to pass to the CMake process:

  1. Properties from all active options are merged. For env and settings, the objects themselves are merged. The merge order is unspecified, so conflicting properties in options will result in unspecified behavior.
  2. All settings from the chosen options are passed as -D arguments to the CMake process.
  3. The buildType is used for CMAKE_BUILD_TYPE, the --config flag for the build (For multi-conf generators), and for the CTest --config flag.
  4. If linkage is true, BUILD_SHARED_LIBS is set to ON. If linkage is false, BUILD_SHARED_LIBS is set to OFF. If not specified, BUILD_SHARED_LIBS will not be set on the CMake command line.
  5. The environment variables from env are set for the CMake process.

A Big Example

Suppose the following variants file:

buildType:
  default: debug
  choices:
    debug:
      short: Debug
      long: Emit debug information
      buildType: Debug
    release:
      short: Release
      long: Optimize generated code
      buildType: Release
    asan:
      short: Asan
      long: Instrument with Address Sanitizer
      buildType: Asan
    tsan:
      short: Tsan
      long: Instrument with Thread Sanitizer
      buildType: Tsan

linkage:
  default: static
  choices:
    static:
      short: Static
      long: Create static libraries
      linkage: static
    shared:
      short: Shared
      long: Create shared libraries/DLLs
      linkage: shared

engine:
  default: ogl
  choices:
    ogl:
      short: OpenGL
      long: OpenGL rendering
      settings:
        ENGINE: OpenGL
    d3d:
      short: Direct3D
      long: Direct3D rendering
      settings:
        ENGINE: Direct3D
    vulkan:
      short: Vulkan
      long: Vulkan rendering
      setting:
        ENGINE: Vulkan
    software:
      short: Software
      long: Software rendering
      setting:
        ENGINE: Software

network:
  default: boost
  choices:
    boost:
      short: Boost.Asio
      long: Use Boost.Asio for networking
      setting:
        NETWORK: Boost
    asio:
      short: Asio
      long: Use standalone-Asio for networking
      setting:
        NETWORK: Asio
    net-ts:
      short: NetTS
      long: Use the C++ Networking TS for networking
      setting:
        NETWORK: net-ts

CMake Tools will present the cartesian product of all options, meaning the above will produce 4 × 2 × 4 × 3 = ninety-six different variants:

_images/many_variants.png

Of course this is quite a lot of possible variants, but such is the way with some complex software. CMake Tools will readily any helpfully show all combinations, and persist the selection between sessions.