diff options
17 files changed, 143 insertions, 21 deletions
diff --git a/Help/manual/cmake-policies.7.rst b/Help/manual/cmake-policies.7.rst index b9e3d45..0f0c0ab 100644 --- a/Help/manual/cmake-policies.7.rst +++ b/Help/manual/cmake-policies.7.rst @@ -51,6 +51,14 @@ The :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` variable may also be used to determine whether to report an error on use of deprecated macros or functions. +Policies Introduced by CMake 3.22 +================================= + +.. toctree:: + :maxdepth: 1 + + CMP0127: cmake_dependent_option() supports full Condition Syntax. </policy/CMP0127> + Policies Introduced by CMake 3.21 ================================= diff --git a/Help/policy/CMP0127.rst b/Help/policy/CMP0127.rst new file mode 100644 index 0000000..8560bbf --- /dev/null +++ b/Help/policy/CMP0127.rst @@ -0,0 +1,32 @@ +CMP0127 +------- + +:command:`cmake_dependent_option` supports full :ref:`Condition Syntax`. + +The ``<depends>`` parameter accepts a :ref:`semicolon-separated list <CMake +Language Lists>` of conditions. CMake 3.21 and lower evaluates each +``condition`` as ``if(${condition})``, which does not properly handle +conditions with nested paren groups. CMake 3.22 and above instead prefer +to evaluate each ``condition`` as ``if(<condition>)``, where ``<condition>`` +is re-parsed as if literally written in a call to :command:`if`. This +allows expressions like:: + + "A AND (B OR C)" + +but requires expressions like:: + + "FOO MATCHES (UPPER|lower)" + +to be re-written as:: + + "FOO MATCHES \"(UPPER|lower)\"" + +Policy ``CMP0127`` provides compatibility for projects that have not +been updated to expect the new behavior. + +This policy was introduced in CMake version 3.22. CMake version +|release| warns when the policy is not set and uses ``OLD`` behavior. +Use the :command:`cmake_policy` command to set it to ``OLD`` or ``NEW`` +explicitly. + +.. include:: DEPRECATED.txt diff --git a/Help/release/dev/cmake_dependent_option_policy.rst b/Help/release/dev/cmake_dependent_option_policy.rst new file mode 100644 index 0000000..c131170 --- /dev/null +++ b/Help/release/dev/cmake_dependent_option_policy.rst @@ -0,0 +1,6 @@ +cmake_dependent_option_policy +----------------------------- + +* The :module:`CMakeDependentOption` module :command:`cmake_dependent_option` + macro now supports full :ref:`Condition Syntax`. + See policy :policy:`CMP0127`. diff --git a/Modules/CMakeDependentOption.cmake b/Modules/CMakeDependentOption.cmake index 96855d2..b7c478f 100644 --- a/Modules/CMakeDependentOption.cmake +++ b/Modules/CMakeDependentOption.cmake @@ -10,44 +10,62 @@ Macro to provide an option dependent on other options. This macro presents an option to the user only if a set of other conditions are true. -Usage: +.. command:: cmake_dependent_option -.. code-block:: cmake + .. code-block:: cmake - cmake_dependent_option(<option> "<help_text>" <value> <depends> <force>) + cmake_dependent_option(<option> "<help_text>" <value> <depends> <force>) -Where ``<option>`` is available to the user if ``<depends>`` is true. When -``<option>`` is available, the given ``<help_text>`` and initial ``<value>`` -are used. If the ``<depends>`` condition is not true, ``<option>`` will not be -presented and will always have the value given by ``<force>``. Any value set by -the user is preserved for when the option is presented again. Each element in -the fourth parameter is evaluated as an if-condition, so -:ref:`Condition Syntax` can be used. + Makes ``<option>`` available to the user if ``<depends>`` is true. When + ``<option>`` is available, the given ``<help_text>`` and initial ``<value>`` + are used. If the ``<depends>`` condition is not true, ``<option>`` will not be + presented and will always have the value given by ``<force>``. Any value set by + the user is preserved for when the option is presented again. In case ``<depends>`` + is a :ref:`semicolon-separated list <CMake Language Lists>`, all elements must + be true in order to initialize ``<option>`` with ``<value>``. Example invocation: .. code-block:: cmake - cmake_dependent_option(USE_FOO "Use Foo" ON - "USE_BAR;NOT USE_ZOT" OFF) + cmake_dependent_option(USE_FOO "Use Foo" ON "USE_BAR;NOT USE_ZOT" OFF) If ``USE_BAR`` is true and ``USE_ZOT`` is false, this provides an option called ``USE_FOO`` that defaults to ON. Otherwise, it sets ``USE_FOO`` to OFF and hides the option from the user. If the status of ``USE_BAR`` or ``USE_ZOT`` ever changes, any value for the ``USE_FOO`` option is saved so that when the option is re-enabled it retains its old value. + +.. versionadded:: 3.22 + + Full :ref:`Condition Syntax` is now supported. See policy :policy:`CMP0127`. + #]=======================================================================] 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) - foreach(d ${depends}) - string(REGEX REPLACE " +" ";" CMAKE_DEPENDENT_OPTION_DEP "${d}") - if(${CMAKE_DEPENDENT_OPTION_DEP}) - else() - set(${option}_AVAILABLE 0) - endif() - endforeach() + 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) @@ -61,4 +79,9 @@ macro(CMAKE_DEPENDENT_OPTION option doc default depends force) 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() diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index f7c0d25..a98e6c6 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -379,7 +379,10 @@ class cmMakefile; 3, 21, 0, cmPolicies::WARN) \ SELECT(POLICY, CMP0126, \ "set(CACHE) does not remove a normal variable of the same name.", 3, \ - 21, 0, cmPolicies::WARN) + 21, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0127, \ + "cmake_dependent_option() supports full Condition Syntax.", 3, 22, \ + 0, cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW-stdout.txt index 15b56a1..15b56a1 100644 --- a/Tests/RunCMake/CMakeDependentOption/Regex-stdout.txt +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW-stdout.txt diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW.cmake b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW.cmake new file mode 100644 index 0000000..5a2b018 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-NEW.cmake @@ -0,0 +1,9 @@ +include(CMakeDependentOption) + +cmake_policy(SET CMP0127 NEW) + +set(A 1) +set(B 1) +set(C 0) +cmake_dependent_option(USE_FOO "Use Foo" ON "A AND (B OR C)" OFF) +message(STATUS "USE_FOO='${USE_FOO}'") diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stderr.txt b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stderr.txt new file mode 100644 index 0000000..b16e84b --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stderr.txt @@ -0,0 +1,9 @@ +^CMake Warning \(dev\) at [^ +]*/Modules/CMakeDependentOption.cmake:[0-9]+ \(message\): + Policy CMP0127 is not set: cmake_dependent_option\(\) supports full Condition + Syntax. Run "cmake --help-policy CMP0127" for policy details. Use the + cmake_policy command to set the policy and suppress this warning. +Call Stack \(most recent call first\): + [^ +]*/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake:[0-9]+ \(cmake_dependent_option\) +This warning is for project developers. Use -Wno-dev to suppress it.$ diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stdout.txt new file mode 100644 index 0000000..d89dbd3 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN-stdout.txt @@ -0,0 +1,2 @@ +-- USE_FOO='OFF' +-- USE_BAR='ON' diff --git a/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake new file mode 100644 index 0000000..00d440d --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Parentheses-CMP0127-WARN.cmake @@ -0,0 +1,9 @@ +include(CMakeDependentOption) + +set(A 1) +set(B 1) +set(C 0) +cmake_dependent_option(USE_FOO "Use Foo" ON "A AND (B OR C)" OFF) +message(STATUS "USE_FOO='${USE_FOO}'") +cmake_dependent_option(USE_BAR "Use Bar" ON "A;B" OFF) +message(STATUS "USE_BAR='${USE_BAR}'") diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW-stdout.txt new file mode 100644 index 0000000..15b56a1 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW-stdout.txt @@ -0,0 +1 @@ +-- USE_FOO='ON' diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW.cmake b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW.cmake new file mode 100644 index 0000000..e92c1e6 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-NEW.cmake @@ -0,0 +1,7 @@ +include(CMakeDependentOption) + +cmake_policy(SET CMP0127 NEW) + +set(FOO "lower") +cmake_dependent_option(USE_FOO "Use Foo" ON "FOO MATCHES \"(UPPER|lower)\"" OFF) +message(STATUS "USE_FOO='${USE_FOO}'") diff --git a/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD-stdout.txt new file mode 100644 index 0000000..15b56a1 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD-stdout.txt @@ -0,0 +1 @@ +-- USE_FOO='ON' diff --git a/Tests/RunCMake/CMakeDependentOption/Regex.cmake b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD.cmake index 8342a01..81df003 100644 --- a/Tests/RunCMake/CMakeDependentOption/Regex.cmake +++ b/Tests/RunCMake/CMakeDependentOption/Regex-CMP0127-OLD.cmake @@ -1,5 +1,7 @@ include(CMakeDependentOption) +cmake_policy(SET CMP0127 OLD) + set(FOO "lower") cmake_dependent_option(USE_FOO "Use Foo" ON "FOO MATCHES (UPPER|lower)" OFF) message(STATUS "USE_FOO='${USE_FOO}'") diff --git a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake index e1045f2..61e046f 100644 --- a/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake +++ b/Tests/RunCMake/CMakeDependentOption/RunCMakeTest.cmake @@ -1,3 +1,6 @@ include(RunCMake) -run_cmake_script(Regex) +run_cmake_script(Regex-CMP0127-NEW) +run_cmake_script(Regex-CMP0127-OLD) +run_cmake_script(Parentheses-CMP0127-NEW) +run_cmake_script(Parentheses-CMP0127-WARN) diff --git a/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD-stdout.txt b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD-stdout.txt new file mode 100644 index 0000000..15b56a1 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD-stdout.txt @@ -0,0 +1 @@ +-- USE_FOO='ON' diff --git a/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD.cmake b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD.cmake new file mode 100644 index 0000000..6db2128 --- /dev/null +++ b/Tests/RunCMake/CMakeDependentOption/Simple-CMP0127-OLD.cmake @@ -0,0 +1,6 @@ +include(CMakeDependentOption) + +set(A1 1) +set(bb 1) +cmake_dependent_option(USE_FOO "Use Foo" ON "A1;bb" OFF) +message(STATUS "USE_FOO='${USE_FOO}'") |