File: CMakeDependentOption.cmake

package info (click to toggle)
cmake 4.1.0-1
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 147,284 kB
  • sloc: ansic: 403,915; cpp: 290,772; sh: 4,102; python: 3,357; yacc: 3,106; lex: 1,189; f90: 532; asm: 471; lisp: 375; cs: 270; java: 266; fortran: 230; perl: 217; objc: 215; xml: 198; makefile: 97; javascript: 83; pascal: 63; tcl: 55; php: 25; ruby: 22
file content (250 lines) | stat: -rw-r--r-- 7,823 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
# file LICENSE.rst or https://cmake.org/licensing for details.

#[=======================================================================[.rst:
CMakeDependentOption
--------------------

This module provides a command to define boolean options whose availability and
default values depend on specified conditions or other options.  This helps
maintain a clean configuration interface by only displaying options that are
relevant to the current settings.

Load this module in a CMake project with:

.. code-block:: cmake

  include(CMakeDependentOption)

Commands
^^^^^^^^

This module provides the following command:

.. command:: cmake_dependent_option

  Provides a boolean option that depends on a set of conditions:

  .. code-block:: cmake

    cmake_dependent_option(<variable> <help> <value> <condition> <else-value>)

  This command creates a boolean ``<variable>`` and makes it available to the
  user in the GUI (such as :manual:`cmake-gui(1)` or :manual:`ccmake(1)`), if
  a set of conditions evaluates to boolean true.

  The arguments are:

  ``<variable>``
    The name of a variable that stores the option value.

  ``<help>``
    A brief description of the option.  This string is typically a short line of
    text and is displayed in the GUI.

  ``<value>``
    Boolean value for the ``<variable>``, when ``<condition>`` evaluates to
    boolean true.

  ``<condition>``
    Specifies the conditions that determine whether ``<variable>`` is set and
    visible in the GUI.

    * If ``<condition>`` evaluates to boolean false, option is hidden from the
      user in the GUI, and a local variable ``<variable>`` is set to
      ``<else-value>``.

    * If ``<condition>`` evaluates to boolean true, a boolean cache variable
      named ``<variable>`` is created with default ``<value>``, and option is
      shown in the GUI, allowing the user to enable or disable it.

    * If ``<condition>`` later evaluates to boolean false (on consecutive
      configuration run),  option is hidden from the user in the GUI and the
      ``<variable>`` type is changed to an internal cache variable.  In that
      case a local variable of the same name is set to ``<else-value>``.

    * If ``<condition>`` becomes true again in consecutive configuration runs,
      the user's previously set value is preserved.

    The ``<condition>`` argument can be:

    * A single condition (such as a variable name).

    * A :ref:`semicolon-separated list <CMake Language Lists>` of multiple
      conditions.

    * .. versionadded:: 3.22
        A full :ref:`Condition Syntax` as used in an ``if(<condition>)`` clause.
        See policy :policy:`CMP0127`.  This enables using entire condition
        syntax (such as grouping conditions with parens and similar).

  ``<else-value>``
    The value assigned to a local variable named ``<variable>``, when
    ``<condition>`` evaluates to boolean false.

Examples
^^^^^^^^

Example: Basic Usage
""""""""""""""""""""

Using this module in a project to conditionally set an option:

.. code-block:: cmake
  :caption: ``CMakeLists.txt``

  include(CMakeDependentOption)

  cmake_dependent_option(USE_SSL_GNUTLS "Use GnuTLS for SSL" ON USE_SSL OFF)

Example: Enabling/Disabling Dependent Option
""""""""""""""""""""""""""""""""""""""""""""

Extending the previous example, this demonstrates how the module allows
user-configurable options based on a condition during the configuration phase:

.. code-block:: cmake
  :caption: ``CMakeLists.txt``

  include(CMakeDependentOption)

  option(USE_SSL "Enable SSL in the project" OFF)

  cmake_dependent_option(USE_SSL_GNUTLS "Use GnuTLS for SSL" ON USE_SSL OFF)

  message(STATUS "USE_SSL: ${USE_SSL}")
  message(STATUS "USE_SSL_GNUTLS: ${USE_SSL_GNUTLS}")

On the first configuration run, a boolean cache variable ``USE_SSL`` is set to
OFF, and a local variable ``USE_SSL_GNUTLS`` is set to OFF:

.. code-block:: console

  $ cmake -B build-dir

  -- USE_SSL: OFF
  -- USE_SSL_GNUTLS: OFF

