@@ -31,9 +31,10 @@ php_set(
3131 <variable>
3232 TYPE <type>
3333 [CHOICES <string>...]
34+ [CHOICES_OPTIONAL]
35+ [CHOICES_CASE_SENSITIVE]
3436 [IF <condition> VALUE <value> [ELSE_VALUE <default>]] | [VALUE <value>]
3537 DOC <docstring>...
36- [WARNING <warning>]
3738)
3839```
3940
@@ -45,6 +46,52 @@ It sets a CACHE `<variable>` of `<type>` to a `<value>`.
4546 a list of supported options to pick in the GUI. Under the hood, it sets the
4647 `STRINGS` CACHE variable property.
4748
49+ * When `CHOICES_OPTIONAL` is used, variable value will not be validated to
50+ match one of the list items. By default when using `CHOICES` variable value
51+ must match one of the list items otherwise a fatal error is thrown.
52+
53+ * When `CHOICES_CASE_SENSITIVE` is used, variable value passed by the user
54+ will need to be of the same case as defined in the `CHOICES` list. By
55+ default, choices are case insensitive.
56+
57+ For example:
58+
59+ ```cmake
60+ php_set(
61+ VAR
62+ TYPE STRING
63+ CHOICES auto unixODBC iODBC
64+ IF TRUE
65+ VALUE auto
66+ DOC "Variable with a case insensitive list of choices"
67+ )
68+ message(STATUS "VAR=${VAR}")
69+ ```
70+
71+ ```sh
72+ cmake -S <source-dir> -B <build-dir> -DVAR=unixodbc
73+ ```
74+
75+ Will output `VAR=unixODBC` and not `VAR=unixodbc`.
76+
77+ With `CHOICES_CASE_SENSITIVE`:
78+
79+ ```cmake
80+ php_set(
81+ VAR
82+ TYPE STRING
83+ CHOICES auto unixODBC iODBC
84+ CHOICES_CASE_SENSITIVE
85+ IF TRUE
86+ VALUE auto
87+ DOC "Variable with a case sensitive list of choices"
88+ )
89+ message(STATUS "VAR=${VAR}")
90+ ```
91+
92+ A fatal error will be thrown, if VAR is set to a case-sensitive value
93+ `unixodbc`, which is not defined in the `CHOICES` list.
94+
4895* `VALUE` is the default variable value. There are two ways to set default
4996 value.
5097
@@ -68,10 +115,6 @@ It sets a CACHE `<variable>` of `<type>` to a `<value>`.
68115
69116* `DOC` is a short variable help text visible in the GUIs. Multiple strings are
70117 joined together.
71-
72- * `WARNING` is optional text that is emitted when setting a variable from the
73- command line or CMake presets but its condition is not met. Otherwise, a
74- default warning is emitted.
75118#]=============================================================================]
76119
77120include_guard (GLOBAL )
@@ -80,10 +123,10 @@ function(php_set)
80123 cmake_parse_arguments (
81124 PARSE_ARGV
82125 1
83- parsed # prefix
84- "" # options
126+ parsed # prefix
127+ "CHOICES_OPTIONAL;CHOICES_CASE_SENSITIVE" # options
85128 "TYPE;IF;VALUE;ELSE_VALUE" # one-value keywords
86- "CHOICES;DOC;WARNING" # multi-value keywords
129+ "CHOICES;DOC" # multi-value keywords
87130 )
88131
89132 # The cmake_parse_arguments() before 3.31 didn't define one-value keywords
@@ -155,11 +198,17 @@ function(php_set)
155198 set (${varName} "${${bufferVarName} }" CACHE ${parsed_TYPE} "${doc} " FORCE)
156199 if (parsed_TYPE STREQUAL "STRING" AND parsed_CHOICES)
157200 set_property (CACHE ${varName} PROPERTY STRINGS ${parsed_CHOICES} )
201+ if (NOT parsed_CHOICES_CASE_SENSITIVE)
202+ _php_set_fix_value(${varName} )
203+ endif ()
204+ if (NOT parsed_CHOICES_OPTIONAL)
205+ _php_set_validate_choices(${varName} ${parsed_CHOICES_CASE_SENSITIVE} )
206+ endif ()
158207 endif ()
159208 unset (${bufferVarName} CACHE )
160209 unset (${bufferVarName} _OVERRIDDEN CACHE )
161210 else ()
162- _php_set_validate_input()
211+ _php_set_validate_input(${varName} )
163212
164213 if (DEFINED parsed_ELSE_VALUE)
165214 set (${varName} "${parsed_ELSE_VALUE} " CACHE INTERNAL "${doc} " FORCE)
@@ -207,41 +256,78 @@ function(_php_set_validate_arguments arguments)
207256 endif ()
208257endfunction ()
209258
210- # Output warning when setting conditional variable and condition is not met.
211- function (_php_set_validate_input)
212- get_property (helpString CACHE ${varName} PROPERTY HELPSTRING )
259+ # Validate variable and output warning when a conditional variable is set by the
260+ # user (on command line or CMake presets) and the condition is not met.
261+ # This is for diagnostics purpose for user to be aware that some configuration
262+ # value was not taken into account.
263+ function (_php_set_validate_input var)
264+ get_property (helpString CACHE ${var} PROPERTY HELPSTRING )
213265 if (NOT helpString STREQUAL "No help, variable specified on the command line." )
214266 return ()
215267 endif ()
216268
217- if (NOT parsed_WARNING)
218- set (parsed_WARNING "Variable ${varName} " )
219- if (DEFINED parsed_ELSE_VALUE)
220- string (
221- APPEND
222- parsed_WARNING
223- " has been overridden (${varName} =${parsed_ELSE_VALUE} )"
224- )
225- else ()
226- string (
227- APPEND
228- parsed_WARNING
229- " has been overridden to an undefined state"
230- )
231- endif ()
232- string (
233- APPEND
234- parsed_WARNING
235- " as it depends on the condition:\n "
236- "${parsed_IF} \n "
237- )
269+ if (${var} STREQUAL "${parsed_ELSE_VALUE} " )
270+ return ()
238271 endif ()
239- set (warning "" )
240- foreach (string ${parsed_WARNING} )
241- string (APPEND warning "${string} " )
272+
273+ set (warning "Variable ${var} " )
274+ if (DEFINED parsed_ELSE_VALUE)
275+ string (APPEND warning " has been overridden (${var} =${parsed_ELSE_VALUE} )" )
276+ else ()
277+ string (APPEND warning " has been undefined" )
278+ endif ()
279+ string (
280+ APPEND
281+ warning
282+ " as it depends on the condition:\n "
283+ "${parsed_IF} \n "
284+ "You can probably remove the ${var} configuration value from the build "
285+ "command as it won't be utilized."
286+ )
287+
288+ message (WARNING "${warning} " )
289+ endfunction ()
290+
291+ # Reset the value passed by the user according to the case sensitivity given in
292+ # the choices list.
293+ function (_php_set_fix_value var)
294+ get_property (value CACHE ${var} PROPERTY VALUE )
295+ get_property (choices CACHE ${var} PROPERTY STRINGS )
296+
297+ string (TOLOWER "${value} " valueLower)
298+ list (TRANSFORM choices TOLOWER OUTPUT_VARIABLE choicesLower)
299+
300+ set (index 0)
301+ foreach (item IN LISTS choicesLower)
302+ if (valueLower STREQUAL "${item} " )
303+ list (GET choices ${index} itemOriginal)
304+ if (NOT value STREQUAL "${itemOriginal} " )
305+ set_property (CACHE ${var} PROPERTY VALUE ${itemOriginal} )
306+ break ()
307+ endif ()
308+ endif ()
309+ math (EXPR index "${index} +1" )
242310 endforeach ()
311+ endfunction ()
312+
313+ # When CHOICES argument is set, validate variable value to match one of the
314+ # choices.
315+ function (_php_set_validate_choices var caseSensitive)
316+ get_property (value CACHE ${var} PROPERTY VALUE )
317+ get_property (choices CACHE ${var} PROPERTY STRINGS )
243318
244- if (NOT ${varName} STREQUAL "${parsed_ELSE_VALUE} " )
245- message (WARNING "${warning} " )
319+ if (NOT caseSensitive)
320+ string (TOLOWER "${value} " value )
321+ list (TRANSFORM choices TOLOWER)
322+ endif ()
323+
324+ if (NOT value IN_LIST choices)
325+ list (JOIN choices ", " choices)
326+
327+ message (
328+ FATAL_ERROR
329+ "Unknown value: ${var} =${value} \n "
330+ "Please select one of: ${choices} ."
331+ )
246332 endif ()
247333endfunction ()
0 commit comments