From 1046a61cfd3a586e650d28b74b3bc0ff0dee4d86 Mon Sep 17 00:00:00 2001 From: Craig Scott Date: Sat, 5 Nov 2022 17:16:24 +1100 Subject: Help: clean up and clarify block() and return() --- Help/command/block.rst | 31 +++++++++--------- Help/command/continue.rst | 6 ++-- Help/command/return.rst | 81 ++++++++++++++++++++++++++++++++++------------- 3 files changed, 78 insertions(+), 40 deletions(-) diff --git a/Help/command/block.rst b/Help/command/block.rst index 9d37deb..dfd60d4 100644 --- a/Help/command/block.rst +++ b/Help/command/block.rst @@ -7,14 +7,14 @@ Evaluate a group of commands with a dedicated variable and/or policy scope. .. code-block:: cmake - block([SCOPE_FOR (POLICIES|VARIABLES)] [PROPAGATE ...]) + block([SCOPE_FOR [POLICIES] [VARIABLES] ] [PROPAGATE ...]) endblock() All commands between ``block()`` and the matching :command:`endblock` are recorded without being invoked. Once the :command:`endblock` is evaluated, the -recorded list of commands is invoked inside the requested scopes, and, finally, -the scopes created by ``block()`` command are removed. +recorded list of commands is invoked inside the requested scopes, then the +scopes created by the ``block()`` command are removed. ``SCOPE_FOR`` Specify which scopes must be created. @@ -33,28 +33,29 @@ the scopes created by ``block()`` command are removed. block(SCOPE_FOR VARIABLES POLICIES) ``PROPAGATE`` - When a variable scope is created by :command:`block` command, this option - set or unset the specified variables in the parent scope. This is equivalent - to :command:`set(PARENT_SCOPE)` or :command:`unset(PARENT_SCOPE)` commands. + When a variable scope is created by the :command:`block` command, this + option sets or unsets the specified variables in the parent scope. This is + equivalent to :command:`set(PARENT_SCOPE)` or :command:`unset(PARENT_SCOPE)` + commands. .. code-block:: cmake - set(VAR1 "INIT1") - set(VAR2 "INIT2") + set(var1 "INIT1") + set(var2 "INIT2") - block(PROPAGATE VAR1 VAR2) - set(VAR1 "VALUE1") - unset(VAR2) + block(PROPAGATE var1 var2) + set(var1 "VALUE1") + unset(var2) endblock() - # here, VAR1 holds value VALUE1 and VAR2 is unset + # Now var1 holds VALUE1, and var2 is unset This option is only allowed when a variable scope is created. An error will be raised in the other cases. -When the ``block`` is local to a :command:`foreach` or :command:`while` -command, the commands :command:`break` and :command:`continue` can be used -inside this block. +When the ``block()`` is inside a :command:`foreach` or :command:`while` +command, the :command:`break` and :command:`continue` commands can be used +inside the block. .. code-block:: cmake diff --git a/Help/command/continue.rst b/Help/command/continue.rst index f62802e..e8012ee 100644 --- a/Help/command/continue.rst +++ b/Help/command/continue.rst @@ -9,8 +9,8 @@ Continue to the top of enclosing foreach or while loop. continue() -The ``continue`` command allows a cmake script to abort the rest of a block -in a :command:`foreach` or :command:`while` loop, and start at the top of -the next iteration. +The ``continue()`` command allows a cmake script to abort the rest of the +current iteration of a :command:`foreach` or :command:`while` loop, and start +at the top of the next iteration. See also the :command:`break` command. diff --git a/Help/command/return.rst b/Help/command/return.rst index 029fd05..3013b52 100644 --- a/Help/command/return.rst +++ b/Help/command/return.rst @@ -7,46 +7,83 @@ Return from a file, directory or function. return([PROPAGATE ...]) -Returns from a file, directory or function. When this command is -encountered in an included file (via :command:`include` or +When this command is encountered in an included file (via :command:`include` or :command:`find_package`), it causes processing of the current file to stop and control is returned to the including file. If it is encountered in a -file which is not included by another file, e.g. a ``CMakeLists.txt``, +file which is not included by another file, e.g. a ``CMakeLists.txt``, deferred calls scheduled by :command:`cmake_language(DEFER)` are invoked and -control is returned to the parent directory if there is one. If return is -called in a function, control is returned to the caller of the function. +control is returned to the parent directory if there is one. + +If ``return()`` is called in a function, control is returned to the caller +of that function. Note that a :command:`macro`, unlike a :command:`function`, +is expanded in place and therefore cannot handle ``return()``. + +Policy :policy:`CMP0140` controls the behavior regarding the arguments of the +command. All arguments are ignored unless that policy is set to ``NEW``. ``PROPAGATE`` .. versionadded:: 3.25 - This option set or unset the specified variables in the parent directory or + This option sets or unsets the specified variables in the parent directory or function caller scope. This is equivalent to :command:`set(PARENT_SCOPE)` or - :command:`unset(PARENT_SCOPE)` commands. + :command:`unset(PARENT_SCOPE)` commands, except for the way it interacts + with the :command:`block` command, as described below. - The option ``PROPAGATE`` can be very useful in conjunction with the - :command:`block` command because the :command:`return` will cross over - various scopes created by the :command:`block` commands. + The ``PROPAGATE`` option can be very useful in conjunction with the + :command:`block` command. A :command:`return` will propagate the + specified variables through any enclosing block scopes created by the + :command:`block` commands. Inside a function, this ensures the variables + are propagated to the function's caller, regardless of any blocks within + the function. If not inside a function, it ensures the variables are + propagated to the parent file or directory scope. For example: .. code-block:: cmake + :caption: CMakeLists.txt + + cmake_version_required(VERSION 3.25) + project(example) + + set(var1 "top-value") + + block(SCOPE_FOR VARIABLES) + add_subdirectory(subDir) + # var1 has the value "block-nested" + endblock() - function(MULTI_SCOPES RESULT_VARIABLE) + # var1 has the value "top-value" + + .. code-block:: cmake + :caption: subDir/CMakeLists.txt + + function(multi_scopes result_var1 result_var2) block(SCOPE_FOR VARIABLES) - # here set(PARENT_SCOPE) is not usable because it will not set the - # variable in the caller scope but in the parent scope of the block() - set(${RESULT_VARIABLE} "new-value") - return(PROPAGATE ${RESULT_VARIABLE}) + # This would only propagate out of the immediate block, not to + # the caller of the function. + #set(${result_var1} "new-value" PARENT_SCOPE) + #unset(${result_var2} PARENT_SCOPE) + + # This propagates the variables through the enclosing block and + # out to the caller of the function. + set(${result_var1} "new-value") + unset(${result_var2}) + return(PROPAGATE ${result_var1} ${result_var2}) endblock() endfunction() - set(MY_VAR "initial-value") - multi_scopes(MY_VAR) - # here MY_VAR will holds "new-value" + set(var1 "some-value") + set(var2 "another-value") -Policy :policy:`CMP0140` controls the behavior regarding the arguments of the -command. + multi_scopes(var1 var2) + # Now var1 will hold "new-value" and var2 will be unset -Note that a :command:`macro `, unlike a :command:`function `, -is expanded in place and therefore cannot handle ``return()``. + block(SCOPE_FOR VARIABLES) + # This return() will set var1 in the directory scope that included us + # via add_subdirectory(). The surrounding block() here does not limit + # propagation to the current file, but the block() in the parent + # directory scope does prevent propagation going any further. + set(var1 "block-nested") + return(PROPAGATE var1) + endblock() See Also ^^^^^^^^ -- cgit v0.12