11#[=============================================================================[
22Set a CACHE variable that depends on a set of conditions.
33
4- In CMake there are 3 main ways to create non-internal cache variables that can
5- be also customized using the `-D` command-line option, through CMake presets, or
6- similar:
4+ At the time of writing, there are 3 main ways in CMake to create non-internal
5+ cache variables that can be also customized from the outside using the `-D`
6+ command-line option, through CMake presets, or similar:
77* `option()`
88* `set(<variable> <value> CACHE <type> <docstring>)`
99* `cmake_dependent_option()`
@@ -22,64 +22,87 @@ This module exposes the following function:
2222```cmake
2323php_set(
2424 <variable>
25- <default>
26- CACHE <type>
27- [STRINGS <string>...]
28- [DOC <docstring>...]
29- IF <condition>
30- FORCED <forced>
25+ TYPE <type>
26+ [CHOICES <string>...]
27+ [IF <condition> VALUE <value> [ELSE_VALUE <default>]] | [VALUE <value>]
28+ DOC <docstring>...
3129)
3230```
3331
34- It sets the given CACHE `<variable>` of `<type>` to a `<value>` if `<condition>`
35- is met. Otherwise it sets the `<variable>` to `<default>` value and hides it in
36- the GUI.
32+ It sets a CACHE `<variable>` of `<type>` to a `<value>`.
3733
38- * The `CACHE` `<type> ` can be `BOOL`, `FILEPATH`, `PATH`, or `STRING`.
34+ * `TYPE ` can be `BOOL`, `FILEPATH`, `PATH`, or `STRING`.
3935
40- * `STRINGS` is an optional list of items when `CACHE` `STRING` is used to create
41- a list of supported options to pick in the GUI.
36+ * `CHOICES` is an optional list of items when `STRING` type is used to create
37+ a list of supported options to pick in the GUI. Under the hood, it sets the
38+ `STRINGS` CACHE variable property.
4239
43- * `DOC` is a short variable help text visible in the GUIs. Multiple strings are
44- joined together.
40+ * `VALUE` is the default variable value. There are two ways to set default
41+ value.
42+
43+ * When using the `IF <condition>` argument, it sets the variable to `<value>`
44+ if `<condition>` is met. Otherwise it sets the `<variable>` to `ELSE_VALUE`
45+ `<default>` and hides it in the GUI, if `ELSE_VALUE` is given. Under the
46+ hood `ELSE_VALUE` will set `INTERNAL` cache variable if `<condition>` is not
47+ met. If `ELSE_VALUE` is not provided, the `INTERNAL` cache variable is not
48+ set (it is undefined).
49+
50+ `IF` behaves the same as the `<depends>` argument in the
51+ `cmake_dependent_option()`. This supports both full condition sytanx and
52+ semicolon-separated list of conditions.
53+
54+ * When using only `VALUE` signature, it sets the cache variable to `<value>`.
55+ It is the same as writing:
4556
46- * `IF` behaves the same as the `<depends>` argument in
47- `cmake_dependent_option()`. If conditions `<condition>` are met, the variable
48- is set to `<default>` value. Otherwise, it is set to `<forced>` value and
49- hidden in the GUIs. This supports both full condition sytanx and
50- semicolon-separated list of conditions.
57+ ```cmake
58+ set(<variable> <value> CACHE <type> <docstring>)
59+ ```
5160
52- * `FORCED` is a value that is set when `IF <conditions>` are not met.
61+ * `DOC` is a short variable help text visible in the GUIs. Multiple strings are
62+ joined together.
5363#]=============================================================================]
5464
5565include_guard (GLOBAL )
5666
5767function (php_set)
68+ # https://cmake.org/cmake/help/latest/policy/CMP0174.html
69+ if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.31)
70+ set (valueNew "VALUE" )
71+ set (elseValueNew "ELSE_VALUE" )
72+ else ()
73+ set (valueOld "VALUE" )
74+ set (elseValueOld "ELSE_VALUE" )
75+ endif ()
76+
5877 cmake_parse_arguments (
5978 PARSE_ARGV
60- 2
61- parsed # prefix
62- "" # options
63- "CACHE;IF" # one-value keywords
64- "STRINGS; DOC;FORCED " # multi-value keywords
79+ 1
80+ parsed # prefix
81+ "" # options
82+ "${valueNew} ;TYPE;IF; ${elseValueNew} " # one-value keywords
83+ "${valueOld} ;CHOICES; DOC;${elseValueOld} " # multi-value keywords
6584 )
6685
6786 if (parsed_UNPARSED_ARGUMENTS)
6887 message (FATAL_ERROR "Bad arguments: ${parsed_UNPARSED_ARGUMENTS} " )
6988 endif ()
7089
71- if (NOT parsed_CACHE)
72- message (FATAL_ERROR "Missing CACHE type argument" )
73- elseif (NOT parsed_CACHE MATCHES "^(BOOL|FILEPATH|PATH|STRING)$" )
74- message (FATAL_ERROR "Unknown CACHE type argument: ${parsed_CACHE} " )
90+ if (NOT DEFINED parsed_VALUE)
91+ message (FATAL_ERROR "Missing VALUE argument" )
92+ endif ()
93+
94+ if (NOT parsed_TYPE)
95+ message (FATAL_ERROR "Missing TYPE argument" )
96+ elseif (NOT parsed_TYPE MATCHES "^(BOOL|FILEPATH|PATH|STRING)$" )
97+ message (FATAL_ERROR "Unknown TYPE argument: ${parsed_TYPE} " )
7598 endif ()
7699
77- if (NOT parsed_IF)
78- message (FATAL_ERROR "Missing IF argument with condition" )
100+ if (NOT DEFINED parsed_IF AND DEFINED parsed_ELSE_VALUE )
101+ message (FATAL_ERROR "Redundant ELSE_VALUE argument without IF condition" )
79102 endif ()
80103
81- if (NOT DEFINED parsed_FORCED )
82- message (FATAL_ERROR "Missing FORCED argument" )
104+ if (NOT DEFINED parsed_DOC )
105+ message (FATAL_ERROR "Missing DOC argument" )
83106 endif ()
84107
85108 set (doc "" )
@@ -88,35 +111,52 @@ function(php_set)
88111 endforeach ()
89112
90113 set (condition TRUE )
91- foreach (d ${parsed_IF} )
92- cmake_language(EVAL CODE "
93- if(${d} )
94- else()
95- set(condition FALSE)
96- endif()"
97- )
98- endforeach ()
114+ if (parsed_IF)
115+ foreach (d ${parsed_IF} )
116+ cmake_language(EVAL CODE "
117+ if(${d} )
118+ else()
119+ set(condition FALSE)
120+ endif()"
121+ )
122+ endforeach ()
123+ endif ()
99124
100125 set (var "${ARGV0} " )
101126 set (internal ___PHP_SET_${var} )
102127
103128 if (NOT DEFINED ${internal} AND DEFINED ${var} )
129+ # Initial configuration phase with variable set by the user.
104130 set (${internal} "${${var} }" CACHE INTERNAL "Internal storage for ${var} " )
105131 elseif (NOT DEFINED ${internal} )
106- set (${internal} "${ARGV1} " CACHE INTERNAL "Internal storage for ${var} " )
132+ # Initial configuration phase without variable set by the user.
133+ set (${internal} "${parsed_VALUE} " CACHE INTERNAL "Internal storage for ${var} " )
134+ elseif (
135+ DEFINED ${internal}
136+ AND ${internal} _FORCED
137+ AND NOT ${var} STREQUAL "${parsed_ELSE_VALUE} "
138+ )
139+ # Consecutive configuration phase that changes the variable after being
140+ # re-enabled.
141+ set (${internal} "${${var} }" CACHE INTERNAL "Internal storage for ${var} " )
107142 elseif (DEFINED ${internal} AND NOT ${internal} _FORCED)
143+ # Consecutive configuration phase.
108144 set (${internal} "${${var} }" CACHE INTERNAL "Internal storage for ${var} " )
109145 endif ()
110146
111147 if (condition )
112- set (${var} "${${internal} }" CACHE ${parsed_CACHE } "${doc} " FORCE)
113- if (parsed_CACHE STREQUAL "STRING" AND parsed_STRINGS )
114- set_property (CACHE ${var} PROPERTY STRINGS ${parsed_STRINGS } )
148+ set (${var} "${${internal} }" CACHE ${parsed_TYPE } "${doc} " FORCE)
149+ if (parsed_TYPE STREQUAL "STRING" AND parsed_CHOICES )
150+ set_property (CACHE ${var} PROPERTY STRINGS ${parsed_CHOICES } )
115151 endif ()
116152 unset (${internal} CACHE )
117153 unset (${internal} _FORCED CACHE )
118154 else ()
119- set (${var} "${parsed_FORCED} " CACHE INTERNAL "${doc} " )
155+ if (DEFINED parsed_ELSE_VALUE)
156+ set (${var} "${parsed_ELSE_VALUE} " CACHE INTERNAL "${doc} " )
157+ else ()
158+ unset (${var} CACHE )
159+ endif ()
120160 set (
121161 ${internal} _FORCED
122162 TRUE
0 commit comments