Running CMake with ``USE_SSL=ON`` sets both ``USE_SSL`` and ``USE_SSL_GNUTLS``
boolean cache variables to ON:

.. code-block:: console

  $ cmake -B build-dir -D USE_SSL=ON

  -- USE_SSL: ON
  -- USE_SSL_GNUTLS: ON

On a subsequent configuration run with ``USE_SSL=OFF``, ``USE_SSL_GNUTLS``
follows suit.  However, its value is preserved in the internal cache while being
overridden locally:

.. code-block:: console

  $ cmake -B build-dir -D USE_SSL=OFF

  -- USE_SSL: OFF
  -- USE_SSL_GNUTLS: OFF

Example: Semicolon-separated List of Conditions
"""""""""""""""""""""""""""""""""""""""""""""""

The ``<condition>`` argument can also be a semicolon-separated list of
conditions.  In the following example, if the variable ``USE_BAR`` is ON and
variable ``USE_ZOT`` is OFF, the option ``USE_FOO`` is available and defaults to
ON.  Otherwise, ``USE_FOO`` is set to OFF and hidden from the user.

If the values of ``USE_BAR`` or ``USE_ZOT`` change in the future configuration
runs, the previous value of ``USE_FOO`` is preserved so that when it becomes
available again, it retains its last set value.

.. code-block:: cmake
  :caption: ``CMakeLists.txt``

  include(CMakeDependentOption)

  cmake_dependent_option(USE_FOO "Use Foo" ON "USE_BAR;NOT USE_ZOT" OFF)

Example: Full Condition Syntax
""""""""""""""""""""""""""""""

As of CMake 3.22, ``cmake_dependent_option()`` supports full condition syntax.

In fhe following example, if the condition evaluates to true, the option
``USE_FOO`` is available and set to ON.  Otherwise, it is set to OFF and hidden
in the GUI.  The value of ``USE_FOO`` is preserved across configuration runs,
similar to the previous example.

.. code-block:: cmake
  :caption: ``CMakeLists.txt``

  include(CMakeDependentOption)

  cmake_dependent_option(USE_FOO "Use Foo" ON "USE_A AND (USE_B OR USE_C)" OFF)

Another example demonstrates how an option can be conditionally available based
on the target system:

.. code-block:: cmake
  :caption: ``CMakeLists.txt``

  include(CMakeDependentOption)

  cmake_dependent_option(
    ENABLE_FOO
    "Enable feature Foo (this option is available when building for Windows)"
    ON
    [[CMAKE_SYSTEM_NAME STREQUAL "Windows"]]
    OFF
  )

See Also
^^^^^^^^

* The :command:`option` command to provide a boolean option that the user can
  optionally select.
#]=======================================================================]

macro(CMAKE_DEPENDENT_OPTION option doc default depends force)
  cmake_policy(GET CMP0127 _CDO_CMP0127
    PARENT_SCOPE # undocumented, do not use outside of CMake
    )
  if(${option}_ISSET MATCHES "^${option}_ISSET$")
    set(${option}_AVAILABLE 1)
    if("x${_CDO_CMP0127}x" STREQUAL "xNEWx")
      foreach(d ${depends})
        cmake_language(EVAL CODE "
          if (${d})
          else()
            set(${option}_AVAILABLE 0)
          endif()"
        )
      endforeach()
    else()
      foreach(d ${depends})
        string(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${d}")
        if(${CMAKE_DEPENDENT_OPTION_DEP})
        else()
          set(${option}_AVAILABLE 0)
        endif()
      endforeach()
    endif()
    if(${option}_AVAILABLE)
      option(${option} "${doc}" "${default}")
      set(${option} "${${option}}" CACHE BOOL "${doc}" FORCE)
    else()
      if(${option} MATCHES "^${option}$")
      else()
        set(${option} "${${option}}" CACHE INTERNAL "${doc}")
      endif()
      set(${option} ${force})
    endif()
  else()
    set(${option} "${${option}_ISSET}")
  endif()
  if("x${_CDO_CMP0127}x" STREQUAL "xx" AND "x${depends}x" MATCHES "[^A-Za-z0-9_.; ]")
    cmake_policy(GET_WARNING CMP0127 _CDO_CMP0127_WARNING)
    message(AUTHOR_WARNING "${_CDO_CMP0127_WARNING}")
  endif()
  unset(_CDO_CMP0127)
endmacro()