Options are CMake CACHE
variables which parameterize a project,
augmented for :ref:`presentation to users <options-summary>` and
:ref:`consistency checking <option-resolution>`.
If an aspect of your project might need to be tuned by users, an
option declaration is probably the most accessible way to expose it.
option(
name < | BOOL | PATH | FILEPATH | STRING | ENUM enum_values... >
help_string
[DEFAULT default_value]
[MARK_AS_ADVANCED]
[REQUIRES [IF condition [dependency required_value]...]...]
[VALIDATE CODE validation_code]
[ADD_COMPILE_DEFINITIONS]
)
Declare an option with the provided name
.
< | BOOL | PATH | FILEPATH | STRING | ENUM enum_values... >
The :cmake:`type <prop_cache/TYPE.html>` of the
CACHE
variable. Options which are not explicitly typed are implicitly of typeBOOL
.ENUM
is an alias forSTRING
which additionally specifies allowed values by setting the :cmake:`STRINGS property <prop_cache/STRINGS.html>`.Every value (default, required values, ...) associated with options of
PATH
orFILEPATH
type are converted to :cmake:`normalized, native paths <command/cmake_path.html#native-path>`. Additionally, if such a value is a relative path then it is assumed to be relative toCMAKE_SOURCE_DIR
and will be converted to an :cmake:`absolute path <command/cmake_path.html#absolute-path>`.BOOL
options are always validated to be eitherON
orOFF
.ENUM
options are always checked against their value set. Additional validation can be specified using :ref:`VALIDATE CODE <option-custom-validation>`.help_string
The :cmake:`help string <prop_cache/HELPSTRING.html>` of the
CACHE
variable.An explanation of the option's purpose, displayed in
ccmake
and other GUIs. :ref:`Predefined macros <option-compile-definitions>` for the option will be decorated with a doxygen-style comment containing this text (which should be accessible to your language server). It will also be displayed in the :ref:`summary <options-summary>` when configuration completes.Note
An escaped representation of the help string is stored, which will be shown directly in
ccmake
and other viewers which only support single line help strings.DEFAULT default_value
The option's value if no explicit value is provided and no requirements constrain it.
Note
In fresh builds, environment variables can be used to assign to options. For example if an option named
FOO_LEVEL
is not otherwise defined butENV{FOO_LEVEL}
is defined, then the environment variable will be used instead of the default. (This can be disabled by settingENV{MAUD_DISABLE_ENVIRONMENT_OPTIONS} = ON
.)Note
CACHE
variables' values may be defined before their declaration as an option (for example if the option is defined on the command line via-DFOO_LEVEL=HI
) in which case the declaration will initialize other properties, leaving the value unchanged.Implicit defaults BOOL
OFF
PATH
orFILEPATH
${CMAKE_SOURCE_DIR}
STRING
""
ENUM
the first enum value MARK_AS_ADVANCED
- Mark this
CACHE
variable :cmake:`advanced <prop_cache/ADVANCED.html>`. Its value will not be displayed by default in the :ref:`summary <options-summary>` (it will be displayed if its value is non-default) and GUIs (ccmake
for example provides an explicit toggle).
REQUIRES
Begin a set of :ref:`requirement <option-resolution>` blocks. Each block begins with
IF condition
wherecondition
is a possible value of the option. The block continues with a sequence ofdependency required_value
pairs where eachdependency
names another option. If the option's value is resolved tocondition
, then eachdependency
in its block will be set to the correspondingrequired_value
.Note
A
dependency
need not be declared withoption()
before it is referenced in a requirement block.Note
To simplify the common case of a
BOOL
option which only has requirements when it isON
,REQUIRES IF ON
may be shortened to justREQUIRES
.
VALIDATE CODE validation_code
- Provide code to validate the option. The code block will be evaluated after
requirements have been resolved and the option's final value is known. For
example this could be used to assert that a
FILEPATH
option specifies a readable file.
ADD_COMPILE_DEFINITIONS
If specified, macros will be added to the predefines buffer to expose option values to C++ code.
For a boolean option an identically named macro will be defined to 0 or 1 // FOO_EMULATED: BOOL #define FOO_EMULATED 0
The name of an enumeration option will be concatenated with each potential value to get macro names, each of which are defined to 0 or 1 // FOO_LEVEL: ENUM LOW MED HI #define FOO_LEVEL_LOW 0 #define FOO_LEVEL_MED 0 #define FOO_LEVEL_HI 1
For options of any other type an identically named macro will be defined to a string literal // FOO_SOCKET_PATH: FILEPATH #define FOO_SOCKET_PATH "/var/run/foo"
After configuration is complete, a summary of option values is printed. The resolved value of each option is printed, along with the reason for that value and the option's help string.
Groups of associated options can be declared by writing
set(OPTION_GROUP "FOO-related options")
before declaring the options.
This adds a heading in the summary.
-- FOO-related options:
--
-- FOO_EMULATED = OFF [constrained by FOO_LEVEL]
-- Emulate FOO functionality rather than requesting a real FOO endpoint.
-- FOO_LEVEL = HI (of LOW;MED;HI) [user configured]
-- What level of FOO API should be requested.
-- LOW is primarily used for testing and is not otherwise recommended.
-- FOO_SOCKET_PATH = /var/run/foo [default]
-- Explicit socket for FOO endpoint.
As part of the options summary, a cmake
:cmake:`configure preset <manual/cmake-presets.7.html#configure-preset>`
is appended to CMakeUserPresets.json
for easy copy-pasting, reproduction, etc.
Project options are frequently interdependent; for example enabling one feature might be impossible without enabling its dependencies. Manually resolving these interdependencies to a consistent state across all options in the project is frequently messy and error prone. :ref:`option() <option-function>` integrates a solution to this problem in the :ref:`REQUIRES <requirement-block-syntax>` argument. The requirements of each option can be specified in terms of assignments to other options on which it depends.
option(
FOO_LEVEL ENUM LOW MED HI
REQUIRES # requirements of FOO_LEVEL follow
IF HI # if FOO_LEVEL is HI ...
FOO_EMULATED OFF # ... FOO_EMULATED must be set to OFF
)
The first time an option is accessed, its value and the values of its dependencies are resolved. This ensures all requirements are met (or reports an error if unsatisfiable requirements are encountered).
.. tab:: ✅ Valid .. code-block:: cmake option(alpha BOOL DEFAULT ON REQUIRES beta 3) option(beta ENUM 1 2 3) # beta accessed; triggers resolution of alpha # no requirements on alpha; alpha resolved to ON # alpha=ON requires beta=3; beta resolved to 3 if(beta EQUAL 1) # ... endif()
.. tab:: ❌ Conflict .. code-block:: cmake option(alpha BOOL DEFAULT ON REQUIRES beta 3) option(beta ENUM 1 2 3) option(omega BOOL DEFAULT ON REQUIRES beta 1) # beta accessed; triggers resolution of alpha and omega # no requirements on alpha or omega; both are resolved to ON # CMake Error at /tmp/usr/lib/cmake/Maud/Maud.cmake:1455 (message): # # Option constraint conflict: beta is constrained # by alpha to be # "3" # but omega requires it to be # "1" if(beta EQUAL 1) # ... endif()
Warning
Since option resolution is implemented using
:cmake:`variable_watch <command/variable_watch.html>`, accessing an option's
value through $CACHE{FOO}
or get_property(... CACHE FOO PROPERTY VALUE)
will circumvent resolution.
Options are considered to form a directed acyclic graph: each option may declare a requirement on any other option as long as no cycles are formed. Options with no requirements placed on them will have their default or user configured value. Otherwise requirements determine the option's value (even if the dependency's default is required).
.. tab:: ✅ Valid .. code-block:: cmake option(foo0 BOOL DEFAULT ON REQUIRES foo1 ON) option(foo1 BOOL DEFAULT ON REQUIRES foo2 ON) option(foo2 BOOL DEFAULT ON REQUIRES foo3 ON) option(foo3 BOOL DEFAULT ON) # foo3 accessed; triggers resolution of foo2 # ... triggers resolution of foo1 # ... triggers resolution of foo0 # no requirements on foo0; foo0 resolved to ON # foo0=ON requires foo1=ON; foo1 resolved to ON # foo1=ON requires foo2=ON; foo2 resolved to ON # foo2=ON requires foo3=ON; foo3 resolved to ON if(foo3) # ... endif()
.. tab:: ❌ Cyclic dependency .. code-block:: cmake option(foo0 BOOL DEFAULT ON REQUIRES foo1 ON) option(foo1 BOOL DEFAULT ON REQUIRES foo2 ON) option(foo2 BOOL DEFAULT ON REQUIRES foo3 ON) option(foo3 BOOL DEFAULT ON REQUIRES foo0 ON) # foo3 accessed; triggers resolution of foo2 # ... triggers resolution of foo1 # ... triggers resolution of foo0 # ... re-enters resolution of foo3 # CMake Error at /tmp/usr/lib/cmake/Maud/Maud.cmake:1436 (message): # # Circular constraint between options # foo3;foo2;foo1;foo0 if(foo3) # ... endif()
Note
User provided values (via -DFOO=0
on the command line, through preset
JSON, from an environment variable, ...) are not considered a hard constraint
and will always be overridden if necessary to satisfy declared requirements.
On a fresh configuration it is possible to detect such an override and a
warning will be issued to facilitate avoidance of inconsistent user provided
values.
Conflicting requirements will result in a FATAL_ERROR
. Likewise if a
requirement is placed on an option which has been accessed, that requirement can
only check for consistency with the option's already resolved value. Whenever
possible I recommend grouping declarations of interdependent options, which
makes it easier to avoid this error.
.. tab:: ✅ Valid .. code-block:: cmake option(alpha BOOL DEFAULT ON REQUIRES beta 3) option(beta ENUM 1 2 3) # beta accessed; triggers resolution of alpha # no requirements on alpha; alpha resolved to ON # alpha=ON requires beta=3; beta resolved to 3 if(beta EQUAL 1) # ... endif()
.. tab:: ❌ Constraining resolved .. code-block:: cmake # alpha is declared later option(beta ENUM 1 2 3) # beta accessed; no requirements on beta; beta resolved to 1 if(beta EQUAL 1) setup_beta_feature(1) endif() # beta's value is already resolved by the access above option(alpha BOOL DEFAULT ON REQUIRES beta 3) # CMake Error at /tmp/usr/lib/cmake/Maud/Maud.cmake:1468 (message): # # Option constraint conflict: beta was already resolved to # "1" # but alpha requires it to be # "3"